private void UpdateParticleTextures(int textureId)
        {
            // m_SpriteID contains the previous id, update all of the textures that are still using it
            Particle.Texture newTexture = m_TexDefs[textureId];

            for (int i = 0; i < m_SysDefs.Count; i++)
            {
                Particle.System.Def sysDef = m_SysDefs[i];

                // main texture
                Particle.MainInfo info = sysDef.m_MainInfo;
                if (info.m_Sprite.m_SpriteID == textureId)
                {
                    info.m_Sprite = newTexture;
                }

                // texseq textures
                if (sysDef.m_TexSeq != null)
                {
                    Particle.TextureSequence texSeq = sysDef.m_TexSeq;
                    for (int j = 0; j < texSeq.m_Sprites.Length; j++)
                    {
                        if (texSeq.m_Sprites[j] != null && texSeq.m_Sprites[j].m_SpriteID == textureId)
                        {
                            texSeq.m_Sprites[j] = newTexture;
                        }
                    }
                }

                // glitter texture
                if (sysDef.m_Glitter != null)
                {
                    Particle.Glitter glitter = sysDef.m_Glitter;
                    if (glitter.m_Sprite.m_SpriteID == textureId)
                    {
                        glitter.m_Sprite = newTexture;
                    }
                }
            }
        }
        bool CanTextureBeRemoved(int textureId)
        {
            for (int i = 0; i < m_SysDefs.Count; i++)
            {
                Particle.System.Def sysDef = m_SysDefs[i];

                // main texture
                Particle.MainInfo info = sysDef.m_MainInfo;
                if (m_TexDefs.IndexOf(info.m_Sprite) == textureId)
                {
                    return(false);
                }

                // texseq textures
                if (sysDef.m_TexSeq != null)
                {
                    Particle.TextureSequence texSeq = sysDef.m_TexSeq;
                    for (int j = 0; j < texSeq.m_Sprites.Length; j++)
                    {
                        if (texSeq.m_Sprites[j] != null && m_TexDefs.IndexOf(texSeq.m_Sprites[j]) == textureId)
                        {
                            return(false);
                        }
                    }
                }

                // glitter texture
                if (sysDef.m_Glitter != null)
                {
                    Particle.Glitter glitter = sysDef.m_Glitter;
                    if (m_TexDefs.IndexOf(glitter.m_Sprite) == textureId)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        public static void GenerateProperties(Particle.System.Def def, List <Particle.Texture> textures)
        {
            PropertyTable props = new PropertyTable();

            Particle.MainInfo info = def.m_MainInfo;

            props.AddProperty(new PropertySpec("Spawn Shape", typeof(int), "General", "The shape that the particles spawn from", (int)info.m_SpawnShape, "", typeof(ItemListTypeConverter), new Attribute[] { new ItemListAttribute(new string[] { "Point", "Sphere", "Circle (Randomly)", "Circle (Evenly)", "Ball", "Disc" }.ToList()) }));
            props.AddProperty(new PropertySpec("Draw Mode", typeof(int), "General", "How the particle is drawn on screen", (int)info.m_DrawMode, "", typeof(ItemListTypeConverter), new Attribute[] { new ItemListAttribute(new string[] { "Billboard", "Velocity Stretch", "3D" }.ToList()) }));
            props.AddProperty(new PropertySpec("Plane", typeof(int), "General", "If the spawn shape is a plane (circle or disc), which axis the plane is perpendicular to", (int)info.m_Plane, "", typeof(ItemListTypeConverter), new Attribute[] { new ItemListAttribute(new string[] { "Z", "Y", "X", "System Direction" }.ToList()) }));
            props.AddProperty(new PropertySpec("Rotate", typeof(bool), "General", "Whether the particle can rotate", info.m_Rotate, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Random Initial Angle", typeof(bool), "General", "Whether to use a random initial angle instead of 0°", info.m_RandomInitAng, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Self Destruct", typeof(bool), "General", "Whether the particle system should self destruct. Usually false for long particles, usually true for short particles.", info.m_SelfDestruct, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Follow System", typeof(bool), "General", "Whether the particles should follow their parent system when it moves", info.m_FollowSystem, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Rotate Around Weird Axis", typeof(bool), "General", "If the particles are rendered in 3D, whether to rotate the particles around the weird axis <-1/sqrt(3), -1/sqrt(3), -1/sqrt(3)> instead of <0, 1, 0>.", info.m_WeirdAxis, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Horizontal if 3D", typeof(bool), "General", "If the particle is rendered in 3D, whether the particle should be horizontal and not vertical", info.m_HorzIf3D, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Rate", typeof(float), "General", "The number of particles the system spawns each frame (can be a fraction)", info.m_Rate, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-0x80000, 0x80000, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Distance", typeof(float), "General", "The initial maximum distance from the system's position", info.m_StartHorzDist, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-0x400000, 0x400000, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Direction X", typeof(float), "General", "The direction the system points (It's recommended to normalize the vector)", info.m_Dir.X, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-8, 8, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Direction Y", typeof(float), "General", "The direction the system points (It's recommended to normalize the vector)", info.m_Dir.Y, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-8, 8, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Direction Z", typeof(float), "General", "The direction the system points (It's recommended to normalize the vector)", info.m_Dir.Z, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-8, 8, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Color", typeof(Color), "General", "The main color of the particles", info.m_Color, typeof(ColorTypeEditor), typeof(ColorTypeConverter)));
            props.AddProperty(new PropertySpec("Horizontal Speed", typeof(float), "General", "The initial speed away from the particle system's position", info.m_HorzSpeed, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-0x400000, 0x400000, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Vertical Speed", typeof(float), "General", "The initial speed in the particle system's direction", info.m_VertSpeed, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-0x400000, 0x400000, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Scale", typeof(float), "General", "Half the side length of the particle square", info.m_Scale, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-0x400000, 0x400000, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Horizontal Scale Multiplier", typeof(float), "General", "What the horizontal scale is multiplied by", info.m_HorzScaleMult, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-8, 8, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Minimum Angular Speed", typeof(int), "General", "The minimum angular speed in degrees per frame", info.m_MinAngleSpeed, "", typeof(AngleTypeConverter)));
            props.AddProperty(new PropertySpec("Maximum Angular Speed", typeof(int), "General", "The maximum angular speed in degrees per frame", info.m_MaxAngleSpeed, "", typeof(AngleTypeConverter)));
            props.AddProperty(new PropertySpec("Frames", typeof(int), "General", "The number of frames the particle system can spawn particles", info.m_Frames, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xffff) }));
            props.AddProperty(new PropertySpec("Lifetime", typeof(int), "General", "The number of frames the particle exists for", info.m_Lifetime, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xffff) }));
            props.AddProperty(new PropertySpec("Scale Randomness", typeof(int), "General", "How random the scales of the particles are. Varies between 0 and 255", info.m_ScaleRand, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xff) }));
            props.AddProperty(new PropertySpec("Lifetime Randomness", typeof(int), "General", "How random the lifetimes of the particles are. Varies between 0 and 255", info.m_LifetimeRand, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xff) }));
            props.AddProperty(new PropertySpec("Speed Randomness", typeof(int), "General", "How random the speeds of the particles are. Varies between 0 and 255", info.m_SpeedRand, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xff) }));
            props.AddProperty(new PropertySpec("Period", typeof(int), "General", "One more than the number of frames between particle spawnings.", info.m_SpawnPeriod, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(1, 0xff) }));
            props.AddProperty(new PropertySpec("Opacity", typeof(int), "General", "The opacity of the particles on a scale of 0 to 31", info.m_Alpha, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0x1f) }));
            props.AddProperty(new PropertySpec("Speed Falloff", typeof(int), "General", "Dictates how fast the speed should decelerate or accelerate. 128 is normal speed", info.m_SpeedFalloff, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xff) }));
            props.AddProperty(new PropertySpec("Sprite ID", typeof(int), "General", "The ID of the texture to use", textures.IndexOf(info.m_Sprite), "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, highestTextureID) }));
            props.AddProperty(new PropertySpec("Alternate Length", typeof(int), "General", "An alternate number of frames to use for transitions instead of the lifetime", info.m_AltLength, "", typeof(IntTypeConverter), new Attribute[] { new IntRangeAttribute(0, 0xff) }));
            props.AddProperty(new PropertySpec("Velocity Stretch Factor", typeof(float), "General", "If the particles are velocity stretched, by how much to velocity stretch them", info.m_VelStretchFactor, "", typeof(FloatTypeConverter), new Attribute[] { new FloatRangeAttribute(-8, 8, FloatRangeAttribute.Inclusivity.INCLUDE_FIRST) }));
            props.AddProperty(new PropertySpec("Texture Repeat X", typeof(int), "General", "How much to repeat the texture in the X direction", info.m_LogTexRepeatHorz, "", typeof(ItemListTypeConverter), new Attribute[] { new ItemListAttribute(new string[] { "1", "2", "4", "8" }.ToList()) }));
            props.AddProperty(new PropertySpec("Texture Repeat Y", typeof(int), "General", "How much to repeat the texture in the Y direction", info.m_LogTexRepeatVert, "", typeof(ItemListTypeConverter), new Attribute[] { new ItemListAttribute(new string[] { "1", "2", "4", "8" }.ToList()) }));
            props.AddProperty(new PropertySpec("Has Scale Transition", typeof(bool), "General", "Whether to transition the particles' sizes", def.m_ScaleTrans != null, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Color Transition", typeof(bool), "General", "Whether to transition the particles' colors", def.m_ColorTrans != null, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Alpha Transition", typeof(bool), "General", "Whether to transition the particles' opacities", def.m_AlphaTrans != null, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Texture Sequence", typeof(bool), "General", "Whether to transition the particles' sprites", def.m_TexSeq != null, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Glitter", typeof(bool), "General", "Whether to have particles spawning particles", def.m_Glitter != null, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Acceleration Effect", typeof(bool), "General", "Whether to accelerate the particles", def.m_Effects.FindIndex(x => x is Particle.Acceleration) != -1, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Jitter Effect", typeof(bool), "General", "Whether to have the particles jitter", def.m_Effects.FindIndex(x => x is Particle.Jitter) != -1, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Converge Effect", typeof(bool), "General", "Whether the particles should converge to a point", def.m_Effects.FindIndex(x => x is Particle.Converge) != -1, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Turn Effect", typeof(bool), "General", "Whether to rotate the entire particle system", def.m_Effects.FindIndex(x => x is Particle.Turn) != -1, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Limit Plane Effect", typeof(bool), "General", "Whether to limit the particles' heights (unused and untested)", def.m_Effects.FindIndex(x => x is Particle.LimitPlane) != -1, "", typeof(BoolTypeConverter)));
            props.AddProperty(new PropertySpec("Has Radius Converge Effect", typeof(bool), "General", "Whether the particles should converge to a circle", def.m_Effects.FindIndex(x => x is Particle.RadiusConverge) != -1, "", typeof(BoolTypeConverter)));

            if (def.m_ScaleTrans != null)
            {
                GenerateScaleTransitionProperties(def, textures, props);
            }
            if (def.m_ColorTrans != null)
            {
                GenerateColorTransitionProperties(def, textures, props);
            }
            if (def.m_AlphaTrans != null)
            {
                GenerateAlphaTransitionProperties(def, textures, props);
            }
            if (def.m_TexSeq != null)
            {
                GenerateTextureSequenceProperties(def, textures, props);
            }
            if (def.m_Glitter != null)
            {
                GenerateGlitterProperties(def, textures, props);
            }
            if (def.m_Effects.FindIndex(x => x is Particle.Acceleration) != -1)
            {
                GenerateAccelerationProperties(def, textures, props);
            }
            if (def.m_Effects.FindIndex(x => x is Particle.Jitter) != -1)
            {
                GenerateJitterProperties(def, textures, props);
            }
            if (def.m_Effects.FindIndex(x => x is Particle.Converge) != -1)
            {
                GenerateConvergeProperties(def, textures, props);
            }
            if (def.m_Effects.FindIndex(x => x is Particle.Turn) != -1)
            {
                GenerateTurnProperties(def, textures, props);
            }
            if (def.m_Effects.FindIndex(x => x is Particle.LimitPlane) != -1)
            {
                GenerateLimitPlaneProperties(def, textures, props);
            }
            if (def.m_Effects.FindIndex(x => x is Particle.RadiusConverge) != -1)
            {
                GenerateRadiusConvergeProperties(def, textures, props);
            }

            def.m_Properties = props;
        }