using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace libsecondlife
{
///
/// Particle system specific enumerators, flags and methods.
///
public partial class Primitive
{
///
/// Complete structure for the particle system
///
public struct ParticleSystem
{
///
/// Particle source pattern
///
public enum SourcePattern : byte
{
/// None
None = 0,
/// Drop particles at source position with no force
Drop = 0x01,
/// "Explode" particles in all directions
Explode = 0x02,
/// Particles shoot across a 2D area
Angle = 0x04,
/// Particles shoot across a 3D Cone
AngleCone = 0x08,
/// Inverse of AngleCone (shoot particles everywhere except the 3D cone defined
AngleConeEmpty = 0x10
}
///
/// Particle Data Flags
///
[Flags]
public enum ParticleDataFlags : uint
{
/// None
None = 0,
/// Interpolate color and alpha from start to end
InterpColor = 0x001,
/// Interpolate scale from start to end
InterpScale = 0x002,
/// Bounce particles off sourc Z height
Bounce = 0x004,
/// velocity of particles is dampened toward the simulators wind
Wind = 0x008,
/// Particles follow the source
FollowSrc = 0x010,
/// Particles point towards the direction of source's velocity
FollowVelocity = 0x020,
/// Target of the particles
TargetPos = 0x040,
/// Particles are sent in a straight line
TargetLinear = 0x080,
/// Particles emit a glow
Emissive = 0x100,
/// used for point/grab/touch
Beam = 0x200
}
///
/// Particle Flags Enum
///
[Flags]
public enum ParticleFlags : uint
{
/// None
None = 0,
/// Acceleration and velocity for particles are
/// relative to the object rotation
ObjectRelative = 0x01,
/// Particles use new 'correct' angle parameters
UseNewAngle = 0x02
}
public uint CRC;
/// Particle Flags
/// There appears to be more data packed in to this area
/// for many particle systems. It doesn't appear to be flag values
/// and serialization breaks unless there is a flag for every
/// possible bit so it is left as an unsigned integer
public uint PartFlags;
/// pattern of particles
public SourcePattern Pattern;
/// Maximimum age (in seconds) particle will be displayed (max 30 seconds)
public float MaxAge;
/// Number of seconds, from when the particle source comes into view,
/// or the particle system's creation, that the object will emits particles;
/// after this time period no more particles are emitted
public float StartAge;
/// Area in radians that specify where particles will not be created
public float InnerAngle;
/// Area in radians that will be filled with particles
public float OuterAngle;
/// How often particle burts will occur in seconds
public float BurstRate;
/// Number of meters from center of sourcewhere particles are created
public float BurstRadius;
/// Minimum speed of particle creation
public float BurstSpeedMin;
/// Maximum speed of particle creation
public float BurstSpeedMax;
/// How many particles are generated per burst
public byte BurstPartCount;
/// X/Y/Z Velocity in which particles are emitted
public LLVector3 AngularVelocity;
/// X/Y/Z Acceleration in which particles are emitted
public LLVector3 PartAcceleration;
/// Key of texture used in particle
public LLUUID Texture;
/// Key of target
public LLUUID Target;
/// Flags of particle from
public ParticleDataFlags PartDataFlags;
/// Max Age particle system will emit particles for
public float PartMaxAge;
/// Starting color of particles
public LLColor PartStartColor;
/// Ending color of particles
public LLColor PartEndColor;
/// Starting X size of particle (Min 0, Max 4)
public float PartStartScaleX;
/// Starting Y size of particle (Min 0, Max 4)
public float PartStartScaleY;
/// Ending X size of particle (Min 0, Max 4)
public float PartEndScaleX;
/// Ending Y size of particle (Min 0, Max 4)
public float PartEndScaleY;
///
/// Decodes a byte[] array into a ParticleSystem Object
///
/// ParticleSystem object
/// Start position for BitPacker
public ParticleSystem(byte[] data, int pos)
{
// TODO: Not sure exactly how many bytes we need here, so partial
// (truncated) data will cause an exception to be thrown
if (data.Length > 0)
{
BitPack pack = new BitPack(data, pos);
CRC = pack.UnpackUBits(32);
PartFlags = pack.UnpackUBits(32);
Pattern = (SourcePattern)pack.UnpackByte();
MaxAge = pack.UnpackFixed(false, 8, 8);
StartAge = pack.UnpackFixed(false, 8, 8);
InnerAngle = pack.UnpackFixed(false, 3, 5);
OuterAngle = pack.UnpackFixed(false, 3, 5);
BurstRate = pack.UnpackFixed(false, 8, 8);
BurstRadius = pack.UnpackFixed(false, 8, 8);
BurstSpeedMin = pack.UnpackFixed(false, 8, 8);
BurstSpeedMax = pack.UnpackFixed(false, 8, 8);
BurstPartCount = pack.UnpackByte();
float x = pack.UnpackFixed(true, 8, 7);
float y = pack.UnpackFixed(true, 8, 7);
float z = pack.UnpackFixed(true, 8, 7);
AngularVelocity = new LLVector3(x, y, z);
x = pack.UnpackFixed(true, 8, 7);
y = pack.UnpackFixed(true, 8, 7);
z = pack.UnpackFixed(true, 8, 7);
PartAcceleration = new LLVector3(x, y, z);
Texture = pack.UnpackUUID();
Target = pack.UnpackUUID();
PartDataFlags = (ParticleDataFlags)pack.UnpackUBits(32);
PartMaxAge = pack.UnpackFixed(false, 8, 8);
byte r = pack.UnpackByte();
byte g = pack.UnpackByte();
byte b = pack.UnpackByte();
byte a = pack.UnpackByte();
PartStartColor = new LLColor(r, g, b, a);
r = pack.UnpackByte();
g = pack.UnpackByte();
b = pack.UnpackByte();
a = pack.UnpackByte();
PartEndColor = new LLColor(r, g, b, a);
PartStartScaleX = pack.UnpackFixed(false, 3, 5);
PartStartScaleY = pack.UnpackFixed(false, 3, 5);
PartEndScaleX = pack.UnpackFixed(false, 3, 5);
PartEndScaleY = pack.UnpackFixed(false, 3, 5);
}
else
{
CRC = PartFlags = 0;
Pattern = SourcePattern.None;
MaxAge = StartAge = InnerAngle = OuterAngle = BurstRate = BurstRadius = BurstSpeedMin =
BurstSpeedMax = 0.0f;
BurstPartCount = 0;
AngularVelocity = PartAcceleration = LLVector3.Zero;
Texture = Target = LLUUID.Zero;
PartDataFlags = ParticleDataFlags.None;
PartMaxAge = 0.0f;
PartStartColor = PartEndColor = LLColor.Black;
PartStartScaleX = PartStartScaleY = PartEndScaleX = PartEndScaleY = 0.0f;
}
}
///
/// Generate byte[] array from particle data
///
/// Byte array
public byte[] GetBytes()
{
byte[] bytes = new byte[86];
BitPack pack = new BitPack(bytes, 0);
pack.PackBits(CRC, 32);
pack.PackBits((uint)PartFlags, 32);
pack.PackBits((uint)Pattern, 8);
pack.PackFixed(MaxAge, false, 8, 8);
pack.PackFixed(StartAge, false, 8, 8);
pack.PackFixed(InnerAngle, false, 3, 5);
pack.PackFixed(OuterAngle, false, 3, 5);
pack.PackFixed(BurstRate, false, 8, 8);
pack.PackFixed(BurstRadius, false, 8, 8);
pack.PackFixed(BurstSpeedMin, false, 8, 8);
pack.PackFixed(BurstSpeedMax, false, 8, 8);
pack.PackBits(BurstPartCount, 8);
pack.PackFixed(AngularVelocity.X, true, 8, 7);
pack.PackFixed(AngularVelocity.Y, true, 8, 7);
pack.PackFixed(AngularVelocity.Z, true, 8, 7);
pack.PackFixed(PartAcceleration.X, true, 8, 7);
pack.PackFixed(PartAcceleration.Y, true, 8, 7);
pack.PackFixed(PartAcceleration.Z, true, 8, 7);
pack.PackUUID(Texture);
pack.PackUUID(Target);
pack.PackBits((uint)PartDataFlags, 32);
pack.PackFixed(MaxAge, false, 8, 8);
pack.PackColor(PartStartColor);
pack.PackColor(PartEndColor);
pack.PackFixed(PartStartScaleX, false, 3, 5);
pack.PackFixed(PartStartScaleY, false, 3, 5);
pack.PackFixed(PartEndScaleX, false, 3, 5);
pack.PackFixed(PartEndScaleY, false, 3, 5);
return bytes;
}
}
}
}