corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Collections.Generic;
29 using System.ComponentModel;
30 using OpenMetaverse.StructuredData;
31  
32 namespace OpenMetaverse
33 {
34 /// <summary>
35 /// Particle system specific enumerators, flags and methods.
36 /// </summary>
37 public partial class Primitive
38 {
39 #region Subclasses
40  
41 /// <summary>
42 /// Complete structure for the particle system
43 /// </summary>
44 public struct ParticleSystem
45 {
46 /// <summary>
47 /// Particle source pattern
48 /// </summary>
49 public enum SourcePattern : byte
50 {
51 /// <summary>None</summary>
52 None = 0,
53 /// <summary>Drop particles from source position with no force</summary>
54 Drop = 0x01,
55 /// <summary>"Explode" particles in all directions</summary>
56 Explode = 0x02,
57 /// <summary>Particles shoot across a 2D area</summary>
58 Angle = 0x04,
59 /// <summary>Particles shoot across a 3D Cone</summary>
60 AngleCone = 0x08,
61 /// <summary>Inverse of AngleCone (shoot particles everywhere except the 3D cone defined</summary>
62 AngleConeEmpty = 0x10
63 }
64  
65 /// <summary>
66 /// Particle Data Flags
67 /// </summary>
68 [Flags]
69 public enum ParticleDataFlags : uint
70 {
71 /// <summary>None</summary>
72 None = 0,
73 /// <summary>Interpolate color and alpha from start to end</summary>
74 InterpColor = 0x001,
75 /// <summary>Interpolate scale from start to end</summary>
76 InterpScale = 0x002,
77 /// <summary>Bounce particles off particle sources Z height</summary>
78 Bounce = 0x004,
79 /// <summary>velocity of particles is dampened toward the simulators wind</summary>
80 Wind = 0x008,
81 /// <summary>Particles follow the source</summary>
82 FollowSrc = 0x010,
83 /// <summary>Particles point towards the direction of source's velocity</summary>
84 FollowVelocity = 0x020,
85 /// <summary>Target of the particles</summary>
86 TargetPos = 0x040,
87 /// <summary>Particles are sent in a straight line</summary>
88 TargetLinear = 0x080,
89 /// <summary>Particles emit a glow</summary>
90 Emissive = 0x100,
91 /// <summary>used for point/grab/touch</summary>
92 Beam = 0x200,
93 /// <summary>continuous ribbon particle</summary>
94 Ribbon = 0x400,
95 /// <summary>particle data contains glow</summary>
96 DataGlow = 0x10000,
97 /// <summary>particle data contains blend functions</summary>
98 DataBlend = 0x20000,
99 }
100  
101 /// <summary>
102 /// Particle Flags Enum
103 /// </summary>
104 [Flags]
105 public enum ParticleFlags : uint
106 {
107 /// <summary>None</summary>
108 None = 0,
109 /// <summary>Acceleration and velocity for particles are
110 /// relative to the object rotation</summary>
111 ObjectRelative = 0x01,
112 /// <summary>Particles use new 'correct' angle parameters</summary>
113 UseNewAngle = 0x02
114 }
115  
116 public enum BlendFunc : byte
117 {
118 One = 0,
119 Zero = 1,
120 DestColor = 2,
121 SourceColor = 3,
122 OneMinusDestColor = 4,
123 OneMinusSourceColor = 5,
124 DestAlpha = 6,
125 SourceAlpha = 7,
126 OneMinusDestAlpha = 8,
127 OneMinusSourceAlpha = 9,
128 }
129  
130 public uint CRC;
131 /// <summary>Particle Flags</summary>
132 /// <remarks>There appears to be more data packed in to this area
133 /// for many particle systems. It doesn't appear to be flag values
134 /// and serialization breaks unless there is a flag for every
135 /// possible bit so it is left as an unsigned integer</remarks>
136 public uint PartFlags;
137 /// <summary><seealso cref="T:SourcePattern"/> pattern of particles</summary>
138 public SourcePattern Pattern;
139 /// <summary>A <see langword="float"/> representing the maximimum age (in seconds) particle will be displayed</summary>
140 /// <remarks>Maximum value is 30 seconds</remarks>
141 public float MaxAge;
142 /// <summary>A <see langword="float"/> representing the number of seconds,
143 /// from when the particle source comes into view,
144 /// or the particle system's creation, that the object will emits particles;
145 /// after this time period no more particles are emitted</summary>
146 public float StartAge;
147 /// <summary>A <see langword="float"/> in radians that specifies where particles will not be created</summary>
148 public float InnerAngle;
149 /// <summary>A <see langword="float"/> in radians that specifies where particles will be created</summary>
150 public float OuterAngle;
151 /// <summary>A <see langword="float"/> representing the number of seconds between burts.</summary>
152 public float BurstRate;
153 /// <summary>A <see langword="float"/> representing the number of meters
154 /// around the center of the source where particles will be created.</summary>
155 public float BurstRadius;
156 /// <summary>A <see langword="float"/> representing in seconds, the minimum speed between bursts of new particles
157 /// being emitted</summary>
158 public float BurstSpeedMin;
159 /// <summary>A <see langword="float"/> representing in seconds the maximum speed of new particles being emitted.</summary>
160 public float BurstSpeedMax;
161 /// <summary>A <see langword="byte"/> representing the maximum number of particles emitted per burst</summary>
162 public byte BurstPartCount;
163 /// <summary>A <see cref="T:Vector3"/> which represents the velocity (speed) from the source which particles are emitted</summary>
164 public Vector3 AngularVelocity;
165 /// <summary>A <see cref="T:Vector3"/> which represents the Acceleration from the source which particles are emitted</summary>
166 public Vector3 PartAcceleration;
167 /// <summary>The <see cref="T:UUID"/> Key of the texture displayed on the particle</summary>
168 public UUID Texture;
169 /// <summary>The <see cref="T:UUID"/> Key of the specified target object or avatar particles will follow</summary>
170 public UUID Target;
171 /// <summary>Flags of particle from <seealso cref="T:ParticleDataFlags"/></summary>
172 public ParticleDataFlags PartDataFlags;
173 /// <summary>Max Age particle system will emit particles for</summary>
174 public float PartMaxAge;
175 /// <summary>The <see cref="T:Color4"/> the particle has at the beginning of its lifecycle</summary>
176 public Color4 PartStartColor;
177 /// <summary>The <see cref="T:Color4"/> the particle has at the ending of its lifecycle</summary>
178 public Color4 PartEndColor;
179 /// <summary>A <see langword="float"/> that represents the starting X size of the particle</summary>
180 /// <remarks>Minimum value is 0, maximum value is 4</remarks>
181 public float PartStartScaleX;
182 /// <summary>A <see langword="float"/> that represents the starting Y size of the particle</summary>
183 /// <remarks>Minimum value is 0, maximum value is 4</remarks>
184 public float PartStartScaleY;
185 /// <summary>A <see langword="float"/> that represents the ending X size of the particle</summary>
186 /// <remarks>Minimum value is 0, maximum value is 4</remarks>
187 public float PartEndScaleX;
188 /// <summary>A <see langword="float"/> that represents the ending Y size of the particle</summary>
189 /// <remarks>Minimum value is 0, maximum value is 4</remarks>
190 public float PartEndScaleY;
191  
192 /// <summary>A <see langword="float"/> that represents the start glow value</summary>
193 /// <remarks>Minimum value is 0, maximum value is 1</remarks>
194 public float PartStartGlow;
195 /// <summary>A <see langword="float"/> that represents the end glow value</summary>
196 /// <remarks>Minimum value is 0, maximum value is 1</remarks>
197 public float PartEndGlow;
198  
199 /// <summary>OpenGL blend function to use at particle source</summary>
200 public byte BlendFuncSource;
201 /// <summary>OpenGL blend function to use at particle destination</summary>
202 public byte BlendFuncDest;
203  
204 public const byte MaxDataBlockSize = 98;
205 public const byte LegacyDataBlockSize = 86;
206 public const byte SysDataSize = 68;
207 public const byte PartDataSize = 18;
208  
209 /// <summary>
210 /// Can this particle system be packed in a legacy compatible way
211 /// </summary>
212 /// <returns>True if the particle system doesn't use new particle system features</returns>
213 public bool IsLegacyCompatible()
214 {
215 return !HasGlow() && !HasBlendFunc();
216 }
217  
218 public bool HasGlow()
219 {
220 return PartStartGlow > 0f || PartEndGlow > 0f;
221 }
222  
223 public bool HasBlendFunc()
224 {
225 return BlendFuncSource != (byte)BlendFunc.SourceAlpha || BlendFuncDest != (byte)BlendFunc.OneMinusSourceAlpha;
226 }
227  
228 /// <summary>
229 /// Decodes a byte[] array into a ParticleSystem Object
230 /// </summary>
231 /// <param name="data">ParticleSystem object</param>
232 /// <param name="pos">Start position for BitPacker</param>
233 public ParticleSystem(byte[] data, int pos)
234 {
235 PartStartGlow = 0f;
236 PartEndGlow = 0f;
237 BlendFuncSource = (byte)BlendFunc.SourceAlpha;
238 BlendFuncDest = (byte)BlendFunc.OneMinusSourceAlpha;
239  
240 CRC = PartFlags = 0;
241 Pattern = SourcePattern.None;
242 MaxAge = StartAge = InnerAngle = OuterAngle = BurstRate = BurstRadius = BurstSpeedMin =
243 BurstSpeedMax = 0.0f;
244 BurstPartCount = 0;
245 AngularVelocity = PartAcceleration = Vector3.Zero;
246 Texture = Target = UUID.Zero;
247 PartDataFlags = ParticleDataFlags.None;
248 PartMaxAge = 0.0f;
249 PartStartColor = PartEndColor = Color4.Black;
250 PartStartScaleX = PartStartScaleY = PartEndScaleX = PartEndScaleY = 0.0f;
251  
252 int size = data.Length - pos;
253 BitPack pack = new BitPack(data, pos);
254  
255 if (size == LegacyDataBlockSize)
256 {
257 UnpackSystem(ref pack);
258 UnpackLegacyData(ref pack);
259 }
260 else if (size > LegacyDataBlockSize && size <= MaxDataBlockSize)
261 {
262 int sysSize = pack.UnpackBits(32);
263 if (sysSize != SysDataSize) return; // unkown particle system data size
264 UnpackSystem(ref pack);
265 int dataSize = pack.UnpackBits(32);
266 UnpackLegacyData(ref pack);
267  
268  
269 if ((PartDataFlags & ParticleDataFlags.DataGlow) == ParticleDataFlags.DataGlow)
270 {
271 if (pack.Data.Length - pack.BytePos < 2) return;
272 uint glow = pack.UnpackUBits(8);
273 PartStartGlow = glow / 255f;
274 glow = pack.UnpackUBits(8);
275 PartEndGlow = glow / 255f;
276 }
277  
278 if ((PartDataFlags & ParticleDataFlags.DataBlend) == ParticleDataFlags.DataBlend)
279 {
280 if (pack.Data.Length - pack.BytePos < 2) return;
281 BlendFuncSource = (byte)pack.UnpackUBits(8);
282 BlendFuncDest = (byte)pack.UnpackUBits(8);
283 }
284  
285 }
286 }
287  
288 void UnpackSystem(ref BitPack pack)
289 {
290 CRC = pack.UnpackUBits(32);
291 PartFlags = pack.UnpackUBits(32);
292 Pattern = (SourcePattern)pack.UnpackByte();
293 MaxAge = pack.UnpackFixed(false, 8, 8);
294 StartAge = pack.UnpackFixed(false, 8, 8);
295 InnerAngle = pack.UnpackFixed(false, 3, 5);
296 OuterAngle = pack.UnpackFixed(false, 3, 5);
297 BurstRate = pack.UnpackFixed(false, 8, 8);
298 BurstRadius = pack.UnpackFixed(false, 8, 8);
299 BurstSpeedMin = pack.UnpackFixed(false, 8, 8);
300 BurstSpeedMax = pack.UnpackFixed(false, 8, 8);
301 BurstPartCount = pack.UnpackByte();
302 float x = pack.UnpackFixed(true, 8, 7);
303 float y = pack.UnpackFixed(true, 8, 7);
304 float z = pack.UnpackFixed(true, 8, 7);
305 AngularVelocity = new Vector3(x, y, z);
306 x = pack.UnpackFixed(true, 8, 7);
307 y = pack.UnpackFixed(true, 8, 7);
308 z = pack.UnpackFixed(true, 8, 7);
309 PartAcceleration = new Vector3(x, y, z);
310 Texture = pack.UnpackUUID();
311 Target = pack.UnpackUUID();
312 }
313  
314 void UnpackLegacyData(ref BitPack pack)
315 {
316 PartDataFlags = (ParticleDataFlags)pack.UnpackUBits(32);
317 PartMaxAge = pack.UnpackFixed(false, 8, 8);
318 byte r = pack.UnpackByte();
319 byte g = pack.UnpackByte();
320 byte b = pack.UnpackByte();
321 byte a = pack.UnpackByte();
322 PartStartColor = new Color4(r, g, b, a);
323 r = pack.UnpackByte();
324 g = pack.UnpackByte();
325 b = pack.UnpackByte();
326 a = pack.UnpackByte();
327 PartEndColor = new Color4(r, g, b, a);
328 PartStartScaleX = pack.UnpackFixed(false, 3, 5);
329 PartStartScaleY = pack.UnpackFixed(false, 3, 5);
330 PartEndScaleX = pack.UnpackFixed(false, 3, 5);
331 PartEndScaleY = pack.UnpackFixed(false, 3, 5);
332 }
333  
334 /// <summary>
335 /// Generate byte[] array from particle data
336 /// </summary>
337 /// <returns>Byte array</returns>
338 public byte[] GetBytes()
339 {
340 int size = LegacyDataBlockSize;
341 if (!IsLegacyCompatible()) size += 8; // two new ints for size
342 if (HasGlow()) size += 2; // two bytes for start and end glow
343 if (HasBlendFunc()) size += 2; // two bytes for start end end blend function
344  
345 byte[] bytes = new byte[size];
346 BitPack pack = new BitPack(bytes, 0);
347  
348 if (IsLegacyCompatible())
349 {
350 PackSystemBytes(ref pack);
351 PackLegacyData(ref pack);
352 }
353 else
354 {
355 if (HasGlow()) PartDataFlags |= ParticleDataFlags.DataGlow;
356 if (HasBlendFunc()) PartDataFlags |= ParticleDataFlags.DataBlend;
357  
358 pack.PackBits(SysDataSize, 32);
359 PackSystemBytes(ref pack);
360 int partSize = PartDataSize;
361 if (HasGlow()) partSize += 2; // two bytes for start and end glow
362 if (HasBlendFunc()) partSize += 2; // two bytes for start end end blend function
363 pack.PackBits(partSize, 32);
364 PackLegacyData(ref pack);
365  
366 if (HasGlow())
367 {
368 pack.PackBits((byte)(PartStartGlow * 255f), 8);
369 pack.PackBits((byte)(PartEndGlow * 255f), 8);
370 }
371  
372 if (HasBlendFunc())
373 {
374 pack.PackBits(BlendFuncSource, 8);
375 pack.PackBits(BlendFuncDest, 8);
376 }
377 }
378  
379 return bytes;
380 }
381  
382 void PackSystemBytes(ref BitPack pack)
383 {
384 pack.PackBits(CRC, 32);
385 pack.PackBits((uint)PartFlags, 32);
386 pack.PackBits((uint)Pattern, 8);
387 pack.PackFixed(MaxAge, false, 8, 8);
388 pack.PackFixed(StartAge, false, 8, 8);
389 pack.PackFixed(InnerAngle, false, 3, 5);
390 pack.PackFixed(OuterAngle, false, 3, 5);
391 pack.PackFixed(BurstRate, false, 8, 8);
392 pack.PackFixed(BurstRadius, false, 8, 8);
393 pack.PackFixed(BurstSpeedMin, false, 8, 8);
394 pack.PackFixed(BurstSpeedMax, false, 8, 8);
395 pack.PackBits(BurstPartCount, 8);
396 pack.PackFixed(AngularVelocity.X, true, 8, 7);
397 pack.PackFixed(AngularVelocity.Y, true, 8, 7);
398 pack.PackFixed(AngularVelocity.Z, true, 8, 7);
399 pack.PackFixed(PartAcceleration.X, true, 8, 7);
400 pack.PackFixed(PartAcceleration.Y, true, 8, 7);
401 pack.PackFixed(PartAcceleration.Z, true, 8, 7);
402 pack.PackUUID(Texture);
403 pack.PackUUID(Target);
404 }
405  
406 void PackLegacyData(ref BitPack pack)
407 {
408 pack.PackBits((uint)PartDataFlags, 32);
409 pack.PackFixed(PartMaxAge, false, 8, 8);
410 pack.PackColor(PartStartColor);
411 pack.PackColor(PartEndColor);
412 pack.PackFixed(PartStartScaleX, false, 3, 5);
413 pack.PackFixed(PartStartScaleY, false, 3, 5);
414 pack.PackFixed(PartEndScaleX, false, 3, 5);
415 pack.PackFixed(PartEndScaleY, false, 3, 5);
416 }
417  
418 public OSD GetOSD()
419 {
420 OSDMap map = new OSDMap();
421  
422 map["crc"] = OSD.FromInteger(CRC);
423 map["part_flags"] = OSD.FromInteger(PartFlags);
424 map["pattern"] = OSD.FromInteger((int)Pattern);
425 map["max_age"] = OSD.FromReal(MaxAge);
426 map["start_age"] = OSD.FromReal(StartAge);
427 map["inner_angle"] = OSD.FromReal(InnerAngle);
428 map["outer_angle"] = OSD.FromReal(OuterAngle);
429 map["burst_rate"] = OSD.FromReal(BurstRate);
430 map["burst_radius"] = OSD.FromReal(BurstRadius);
431 map["burst_speed_min"] = OSD.FromReal(BurstSpeedMin);
432 map["burst_speed_max"] = OSD.FromReal(BurstSpeedMax);
433 map["burst_part_count"] = OSD.FromInteger(BurstPartCount);
434 map["ang_velocity"] = OSD.FromVector3(AngularVelocity);
435 map["part_acceleration"] = OSD.FromVector3(PartAcceleration);
436 map["texture"] = OSD.FromUUID(Texture);
437 map["target"] = OSD.FromUUID(Target);
438  
439 map["part_data_flags"] = (uint)PartDataFlags;
440 map["part_max_age"] = PartMaxAge;
441 map["part_start_color"] = PartStartColor;
442 map["part_end_color"] = PartEndColor;
443 map["part_start_scale"] = new Vector3(PartStartScaleX, PartStartScaleY, 0f);
444 map["part_end_scale"] = new Vector3(PartEndScaleX, PartEndScaleY, 0f);
445  
446 if (HasGlow())
447 {
448 map["part_start_glow"] = PartStartGlow;
449 map["part_end_glow"] = PartEndGlow;
450 }
451  
452 if (HasBlendFunc())
453 {
454 map["blendfunc_source"] = BlendFuncSource;
455 map["blendfunc_dest"] = BlendFuncDest;
456 }
457  
458 return map;
459 }
460  
461 public static ParticleSystem FromOSD(OSD osd)
462 {
463 ParticleSystem partSys = new ParticleSystem();
464 OSDMap map = osd as OSDMap;
465  
466 if (map != null)
467 {
468 partSys.CRC = map["crc"].AsUInteger();
469 partSys.PartFlags = map["part_flags"].AsUInteger();
470 partSys.Pattern = (SourcePattern)map["pattern"].AsInteger();
471 partSys.MaxAge = (float)map["max_age"].AsReal();
472 partSys.StartAge = (float)map["start_age"].AsReal();
473 partSys.InnerAngle = (float)map["inner_angle"].AsReal();
474 partSys.OuterAngle = (float)map["outer_angle"].AsReal();
475 partSys.BurstRate = (float)map["burst_rate"].AsReal();
476 partSys.BurstRadius = (float)map["burst_radius"].AsReal();
477 partSys.BurstSpeedMin = (float)map["burst_speed_min"].AsReal();
478 partSys.BurstSpeedMax = (float)map["burst_speed_max"].AsReal();
479 partSys.BurstPartCount = (byte)map["burst_part_count"].AsInteger();
480 partSys.AngularVelocity = map["ang_velocity"].AsVector3();
481 partSys.PartAcceleration = map["part_acceleration"].AsVector3();
482 partSys.Texture = map["texture"].AsUUID();
483 partSys.Target = map["target"].AsUUID();
484  
485 partSys.PartDataFlags = (ParticleDataFlags)map["part_data_flags"].AsUInteger();
486 partSys.PartMaxAge = map["part_max_age"];
487 partSys.PartStartColor = map["part_start_color"];
488 partSys.PartEndColor = map["part_end_color"];
489 Vector3 ss = map["part_start_scale"];
490 partSys.PartStartScaleX = ss.X;
491 partSys.PartStartScaleY = ss.Y;
492 Vector3 es = map["part_end_scale"];
493 partSys.PartEndScaleX = es.X;
494 partSys.PartEndScaleY = es.Y;
495  
496 if (map.ContainsKey("part_start_glow"))
497 {
498 partSys.PartStartGlow = map["part_start_glow"];
499 partSys.PartEndGlow = map["part_end_glow"];
500 }
501  
502 if (map.ContainsKey("blendfunc_source"))
503 {
504 partSys.BlendFuncSource = (byte)map["blendfunc_source"].AsUInteger();
505 partSys.BlendFuncDest = (byte)map["blendfunc_dest"].AsUInteger();
506 }
507 }
508  
509 return partSys;
510 }
511 }
512  
513 #endregion Subclasses
514  
515 #region Public Members
516  
517 /// <summary></summary>
518 public ParticleSystem ParticleSys;
519  
520 #endregion Public Members
521 }
522 }