corrade-vassal – Blame information for rev 1
?pathlinks?
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 OpenMetaverse.StructuredData; |
||
30 | |||
31 | namespace OpenMetaverse |
||
32 | { |
||
33 | public partial class Primitive : IEquatable<Primitive> |
||
34 | { |
||
35 | // Used for packing and unpacking parameters |
||
36 | protected const float CUT_QUANTA = 0.00002f; |
||
37 | protected const float SCALE_QUANTA = 0.01f; |
||
38 | protected const float SHEAR_QUANTA = 0.01f; |
||
39 | protected const float TAPER_QUANTA = 0.01f; |
||
40 | protected const float REV_QUANTA = 0.015f; |
||
41 | protected const float HOLLOW_QUANTA = 0.00002f; |
||
42 | |||
43 | #region Subclasses |
||
44 | |||
45 | /// <summary> |
||
46 | /// Parameters used to construct a visual representation of a primitive |
||
47 | /// </summary> |
||
48 | public struct ConstructionData |
||
49 | { |
||
50 | private const byte PROFILE_MASK = 0x0F; |
||
51 | private const byte HOLE_MASK = 0xF0; |
||
52 | |||
53 | /// <summary></summary> |
||
54 | public byte profileCurve; |
||
55 | /// <summary></summary> |
||
56 | public PathCurve PathCurve; |
||
57 | /// <summary></summary> |
||
58 | public float PathEnd; |
||
59 | /// <summary></summary> |
||
60 | public float PathRadiusOffset; |
||
61 | /// <summary></summary> |
||
62 | public float PathSkew; |
||
63 | /// <summary></summary> |
||
64 | public float PathScaleX; |
||
65 | /// <summary></summary> |
||
66 | public float PathScaleY; |
||
67 | /// <summary></summary> |
||
68 | public float PathShearX; |
||
69 | /// <summary></summary> |
||
70 | public float PathShearY; |
||
71 | /// <summary></summary> |
||
72 | public float PathTaperX; |
||
73 | /// <summary></summary> |
||
74 | public float PathTaperY; |
||
75 | /// <summary></summary> |
||
76 | public float PathBegin; |
||
77 | /// <summary></summary> |
||
78 | public float PathTwist; |
||
79 | /// <summary></summary> |
||
80 | public float PathTwistBegin; |
||
81 | /// <summary></summary> |
||
82 | public float PathRevolutions; |
||
83 | /// <summary></summary> |
||
84 | public float ProfileBegin; |
||
85 | /// <summary></summary> |
||
86 | public float ProfileEnd; |
||
87 | /// <summary></summary> |
||
88 | public float ProfileHollow; |
||
89 | |||
90 | /// <summary></summary> |
||
91 | public Material Material; |
||
92 | /// <summary></summary> |
||
93 | public byte State; |
||
94 | /// <summary></summary> |
||
95 | public PCode PCode; |
||
96 | |||
97 | #region Properties |
||
98 | |||
99 | /// <summary>Attachment point to an avatar</summary> |
||
100 | public AttachmentPoint AttachmentPoint |
||
101 | { |
||
102 | get { return (AttachmentPoint)Utils.SwapWords(State); } |
||
103 | set { State = (byte)Utils.SwapWords((byte)value); } |
||
104 | } |
||
105 | |||
106 | /// <summary></summary> |
||
107 | public ProfileCurve ProfileCurve |
||
108 | { |
||
109 | get { return (ProfileCurve)(profileCurve & PROFILE_MASK); } |
||
110 | set |
||
111 | { |
||
112 | profileCurve &= HOLE_MASK; |
||
113 | profileCurve |= (byte)value; |
||
114 | } |
||
115 | } |
||
116 | |||
117 | /// <summary></summary> |
||
118 | public HoleType ProfileHole |
||
119 | { |
||
120 | get { return (HoleType)(profileCurve & HOLE_MASK); } |
||
121 | set |
||
122 | { |
||
123 | profileCurve &= PROFILE_MASK; |
||
124 | profileCurve |= (byte)value; |
||
125 | } |
||
126 | } |
||
127 | |||
128 | /// <summary></summary> |
||
129 | public Vector2 PathBeginScale |
||
130 | { |
||
131 | get |
||
132 | { |
||
133 | Vector2 begin = new Vector2(1f, 1f); |
||
134 | if (PathScaleX > 1f) |
||
135 | begin.X = 2f - PathScaleX; |
||
136 | if (PathScaleY > 1f) |
||
137 | begin.Y = 2f - PathScaleY; |
||
138 | return begin; |
||
139 | } |
||
140 | } |
||
141 | |||
142 | /// <summary></summary> |
||
143 | public Vector2 PathEndScale |
||
144 | { |
||
145 | get |
||
146 | { |
||
147 | Vector2 end = new Vector2(1f, 1f); |
||
148 | if (PathScaleX < 1f) |
||
149 | end.X = PathScaleX; |
||
150 | if (PathScaleY < 1f) |
||
151 | end.Y = PathScaleY; |
||
152 | return end; |
||
153 | } |
||
154 | } |
||
155 | |||
156 | #endregion Properties |
||
157 | |||
158 | /// <summary> |
||
159 | /// Calculdates hash code for prim construction data |
||
160 | /// </summary> |
||
161 | /// <returns>The has</returns> |
||
162 | public override int GetHashCode() |
||
163 | { |
||
164 | return profileCurve.GetHashCode() |
||
165 | ^ PathCurve.GetHashCode() |
||
166 | ^ PathEnd.GetHashCode() |
||
167 | ^ PathRadiusOffset.GetHashCode() |
||
168 | ^ PathSkew.GetHashCode() |
||
169 | ^ PathScaleX.GetHashCode() |
||
170 | ^ PathScaleY.GetHashCode() |
||
171 | ^ PathShearX.GetHashCode() |
||
172 | ^ PathShearY.GetHashCode() |
||
173 | ^ PathTaperX.GetHashCode() |
||
174 | ^ PathTaperY.GetHashCode() |
||
175 | ^ PathBegin.GetHashCode() |
||
176 | ^ PathTwist.GetHashCode() |
||
177 | ^ PathTwistBegin.GetHashCode() |
||
178 | ^ PathRevolutions.GetHashCode() |
||
179 | ^ ProfileBegin.GetHashCode() |
||
180 | ^ ProfileEnd.GetHashCode() |
||
181 | ^ ProfileHollow.GetHashCode() |
||
182 | ^ Material.GetHashCode() |
||
183 | ^ State.GetHashCode() |
||
184 | ^ PCode.GetHashCode(); |
||
185 | } |
||
186 | } |
||
187 | |||
188 | /// <summary> |
||
189 | /// Information on the flexible properties of a primitive |
||
190 | /// </summary> |
||
191 | public class FlexibleData |
||
192 | { |
||
193 | /// <summary></summary> |
||
194 | public int Softness; |
||
195 | /// <summary></summary> |
||
196 | public float Gravity; |
||
197 | /// <summary></summary> |
||
198 | public float Drag; |
||
199 | /// <summary></summary> |
||
200 | public float Wind; |
||
201 | /// <summary></summary> |
||
202 | public float Tension; |
||
203 | /// <summary></summary> |
||
204 | public Vector3 Force; |
||
205 | |||
206 | /// <summary> |
||
207 | /// Default constructor |
||
208 | /// </summary> |
||
209 | public FlexibleData() |
||
210 | { |
||
211 | } |
||
212 | |||
213 | /// <summary> |
||
214 | /// |
||
215 | /// </summary> |
||
216 | /// <param name="data"></param> |
||
217 | /// <param name="pos"></param> |
||
218 | public FlexibleData(byte[] data, int pos) |
||
219 | { |
||
220 | if (data.Length >= 5) |
||
221 | { |
||
222 | Softness = ((data[pos] & 0x80) >> 6) | ((data[pos + 1] & 0x80) >> 7); |
||
223 | |||
224 | Tension = (float)(data[pos++] & 0x7F) / 10.0f; |
||
225 | Drag = (float)(data[pos++] & 0x7F) / 10.0f; |
||
226 | Gravity = (float)(data[pos++] / 10.0f) - 10.0f; |
||
227 | Wind = (float)data[pos++] / 10.0f; |
||
228 | Force = new Vector3(data, pos); |
||
229 | } |
||
230 | else |
||
231 | { |
||
232 | Softness = 0; |
||
233 | |||
234 | Tension = 0.0f; |
||
235 | Drag = 0.0f; |
||
236 | Gravity = 0.0f; |
||
237 | Wind = 0.0f; |
||
238 | Force = Vector3.Zero; |
||
239 | } |
||
240 | } |
||
241 | |||
242 | /// <summary> |
||
243 | /// |
||
244 | /// </summary> |
||
245 | /// <returns></returns> |
||
246 | public byte[] GetBytes() |
||
247 | { |
||
248 | byte[] data = new byte[16]; |
||
249 | int i = 0; |
||
250 | |||
251 | // Softness is packed in the upper bits of tension and drag |
||
252 | data[i] = (byte)((Softness & 2) << 6); |
||
253 | data[i + 1] = (byte)((Softness & 1) << 7); |
||
254 | |||
255 | data[i++] |= (byte)((byte)(Tension * 10.01f) & 0x7F); |
||
256 | data[i++] |= (byte)((byte)(Drag * 10.01f) & 0x7F); |
||
257 | data[i++] = (byte)((Gravity + 10.0f) * 10.01f); |
||
258 | data[i++] = (byte)(Wind * 10.01f); |
||
259 | |||
260 | Force.GetBytes().CopyTo(data, i); |
||
261 | |||
262 | return data; |
||
263 | } |
||
264 | |||
265 | /// <summary> |
||
266 | /// |
||
267 | /// </summary> |
||
268 | /// <returns></returns> |
||
269 | public OSD GetOSD() |
||
270 | { |
||
271 | OSDMap map = new OSDMap(); |
||
272 | |||
273 | map["simulate_lod"] = OSD.FromInteger(Softness); |
||
274 | map["gravity"] = OSD.FromReal(Gravity); |
||
275 | map["air_friction"] = OSD.FromReal(Drag); |
||
276 | map["wind_sensitivity"] = OSD.FromReal(Wind); |
||
277 | map["tension"] = OSD.FromReal(Tension); |
||
278 | map["user_force"] = OSD.FromVector3(Force); |
||
279 | |||
280 | return map; |
||
281 | } |
||
282 | |||
283 | public static FlexibleData FromOSD(OSD osd) |
||
284 | { |
||
285 | FlexibleData flex = new FlexibleData(); |
||
286 | |||
287 | if (osd.Type == OSDType.Map) |
||
288 | { |
||
289 | OSDMap map = (OSDMap)osd; |
||
290 | |||
291 | flex.Softness = map["simulate_lod"].AsInteger(); |
||
292 | flex.Gravity = (float)map["gravity"].AsReal(); |
||
293 | flex.Drag = (float)map["air_friction"].AsReal(); |
||
294 | flex.Wind = (float)map["wind_sensitivity"].AsReal(); |
||
295 | flex.Tension = (float)map["tension"].AsReal(); |
||
296 | flex.Force = ((OSDArray)map["user_force"]).AsVector3(); |
||
297 | } |
||
298 | |||
299 | return flex; |
||
300 | } |
||
301 | |||
302 | public override int GetHashCode() |
||
303 | { |
||
304 | return |
||
305 | Softness.GetHashCode() ^ |
||
306 | Gravity.GetHashCode() ^ |
||
307 | Drag.GetHashCode() ^ |
||
308 | Wind.GetHashCode() ^ |
||
309 | Tension.GetHashCode() ^ |
||
310 | Force.GetHashCode(); |
||
311 | } |
||
312 | } |
||
313 | |||
314 | /// <summary> |
||
315 | /// Information on the light properties of a primitive |
||
316 | /// </summary> |
||
317 | public class LightData |
||
318 | { |
||
319 | /// <summary></summary> |
||
320 | public Color4 Color; |
||
321 | /// <summary></summary> |
||
322 | public float Intensity; |
||
323 | /// <summary></summary> |
||
324 | public float Radius; |
||
325 | /// <summary></summary> |
||
326 | public float Cutoff; |
||
327 | /// <summary></summary> |
||
328 | public float Falloff; |
||
329 | |||
330 | /// <summary> |
||
331 | /// Default constructor |
||
332 | /// </summary> |
||
333 | public LightData() |
||
334 | { |
||
335 | } |
||
336 | |||
337 | /// <summary> |
||
338 | /// |
||
339 | /// </summary> |
||
340 | /// <param name="data"></param> |
||
341 | /// <param name="pos"></param> |
||
342 | public LightData(byte[] data, int pos) |
||
343 | { |
||
344 | if (data.Length - pos >= 16) |
||
345 | { |
||
346 | Color = new Color4(data, pos, false); |
||
347 | Radius = Utils.BytesToFloat(data, pos + 4); |
||
348 | Cutoff = Utils.BytesToFloat(data, pos + 8); |
||
349 | Falloff = Utils.BytesToFloat(data, pos + 12); |
||
350 | |||
351 | // Alpha in color is actually intensity |
||
352 | Intensity = Color.A; |
||
353 | Color.A = 1f; |
||
354 | } |
||
355 | else |
||
356 | { |
||
357 | Color = Color4.Black; |
||
358 | Radius = 0f; |
||
359 | Cutoff = 0f; |
||
360 | Falloff = 0f; |
||
361 | Intensity = 0f; |
||
362 | } |
||
363 | } |
||
364 | |||
365 | /// <summary> |
||
366 | /// |
||
367 | /// </summary> |
||
368 | /// <returns></returns> |
||
369 | public byte[] GetBytes() |
||
370 | { |
||
371 | byte[] data = new byte[16]; |
||
372 | |||
373 | // Alpha channel in color is intensity |
||
374 | Color4 tmpColor = Color; |
||
375 | tmpColor.A = Intensity; |
||
376 | tmpColor.GetBytes().CopyTo(data, 0); |
||
377 | Utils.FloatToBytes(Radius).CopyTo(data, 4); |
||
378 | Utils.FloatToBytes(Cutoff).CopyTo(data, 8); |
||
379 | Utils.FloatToBytes(Falloff).CopyTo(data, 12); |
||
380 | |||
381 | return data; |
||
382 | } |
||
383 | |||
384 | public OSD GetOSD() |
||
385 | { |
||
386 | OSDMap map = new OSDMap(); |
||
387 | |||
388 | map["color"] = OSD.FromColor4(Color); |
||
389 | map["intensity"] = OSD.FromReal(Intensity); |
||
390 | map["radius"] = OSD.FromReal(Radius); |
||
391 | map["cutoff"] = OSD.FromReal(Cutoff); |
||
392 | map["falloff"] = OSD.FromReal(Falloff); |
||
393 | |||
394 | return map; |
||
395 | } |
||
396 | |||
397 | public static LightData FromOSD(OSD osd) |
||
398 | { |
||
399 | LightData light = new LightData(); |
||
400 | |||
401 | if (osd.Type == OSDType.Map) |
||
402 | { |
||
403 | OSDMap map = (OSDMap)osd; |
||
404 | |||
405 | light.Color = ((OSDArray)map["color"]).AsColor4(); |
||
406 | light.Intensity = (float)map["intensity"].AsReal(); |
||
407 | light.Radius = (float)map["radius"].AsReal(); |
||
408 | light.Cutoff = (float)map["cutoff"].AsReal(); |
||
409 | light.Falloff = (float)map["falloff"].AsReal(); |
||
410 | } |
||
411 | |||
412 | return light; |
||
413 | } |
||
414 | |||
415 | public override int GetHashCode() |
||
416 | { |
||
417 | return |
||
418 | Color.GetHashCode() ^ |
||
419 | Intensity.GetHashCode() ^ |
||
420 | Radius.GetHashCode() ^ |
||
421 | Cutoff.GetHashCode() ^ |
||
422 | Falloff.GetHashCode(); |
||
423 | } |
||
424 | |||
425 | /// <summary> |
||
426 | /// |
||
427 | /// </summary> |
||
428 | /// <returns></returns> |
||
429 | public override string ToString() |
||
430 | { |
||
431 | return String.Format("Color: {0} Intensity: {1} Radius: {2} Cutoff: {3} Falloff: {4}", |
||
432 | Color, Intensity, Radius, Cutoff, Falloff); |
||
433 | } |
||
434 | } |
||
435 | |||
436 | /// <summary> |
||
437 | /// Information on the light properties of a primitive as texture map |
||
438 | /// </summary> |
||
439 | public class LightImage |
||
440 | { |
||
441 | /// <summary></summary> |
||
442 | public UUID LightTexture; |
||
443 | /// <summary></summary> |
||
444 | public Vector3 Params; |
||
445 | |||
446 | /// <summary> |
||
447 | /// Default constructor |
||
448 | /// </summary> |
||
449 | public LightImage() |
||
450 | { |
||
451 | } |
||
452 | |||
453 | /// <summary> |
||
454 | /// |
||
455 | /// </summary> |
||
456 | /// <param name="data"></param> |
||
457 | /// <param name="pos"></param> |
||
458 | public LightImage(byte[] data, int pos) |
||
459 | { |
||
460 | if (data.Length - pos >= 28) |
||
461 | { |
||
462 | LightTexture = new UUID(data, pos); |
||
463 | Params = new Vector3(data, pos + 16); |
||
464 | } |
||
465 | else |
||
466 | { |
||
467 | LightTexture = UUID.Zero; |
||
468 | Params = Vector3.Zero; |
||
469 | } |
||
470 | } |
||
471 | |||
472 | /// <summary> |
||
473 | /// |
||
474 | /// </summary> |
||
475 | /// <returns></returns> |
||
476 | public byte[] GetBytes() |
||
477 | { |
||
478 | byte[] data = new byte[28]; |
||
479 | |||
480 | // Alpha channel in color is intensity |
||
481 | LightTexture.ToBytes(data, 0); |
||
482 | Params.ToBytes(data, 16); |
||
483 | |||
484 | return data; |
||
485 | } |
||
486 | |||
487 | public OSD GetOSD() |
||
488 | { |
||
489 | OSDMap map = new OSDMap(); |
||
490 | |||
491 | map["texture"] = OSD.FromUUID(LightTexture); |
||
492 | map["params"] = OSD.FromVector3(Params); |
||
493 | |||
494 | return map; |
||
495 | } |
||
496 | |||
497 | public static LightImage FromOSD(OSD osd) |
||
498 | { |
||
499 | LightImage light = new LightImage(); |
||
500 | |||
501 | if (osd.Type == OSDType.Map) |
||
502 | { |
||
503 | OSDMap map = (OSDMap)osd; |
||
504 | |||
505 | light.LightTexture = map["texture"].AsUUID(); |
||
506 | light.Params = map["params"].AsVector3(); |
||
507 | } |
||
508 | |||
509 | return light; |
||
510 | } |
||
511 | |||
512 | public override int GetHashCode() |
||
513 | { |
||
514 | return LightTexture.GetHashCode() ^ Params.GetHashCode(); |
||
515 | } |
||
516 | |||
517 | /// <summary> |
||
518 | /// |
||
519 | /// </summary> |
||
520 | /// <returns></returns> |
||
521 | public override string ToString() |
||
522 | { |
||
523 | return String.Format("LightTexture: {0} Params; {1]", LightTexture, Params); |
||
524 | } |
||
525 | } |
||
526 | |||
527 | /// <summary> |
||
528 | /// Information on the sculpt properties of a sculpted primitive |
||
529 | /// </summary> |
||
530 | public class SculptData |
||
531 | { |
||
532 | public UUID SculptTexture; |
||
533 | private byte type; |
||
534 | |||
535 | public SculptType Type |
||
536 | { |
||
537 | get { return (SculptType)(type & 7); } |
||
538 | set { type = (byte)value; } |
||
539 | } |
||
540 | |||
541 | /// <summary> |
||
542 | /// Render inside out (inverts the normals). |
||
543 | /// </summary> |
||
544 | public bool Invert |
||
545 | { |
||
546 | get { return ((type & (byte)SculptType.Invert) != 0); } |
||
547 | } |
||
548 | |||
549 | /// <summary> |
||
550 | /// Render an X axis mirror of the sculpty. |
||
551 | /// </summary> |
||
552 | public bool Mirror |
||
553 | { |
||
554 | get { return ((type & (byte)SculptType.Mirror) != 0); } |
||
555 | } |
||
556 | |||
557 | /// <summary> |
||
558 | /// Default constructor |
||
559 | /// </summary> |
||
560 | public SculptData() |
||
561 | { |
||
562 | } |
||
563 | |||
564 | /// <summary> |
||
565 | /// |
||
566 | /// </summary> |
||
567 | /// <param name="data"></param> |
||
568 | /// <param name="pos"></param> |
||
569 | public SculptData(byte[] data, int pos) |
||
570 | { |
||
571 | if (data.Length >= 17) |
||
572 | { |
||
573 | SculptTexture = new UUID(data, pos); |
||
574 | type = data[pos + 16]; |
||
575 | } |
||
576 | else |
||
577 | { |
||
578 | SculptTexture = UUID.Zero; |
||
579 | type = (byte)SculptType.None; |
||
580 | } |
||
581 | } |
||
582 | |||
583 | public byte[] GetBytes() |
||
584 | { |
||
585 | byte[] data = new byte[17]; |
||
586 | |||
587 | SculptTexture.GetBytes().CopyTo(data, 0); |
||
588 | data[16] = type; |
||
589 | |||
590 | return data; |
||
591 | } |
||
592 | |||
593 | public OSD GetOSD() |
||
594 | { |
||
595 | OSDMap map = new OSDMap(); |
||
596 | |||
597 | map["texture"] = OSD.FromUUID(SculptTexture); |
||
598 | map["type"] = OSD.FromInteger(type); |
||
599 | |||
600 | return map; |
||
601 | } |
||
602 | |||
603 | public static SculptData FromOSD(OSD osd) |
||
604 | { |
||
605 | SculptData sculpt = new SculptData(); |
||
606 | |||
607 | if (osd.Type == OSDType.Map) |
||
608 | { |
||
609 | OSDMap map = (OSDMap)osd; |
||
610 | |||
611 | sculpt.SculptTexture = map["texture"].AsUUID(); |
||
612 | sculpt.type = (byte)map["type"].AsInteger(); |
||
613 | } |
||
614 | |||
615 | return sculpt; |
||
616 | } |
||
617 | |||
618 | public override int GetHashCode() |
||
619 | { |
||
620 | return SculptTexture.GetHashCode() ^ type.GetHashCode(); |
||
621 | } |
||
622 | } |
||
623 | |||
624 | /// <summary> |
||
625 | /// Extended properties to describe an object |
||
626 | /// </summary> |
||
627 | public class ObjectProperties |
||
628 | { |
||
629 | /// <summary></summary> |
||
630 | public UUID ObjectID; |
||
631 | /// <summary></summary> |
||
632 | public UUID CreatorID; |
||
633 | /// <summary></summary> |
||
634 | public UUID OwnerID; |
||
635 | /// <summary></summary> |
||
636 | public UUID GroupID; |
||
637 | /// <summary></summary> |
||
638 | public DateTime CreationDate; |
||
639 | /// <summary></summary> |
||
640 | public Permissions Permissions; |
||
641 | /// <summary></summary> |
||
642 | public int OwnershipCost; |
||
643 | /// <summary></summary> |
||
644 | public SaleType SaleType; |
||
645 | /// <summary></summary> |
||
646 | public int SalePrice; |
||
647 | /// <summary></summary> |
||
648 | public byte AggregatePerms; |
||
649 | /// <summary></summary> |
||
650 | public byte AggregatePermTextures; |
||
651 | /// <summary></summary> |
||
652 | public byte AggregatePermTexturesOwner; |
||
653 | /// <summary></summary> |
||
654 | public ObjectCategory Category; |
||
655 | /// <summary></summary> |
||
656 | public short InventorySerial; |
||
657 | /// <summary></summary> |
||
658 | public UUID ItemID; |
||
659 | /// <summary></summary> |
||
660 | public UUID FolderID; |
||
661 | /// <summary></summary> |
||
662 | public UUID FromTaskID; |
||
663 | /// <summary></summary> |
||
664 | public UUID LastOwnerID; |
||
665 | /// <summary></summary> |
||
666 | public string Name; |
||
667 | /// <summary></summary> |
||
668 | public string Description; |
||
669 | /// <summary></summary> |
||
670 | public string TouchName; |
||
671 | /// <summary></summary> |
||
672 | public string SitName; |
||
673 | /// <summary></summary> |
||
674 | public UUID[] TextureIDs; |
||
675 | |||
676 | /// <summary> |
||
677 | /// Default constructor |
||
678 | /// </summary> |
||
679 | public ObjectProperties() |
||
680 | { |
||
681 | Name = String.Empty; |
||
682 | Description = String.Empty; |
||
683 | TouchName = String.Empty; |
||
684 | SitName = String.Empty; |
||
685 | } |
||
686 | |||
687 | /// <summary> |
||
688 | /// Set the properties that are set in an ObjectPropertiesFamily packet |
||
689 | /// </summary> |
||
690 | /// <param name="props"><seealso cref="ObjectProperties"/> that has |
||
691 | /// been partially filled by an ObjectPropertiesFamily packet</param> |
||
692 | public void SetFamilyProperties(ObjectProperties props) |
||
693 | { |
||
694 | ObjectID = props.ObjectID; |
||
695 | OwnerID = props.OwnerID; |
||
696 | GroupID = props.GroupID; |
||
697 | Permissions = props.Permissions; |
||
698 | OwnershipCost = props.OwnershipCost; |
||
699 | SaleType = props.SaleType; |
||
700 | SalePrice = props.SalePrice; |
||
701 | Category = props.Category; |
||
702 | LastOwnerID = props.LastOwnerID; |
||
703 | Name = props.Name; |
||
704 | Description = props.Description; |
||
705 | } |
||
706 | |||
707 | public byte[] GetTextureIDBytes() |
||
708 | { |
||
709 | if (TextureIDs == null || TextureIDs.Length == 0) |
||
710 | return Utils.EmptyBytes; |
||
711 | |||
712 | byte[] bytes = new byte[16 * TextureIDs.Length]; |
||
713 | for (int i = 0; i < TextureIDs.Length; i++) |
||
714 | TextureIDs[i].ToBytes(bytes, 16 * i); |
||
715 | |||
716 | return bytes; |
||
717 | } |
||
718 | } |
||
719 | |||
720 | /// <summary> |
||
721 | /// Describes physics attributes of the prim |
||
722 | /// </summary> |
||
723 | public class PhysicsProperties |
||
724 | { |
||
725 | /// <summary>Primitive's local ID</summary> |
||
726 | public uint LocalID; |
||
727 | /// <summary>Density (1000 for normal density)</summary> |
||
728 | public float Density; |
||
729 | /// <summary>Friction</summary> |
||
730 | public float Friction; |
||
731 | /// <summary>Gravity multiplier (1 for normal gravity) </summary> |
||
732 | public float GravityMultiplier; |
||
733 | /// <summary>Type of physics representation of this primitive in the simulator</summary> |
||
734 | public PhysicsShapeType PhysicsShapeType; |
||
735 | /// <summary>Restitution</summary> |
||
736 | public float Restitution; |
||
737 | |||
738 | /// <summary> |
||
739 | /// Creates PhysicsProperties from OSD |
||
740 | /// </summary> |
||
741 | /// <param name="osd">OSDMap with incoming data</param> |
||
742 | /// <returns>Deserialized PhysicsProperties object</returns> |
||
743 | public static PhysicsProperties FromOSD(OSD osd) |
||
744 | { |
||
745 | PhysicsProperties ret = new PhysicsProperties(); |
||
746 | |||
747 | if (osd is OSDMap) |
||
748 | { |
||
749 | OSDMap map = (OSDMap)osd; |
||
750 | ret.LocalID = map["LocalID"]; |
||
751 | ret.Density = map["Density"]; |
||
752 | ret.Friction = map["Friction"]; |
||
753 | ret.GravityMultiplier = map["GravityMultiplier"]; |
||
754 | ret.Restitution = map["Restitution"]; |
||
755 | ret.PhysicsShapeType = (PhysicsShapeType)map["PhysicsShapeType"].AsInteger(); |
||
756 | } |
||
757 | |||
758 | return ret; |
||
759 | } |
||
760 | |||
761 | /// <summary> |
||
762 | /// Serializes PhysicsProperties to OSD |
||
763 | /// </summary> |
||
764 | /// <returns>OSDMap with serialized PhysicsProperties data</returns> |
||
765 | public OSD GetOSD() |
||
766 | { |
||
767 | OSDMap map = new OSDMap(6); |
||
768 | map["LocalID"] = LocalID; |
||
769 | map["Density"] = Density; |
||
770 | map["Friction"] = Friction; |
||
771 | map["GravityMultiplier"] = GravityMultiplier; |
||
772 | map["Restitution"] = Restitution; |
||
773 | map["PhysicsShapeType"] = (int)PhysicsShapeType; |
||
774 | return map; |
||
775 | } |
||
776 | } |
||
777 | |||
778 | #endregion Subclasses |
||
779 | |||
780 | #region Public Members |
||
781 | |||
782 | /// <summary></summary> |
||
783 | public UUID ID; |
||
784 | /// <summary></summary> |
||
785 | public UUID GroupID; |
||
786 | /// <summary></summary> |
||
787 | public uint LocalID; |
||
788 | /// <summary></summary> |
||
789 | public uint ParentID; |
||
790 | /// <summary></summary> |
||
791 | public ulong RegionHandle; |
||
792 | /// <summary></summary> |
||
793 | public PrimFlags Flags; |
||
794 | /// <summary>Foliage type for this primitive. Only applicable if this |
||
795 | /// primitive is foliage</summary> |
||
796 | public Tree TreeSpecies; |
||
797 | /// <summary>Unknown</summary> |
||
798 | public byte[] ScratchPad; |
||
799 | /// <summary></summary> |
||
800 | public Vector3 Position; |
||
801 | /// <summary></summary> |
||
802 | public Vector3 Scale; |
||
803 | /// <summary></summary> |
||
804 | public Quaternion Rotation = Quaternion.Identity; |
||
805 | /// <summary></summary> |
||
806 | public Vector3 Velocity; |
||
807 | /// <summary></summary> |
||
808 | public Vector3 AngularVelocity; |
||
809 | /// <summary></summary> |
||
810 | public Vector3 Acceleration; |
||
811 | /// <summary></summary> |
||
812 | public Vector4 CollisionPlane; |
||
813 | /// <summary></summary> |
||
814 | public FlexibleData Flexible; |
||
815 | /// <summary></summary> |
||
816 | public LightData Light; |
||
817 | /// <summary></summary> |
||
818 | public LightImage LightMap; |
||
819 | /// <summary></summary> |
||
820 | public SculptData Sculpt; |
||
821 | /// <summary></summary> |
||
822 | public ClickAction ClickAction; |
||
823 | /// <summary></summary> |
||
824 | public UUID Sound; |
||
825 | /// <summary>Identifies the owner if audio or a particle system is |
||
826 | /// active</summary> |
||
827 | public UUID OwnerID; |
||
828 | /// <summary></summary> |
||
829 | public SoundFlags SoundFlags; |
||
830 | /// <summary></summary> |
||
831 | public float SoundGain; |
||
832 | /// <summary></summary> |
||
833 | public float SoundRadius; |
||
834 | /// <summary></summary> |
||
835 | public string Text; |
||
836 | /// <summary></summary> |
||
837 | public Color4 TextColor; |
||
838 | /// <summary></summary> |
||
839 | public string MediaURL; |
||
840 | /// <summary></summary> |
||
841 | public JointType Joint; |
||
842 | /// <summary></summary> |
||
843 | public Vector3 JointPivot; |
||
844 | /// <summary></summary> |
||
845 | public Vector3 JointAxisOrAnchor; |
||
846 | /// <summary></summary> |
||
847 | public NameValue[] NameValues; |
||
848 | /// <summary></summary> |
||
849 | public ConstructionData PrimData; |
||
850 | /// <summary></summary> |
||
851 | public ObjectProperties Properties; |
||
852 | /// <summary>Objects physics engine propertis</summary> |
||
853 | public PhysicsProperties PhysicsProps; |
||
854 | /// <summary>Extra data about primitive</summary> |
||
855 | public object Tag; |
||
856 | /// <summary>Indicates if prim is attached to an avatar</summary> |
||
857 | public bool IsAttachment; |
||
858 | /// <summary>Number of clients referencing this prim</summary> |
||
859 | public int ActiveClients = 0; |
||
860 | |||
861 | #endregion Public Members |
||
862 | |||
863 | #region Properties |
||
864 | |||
865 | /// <summary>Uses basic heuristics to estimate the primitive shape</summary> |
||
866 | public PrimType Type |
||
867 | { |
||
868 | get |
||
869 | { |
||
870 | if (Sculpt != null && Sculpt.Type != SculptType.None && Sculpt.SculptTexture != UUID.Zero) |
||
871 | { |
||
872 | if (Sculpt.Type == SculptType.Mesh) |
||
873 | return PrimType.Mesh; |
||
874 | else |
||
875 | return PrimType.Sculpt; |
||
876 | } |
||
877 | |||
878 | bool linearPath = (PrimData.PathCurve == PathCurve.Line || PrimData.PathCurve == PathCurve.Flexible); |
||
879 | float scaleY = PrimData.PathScaleY; |
||
880 | |||
881 | if (linearPath) |
||
882 | { |
||
883 | switch (PrimData.ProfileCurve) |
||
884 | { |
||
885 | case ProfileCurve.Circle: |
||
886 | return PrimType.Cylinder; |
||
887 | case ProfileCurve.Square: |
||
888 | return PrimType.Box; |
||
889 | case ProfileCurve.IsoTriangle: |
||
890 | case ProfileCurve.EqualTriangle: |
||
891 | case ProfileCurve.RightTriangle: |
||
892 | return PrimType.Prism; |
||
893 | case ProfileCurve.HalfCircle: |
||
894 | default: |
||
895 | return PrimType.Unknown; |
||
896 | } |
||
897 | } |
||
898 | else |
||
899 | { |
||
900 | switch (PrimData.PathCurve) |
||
901 | { |
||
902 | case PathCurve.Flexible: |
||
903 | return PrimType.Unknown; |
||
904 | case PathCurve.Circle: |
||
905 | switch (PrimData.ProfileCurve) |
||
906 | { |
||
907 | case ProfileCurve.Circle: |
||
908 | if (scaleY > 0.75f) |
||
909 | return PrimType.Sphere; |
||
910 | else |
||
911 | return PrimType.Torus; |
||
912 | case ProfileCurve.HalfCircle: |
||
913 | return PrimType.Sphere; |
||
914 | case ProfileCurve.EqualTriangle: |
||
915 | return PrimType.Ring; |
||
916 | case ProfileCurve.Square: |
||
917 | if (scaleY <= 0.75f) |
||
918 | return PrimType.Tube; |
||
919 | else |
||
920 | return PrimType.Unknown; |
||
921 | default: |
||
922 | return PrimType.Unknown; |
||
923 | } |
||
924 | case PathCurve.Circle2: |
||
925 | if (PrimData.ProfileCurve == ProfileCurve.Circle) |
||
926 | return PrimType.Sphere; |
||
927 | else |
||
928 | return PrimType.Unknown; |
||
929 | default: |
||
930 | return PrimType.Unknown; |
||
931 | } |
||
932 | } |
||
933 | } |
||
934 | } |
||
935 | |||
936 | #endregion Properties |
||
937 | |||
938 | #region Constructors |
||
939 | |||
940 | /// <summary> |
||
941 | /// Default constructor |
||
942 | /// </summary> |
||
943 | public Primitive() |
||
944 | { |
||
945 | // Default a few null property values to String.Empty |
||
946 | Text = String.Empty; |
||
947 | MediaURL = String.Empty; |
||
948 | } |
||
949 | |||
950 | public Primitive(Primitive prim) |
||
951 | { |
||
952 | ID = prim.ID; |
||
953 | GroupID = prim.GroupID; |
||
954 | LocalID = prim.LocalID; |
||
955 | ParentID = prim.ParentID; |
||
956 | RegionHandle = prim.RegionHandle; |
||
957 | Flags = prim.Flags; |
||
958 | TreeSpecies = prim.TreeSpecies; |
||
959 | if (prim.ScratchPad != null) |
||
960 | { |
||
961 | ScratchPad = new byte[prim.ScratchPad.Length]; |
||
962 | Buffer.BlockCopy(prim.ScratchPad, 0, ScratchPad, 0, ScratchPad.Length); |
||
963 | } |
||
964 | else |
||
965 | ScratchPad = Utils.EmptyBytes; |
||
966 | Position = prim.Position; |
||
967 | Scale = prim.Scale; |
||
968 | Rotation = prim.Rotation; |
||
969 | Velocity = prim.Velocity; |
||
970 | AngularVelocity = prim.AngularVelocity; |
||
971 | Acceleration = prim.Acceleration; |
||
972 | CollisionPlane = prim.CollisionPlane; |
||
973 | Flexible = prim.Flexible; |
||
974 | Light = prim.Light; |
||
975 | LightMap = prim.LightMap; |
||
976 | Sculpt = prim.Sculpt; |
||
977 | ClickAction = prim.ClickAction; |
||
978 | Sound = prim.Sound; |
||
979 | OwnerID = prim.OwnerID; |
||
980 | SoundFlags = prim.SoundFlags; |
||
981 | SoundGain = prim.SoundGain; |
||
982 | SoundRadius = prim.SoundRadius; |
||
983 | Text = prim.Text; |
||
984 | TextColor = prim.TextColor; |
||
985 | MediaURL = prim.MediaURL; |
||
986 | Joint = prim.Joint; |
||
987 | JointPivot = prim.JointPivot; |
||
988 | JointAxisOrAnchor = prim.JointAxisOrAnchor; |
||
989 | if (prim.NameValues != null) |
||
990 | { |
||
991 | if (NameValues == null || NameValues.Length != prim.NameValues.Length) |
||
992 | NameValues = new NameValue[prim.NameValues.Length]; |
||
993 | Array.Copy(prim.NameValues, NameValues, prim.NameValues.Length); |
||
994 | } |
||
995 | else |
||
996 | NameValues = null; |
||
997 | PrimData = prim.PrimData; |
||
998 | Properties = prim.Properties; |
||
999 | // FIXME: Get a real copy constructor for TextureEntry instead of serializing to bytes and back |
||
1000 | if (prim.Textures != null) |
||
1001 | { |
||
1002 | byte[] textureBytes = prim.Textures.GetBytes(); |
||
1003 | Textures = new TextureEntry(textureBytes, 0, textureBytes.Length); |
||
1004 | } |
||
1005 | else |
||
1006 | { |
||
1007 | Textures = null; |
||
1008 | } |
||
1009 | TextureAnim = prim.TextureAnim; |
||
1010 | ParticleSys = prim.ParticleSys; |
||
1011 | } |
||
1012 | |||
1013 | #endregion Constructors |
||
1014 | |||
1015 | #region Public Methods |
||
1016 | |||
1017 | public virtual OSD GetOSD() |
||
1018 | { |
||
1019 | OSDMap path = new OSDMap(14); |
||
1020 | path["begin"] = OSD.FromReal(PrimData.PathBegin); |
||
1021 | path["curve"] = OSD.FromInteger((int)PrimData.PathCurve); |
||
1022 | path["end"] = OSD.FromReal(PrimData.PathEnd); |
||
1023 | path["radius_offset"] = OSD.FromReal(PrimData.PathRadiusOffset); |
||
1024 | path["revolutions"] = OSD.FromReal(PrimData.PathRevolutions); |
||
1025 | path["scale_x"] = OSD.FromReal(PrimData.PathScaleX); |
||
1026 | path["scale_y"] = OSD.FromReal(PrimData.PathScaleY); |
||
1027 | path["shear_x"] = OSD.FromReal(PrimData.PathShearX); |
||
1028 | path["shear_y"] = OSD.FromReal(PrimData.PathShearY); |
||
1029 | path["skew"] = OSD.FromReal(PrimData.PathSkew); |
||
1030 | path["taper_x"] = OSD.FromReal(PrimData.PathTaperX); |
||
1031 | path["taper_y"] = OSD.FromReal(PrimData.PathTaperY); |
||
1032 | path["twist"] = OSD.FromReal(PrimData.PathTwist); |
||
1033 | path["twist_begin"] = OSD.FromReal(PrimData.PathTwistBegin); |
||
1034 | |||
1035 | OSDMap profile = new OSDMap(4); |
||
1036 | profile["begin"] = OSD.FromReal(PrimData.ProfileBegin); |
||
1037 | profile["curve"] = OSD.FromInteger((int)PrimData.ProfileCurve); |
||
1038 | profile["hole"] = OSD.FromInteger((int)PrimData.ProfileHole); |
||
1039 | profile["end"] = OSD.FromReal(PrimData.ProfileEnd); |
||
1040 | profile["hollow"] = OSD.FromReal(PrimData.ProfileHollow); |
||
1041 | |||
1042 | OSDMap volume = new OSDMap(2); |
||
1043 | volume["path"] = path; |
||
1044 | volume["profile"] = profile; |
||
1045 | |||
1046 | OSDMap prim = new OSDMap(20); |
||
1047 | if (Properties != null) |
||
1048 | { |
||
1049 | prim["name"] = OSD.FromString(Properties.Name); |
||
1050 | prim["description"] = OSD.FromString(Properties.Description); |
||
1051 | } |
||
1052 | else |
||
1053 | { |
||
1054 | prim["name"] = OSD.FromString("Object"); |
||
1055 | prim["description"] = OSD.FromString(String.Empty); |
||
1056 | } |
||
1057 | |||
1058 | prim["phantom"] = OSD.FromBoolean(((Flags & PrimFlags.Phantom) != 0)); |
||
1059 | prim["physical"] = OSD.FromBoolean(((Flags & PrimFlags.Physics) != 0)); |
||
1060 | prim["position"] = OSD.FromVector3(Position); |
||
1061 | prim["rotation"] = OSD.FromQuaternion(Rotation); |
||
1062 | prim["scale"] = OSD.FromVector3(Scale); |
||
1063 | prim["pcode"] = OSD.FromInteger((int)PrimData.PCode); |
||
1064 | prim["material"] = OSD.FromInteger((int)PrimData.Material); |
||
1065 | prim["shadows"] = OSD.FromBoolean(((Flags & PrimFlags.CastShadows) != 0)); |
||
1066 | prim["state"] = OSD.FromInteger(PrimData.State); |
||
1067 | |||
1068 | prim["id"] = OSD.FromUUID(ID); |
||
1069 | prim["localid"] = OSD.FromUInteger(LocalID); |
||
1070 | prim["parentid"] = OSD.FromUInteger(ParentID); |
||
1071 | |||
1072 | prim["volume"] = volume; |
||
1073 | |||
1074 | if (Textures != null) |
||
1075 | prim["textures"] = Textures.GetOSD(); |
||
1076 | |||
1077 | if ((TextureAnim.Flags & TextureAnimMode.ANIM_ON) != 0) |
||
1078 | prim["texture_anim"] = TextureAnim.GetOSD(); |
||
1079 | |||
1080 | if (Light != null) |
||
1081 | prim["light"] = Light.GetOSD(); |
||
1082 | |||
1083 | if (LightMap != null) |
||
1084 | prim["light_image"] = LightMap.GetOSD(); |
||
1085 | |||
1086 | if (Flexible != null) |
||
1087 | prim["flex"] = Flexible.GetOSD(); |
||
1088 | |||
1089 | if (Sculpt != null) |
||
1090 | prim["sculpt"] = Sculpt.GetOSD(); |
||
1091 | |||
1092 | return prim; |
||
1093 | } |
||
1094 | |||
1095 | public static Primitive FromOSD(OSD osd) |
||
1096 | { |
||
1097 | Primitive prim = new Primitive(); |
||
1098 | Primitive.ConstructionData data; |
||
1099 | |||
1100 | OSDMap map = (OSDMap)osd; |
||
1101 | OSDMap volume = (OSDMap)map["volume"]; |
||
1102 | OSDMap path = (OSDMap)volume["path"]; |
||
1103 | OSDMap profile = (OSDMap)volume["profile"]; |
||
1104 | |||
1105 | #region Path/Profile |
||
1106 | |||
1107 | data.profileCurve = (byte)0; |
||
1108 | data.Material = (Material)map["material"].AsInteger(); |
||
1109 | data.PCode = (PCode)map["pcode"].AsInteger(); |
||
1110 | data.State = (byte)map["state"].AsInteger(); |
||
1111 | |||
1112 | data.PathBegin = (float)path["begin"].AsReal(); |
||
1113 | data.PathCurve = (PathCurve)path["curve"].AsInteger(); |
||
1114 | data.PathEnd = (float)path["end"].AsReal(); |
||
1115 | data.PathRadiusOffset = (float)path["radius_offset"].AsReal(); |
||
1116 | data.PathRevolutions = (float)path["revolutions"].AsReal(); |
||
1117 | data.PathScaleX = (float)path["scale_x"].AsReal(); |
||
1118 | data.PathScaleY = (float)path["scale_y"].AsReal(); |
||
1119 | data.PathShearX = (float)path["shear_x"].AsReal(); |
||
1120 | data.PathShearY = (float)path["shear_y"].AsReal(); |
||
1121 | data.PathSkew = (float)path["skew"].AsReal(); |
||
1122 | data.PathTaperX = (float)path["taper_x"].AsReal(); |
||
1123 | data.PathTaperY = (float)path["taper_y"].AsReal(); |
||
1124 | data.PathTwist = (float)path["twist"].AsReal(); |
||
1125 | data.PathTwistBegin = (float)path["twist_begin"].AsReal(); |
||
1126 | |||
1127 | data.ProfileBegin = (float)profile["begin"].AsReal(); |
||
1128 | data.ProfileEnd = (float)profile["end"].AsReal(); |
||
1129 | data.ProfileHollow = (float)profile["hollow"].AsReal(); |
||
1130 | data.ProfileCurve = (ProfileCurve)profile["curve"].AsInteger(); |
||
1131 | data.ProfileHole = (HoleType)profile["hole"].AsInteger(); |
||
1132 | |||
1133 | #endregion Path/Profile |
||
1134 | |||
1135 | prim.PrimData = data; |
||
1136 | |||
1137 | if (map["phantom"].AsBoolean()) |
||
1138 | prim.Flags |= PrimFlags.Phantom; |
||
1139 | |||
1140 | if (map["physical"].AsBoolean()) |
||
1141 | prim.Flags |= PrimFlags.Physics; |
||
1142 | |||
1143 | if (map["shadows"].AsBoolean()) |
||
1144 | prim.Flags |= PrimFlags.CastShadows; |
||
1145 | |||
1146 | prim.ID = map["id"].AsUUID(); |
||
1147 | prim.LocalID = map["localid"].AsUInteger(); |
||
1148 | prim.ParentID = map["parentid"].AsUInteger(); |
||
1149 | prim.Position = ((OSDArray)map["position"]).AsVector3(); |
||
1150 | prim.Rotation = ((OSDArray)map["rotation"]).AsQuaternion(); |
||
1151 | prim.Scale = ((OSDArray)map["scale"]).AsVector3(); |
||
1152 | |||
1153 | if (map["flex"]) |
||
1154 | prim.Flexible = FlexibleData.FromOSD(map["flex"]); |
||
1155 | |||
1156 | if (map["light"]) |
||
1157 | prim.Light = LightData.FromOSD(map["light"]); |
||
1158 | |||
1159 | if (map["light_image"]) |
||
1160 | prim.LightMap = LightImage.FromOSD(map["light_image"]); |
||
1161 | |||
1162 | if (map["sculpt"]) |
||
1163 | prim.Sculpt = SculptData.FromOSD(map["sculpt"]); |
||
1164 | |||
1165 | prim.Textures = TextureEntry.FromOSD(map["textures"]); |
||
1166 | |||
1167 | if (map["texture_anim"]) |
||
1168 | prim.TextureAnim = TextureAnimation.FromOSD(map["texture_anim"]); |
||
1169 | |||
1170 | prim.Properties = new ObjectProperties(); |
||
1171 | |||
1172 | if (!string.IsNullOrEmpty(map["name"].AsString())) |
||
1173 | { |
||
1174 | prim.Properties.Name = map["name"].AsString(); |
||
1175 | } |
||
1176 | |||
1177 | if (!string.IsNullOrEmpty(map["description"].AsString())) |
||
1178 | { |
||
1179 | prim.Properties.Description = map["description"].AsString(); |
||
1180 | } |
||
1181 | |||
1182 | return prim; |
||
1183 | } |
||
1184 | |||
1185 | public int SetExtraParamsFromBytes(byte[] data, int pos) |
||
1186 | { |
||
1187 | int i = pos; |
||
1188 | int totalLength = 1; |
||
1189 | |||
1190 | if (data.Length == 0 || pos >= data.Length) |
||
1191 | return 0; |
||
1192 | |||
1193 | byte extraParamCount = data[i++]; |
||
1194 | |||
1195 | for (int k = 0; k < extraParamCount; k++) |
||
1196 | { |
||
1197 | ExtraParamType type = (ExtraParamType)Utils.BytesToUInt16(data, i); |
||
1198 | i += 2; |
||
1199 | |||
1200 | uint paramLength = Utils.BytesToUInt(data, i); |
||
1201 | i += 4; |
||
1202 | |||
1203 | if (type == ExtraParamType.Flexible) |
||
1204 | Flexible = new FlexibleData(data, i); |
||
1205 | else if (type == ExtraParamType.Light) |
||
1206 | Light = new LightData(data, i); |
||
1207 | else if (type == ExtraParamType.LightImage) |
||
1208 | LightMap = new LightImage(data, i); |
||
1209 | else if (type == ExtraParamType.Sculpt || type == ExtraParamType.Mesh) |
||
1210 | Sculpt = new SculptData(data, i); |
||
1211 | |||
1212 | i += (int)paramLength; |
||
1213 | totalLength += (int)paramLength + 6; |
||
1214 | } |
||
1215 | |||
1216 | return totalLength; |
||
1217 | } |
||
1218 | |||
1219 | public byte[] GetExtraParamsBytes() |
||
1220 | { |
||
1221 | byte[] flexible = null; |
||
1222 | byte[] light = null; |
||
1223 | byte[] lightmap = null; |
||
1224 | byte[] sculpt = null; |
||
1225 | byte[] buffer = null; |
||
1226 | int size = 1; |
||
1227 | int pos = 0; |
||
1228 | byte count = 0; |
||
1229 | |||
1230 | if (Flexible != null) |
||
1231 | { |
||
1232 | flexible = Flexible.GetBytes(); |
||
1233 | size += flexible.Length + 6; |
||
1234 | ++count; |
||
1235 | } |
||
1236 | if (Light != null) |
||
1237 | { |
||
1238 | light = Light.GetBytes(); |
||
1239 | size += light.Length + 6; |
||
1240 | ++count; |
||
1241 | } |
||
1242 | if (LightMap != null) |
||
1243 | { |
||
1244 | lightmap = LightMap.GetBytes(); |
||
1245 | size += lightmap.Length + 6; |
||
1246 | ++count; |
||
1247 | } |
||
1248 | if (Sculpt != null) |
||
1249 | { |
||
1250 | sculpt = Sculpt.GetBytes(); |
||
1251 | size += sculpt.Length + 6; |
||
1252 | ++count; |
||
1253 | } |
||
1254 | |||
1255 | buffer = new byte[size]; |
||
1256 | buffer[0] = count; |
||
1257 | ++pos; |
||
1258 | |||
1259 | if (flexible != null) |
||
1260 | { |
||
1261 | Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Flexible), 0, buffer, pos, 2); |
||
1262 | pos += 2; |
||
1263 | |||
1264 | Buffer.BlockCopy(Utils.UIntToBytes((uint)flexible.Length), 0, buffer, pos, 4); |
||
1265 | pos += 4; |
||
1266 | |||
1267 | Buffer.BlockCopy(flexible, 0, buffer, pos, flexible.Length); |
||
1268 | pos += flexible.Length; |
||
1269 | } |
||
1270 | if (light != null) |
||
1271 | { |
||
1272 | Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Light), 0, buffer, pos, 2); |
||
1273 | pos += 2; |
||
1274 | |||
1275 | Buffer.BlockCopy(Utils.UIntToBytes((uint)light.Length), 0, buffer, pos, 4); |
||
1276 | pos += 4; |
||
1277 | |||
1278 | Buffer.BlockCopy(light, 0, buffer, pos, light.Length); |
||
1279 | pos += light.Length; |
||
1280 | } |
||
1281 | if (lightmap != null) |
||
1282 | { |
||
1283 | Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.LightImage), 0, buffer, pos, 2); |
||
1284 | pos += 2; |
||
1285 | |||
1286 | Buffer.BlockCopy(Utils.UIntToBytes((uint)lightmap.Length), 0, buffer, pos, 4); |
||
1287 | pos += 4; |
||
1288 | |||
1289 | Buffer.BlockCopy(lightmap, 0, buffer, pos, lightmap.Length); |
||
1290 | pos += lightmap.Length; |
||
1291 | } |
||
1292 | if (sculpt != null) |
||
1293 | { |
||
1294 | if (Sculpt.Type == SculptType.Mesh) |
||
1295 | { |
||
1296 | Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Mesh), 0, buffer, pos, 2); |
||
1297 | } |
||
1298 | else |
||
1299 | { |
||
1300 | Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Sculpt), 0, buffer, pos, 2); |
||
1301 | } |
||
1302 | pos += 2; |
||
1303 | |||
1304 | Buffer.BlockCopy(Utils.UIntToBytes((uint)sculpt.Length), 0, buffer, pos, 4); |
||
1305 | pos += 4; |
||
1306 | |||
1307 | Buffer.BlockCopy(sculpt, 0, buffer, pos, sculpt.Length); |
||
1308 | pos += sculpt.Length; |
||
1309 | } |
||
1310 | |||
1311 | return buffer; |
||
1312 | } |
||
1313 | |||
1314 | #endregion Public Methods |
||
1315 | |||
1316 | #region Overrides |
||
1317 | |||
1318 | public override bool Equals(object obj) |
||
1319 | { |
||
1320 | return (obj is Primitive) ? this == (Primitive)obj : false; |
||
1321 | } |
||
1322 | |||
1323 | public bool Equals(Primitive other) |
||
1324 | { |
||
1325 | return this == other; |
||
1326 | } |
||
1327 | |||
1328 | public override string ToString() |
||
1329 | { |
||
1330 | switch (PrimData.PCode) |
||
1331 | { |
||
1332 | case PCode.Prim: |
||
1333 | return String.Format("{0} ({1})", Type, ID); |
||
1334 | default: |
||
1335 | return String.Format("{0} ({1})", PrimData.PCode, ID); |
||
1336 | } |
||
1337 | } |
||
1338 | |||
1339 | public override int GetHashCode() |
||
1340 | { |
||
1341 | return |
||
1342 | Position.GetHashCode() ^ |
||
1343 | Velocity.GetHashCode() ^ |
||
1344 | Acceleration.GetHashCode() ^ |
||
1345 | Rotation.GetHashCode() ^ |
||
1346 | AngularVelocity.GetHashCode() ^ |
||
1347 | ClickAction.GetHashCode() ^ |
||
1348 | (Flexible != null ? Flexible.GetHashCode() : 0) ^ |
||
1349 | (Light != null ? Light.GetHashCode() : 0) ^ |
||
1350 | (Sculpt != null ? Sculpt.GetHashCode() : 0) ^ |
||
1351 | Flags.GetHashCode() ^ |
||
1352 | PrimData.Material.GetHashCode() ^ |
||
1353 | MediaURL.GetHashCode() ^ |
||
1354 | //TODO: NameValues? |
||
1355 | (Properties != null ? Properties.OwnerID.GetHashCode() : 0) ^ |
||
1356 | ParentID.GetHashCode() ^ |
||
1357 | PrimData.PathBegin.GetHashCode() ^ |
||
1358 | PrimData.PathCurve.GetHashCode() ^ |
||
1359 | PrimData.PathEnd.GetHashCode() ^ |
||
1360 | PrimData.PathRadiusOffset.GetHashCode() ^ |
||
1361 | PrimData.PathRevolutions.GetHashCode() ^ |
||
1362 | PrimData.PathScaleX.GetHashCode() ^ |
||
1363 | PrimData.PathScaleY.GetHashCode() ^ |
||
1364 | PrimData.PathShearX.GetHashCode() ^ |
||
1365 | PrimData.PathShearY.GetHashCode() ^ |
||
1366 | PrimData.PathSkew.GetHashCode() ^ |
||
1367 | PrimData.PathTaperX.GetHashCode() ^ |
||
1368 | PrimData.PathTaperY.GetHashCode() ^ |
||
1369 | PrimData.PathTwist.GetHashCode() ^ |
||
1370 | PrimData.PathTwistBegin.GetHashCode() ^ |
||
1371 | PrimData.PCode.GetHashCode() ^ |
||
1372 | PrimData.ProfileBegin.GetHashCode() ^ |
||
1373 | PrimData.ProfileCurve.GetHashCode() ^ |
||
1374 | PrimData.ProfileEnd.GetHashCode() ^ |
||
1375 | PrimData.ProfileHollow.GetHashCode() ^ |
||
1376 | ParticleSys.GetHashCode() ^ |
||
1377 | TextColor.GetHashCode() ^ |
||
1378 | TextureAnim.GetHashCode() ^ |
||
1379 | (Textures != null ? Textures.GetHashCode() : 0) ^ |
||
1380 | SoundRadius.GetHashCode() ^ |
||
1381 | Scale.GetHashCode() ^ |
||
1382 | Sound.GetHashCode() ^ |
||
1383 | PrimData.State.GetHashCode() ^ |
||
1384 | Text.GetHashCode() ^ |
||
1385 | TreeSpecies.GetHashCode(); |
||
1386 | } |
||
1387 | |||
1388 | #endregion Overrides |
||
1389 | |||
1390 | #region Operators |
||
1391 | |||
1392 | public static bool operator ==(Primitive lhs, Primitive rhs) |
||
1393 | { |
||
1394 | if ((Object)lhs == null || (Object)rhs == null) |
||
1395 | { |
||
1396 | return (Object)rhs == (Object)lhs; |
||
1397 | } |
||
1398 | return (lhs.ID == rhs.ID); |
||
1399 | } |
||
1400 | |||
1401 | public static bool operator !=(Primitive lhs, Primitive rhs) |
||
1402 | { |
||
1403 | if ((Object)lhs == null || (Object)rhs == null) |
||
1404 | { |
||
1405 | return (Object)rhs != (Object)lhs; |
||
1406 | } |
||
1407 | return !(lhs.ID == rhs.ID); |
||
1408 | } |
||
1409 | |||
1410 | #endregion Operators |
||
1411 | |||
1412 | #region Parameter Packing Methods |
||
1413 | |||
1414 | public static ushort PackBeginCut(float beginCut) |
||
1415 | { |
||
1416 | return (ushort)Math.Round(beginCut / CUT_QUANTA); |
||
1417 | } |
||
1418 | |||
1419 | public static ushort PackEndCut(float endCut) |
||
1420 | { |
||
1421 | return (ushort)(50000 - (ushort)Math.Round(endCut / CUT_QUANTA)); |
||
1422 | } |
||
1423 | |||
1424 | public static byte PackPathScale(float pathScale) |
||
1425 | { |
||
1426 | return (byte)(200 - (byte)Math.Round(pathScale / SCALE_QUANTA)); |
||
1427 | } |
||
1428 | |||
1429 | public static sbyte PackPathShear(float pathShear) |
||
1430 | { |
||
1431 | return (sbyte)Math.Round(pathShear / SHEAR_QUANTA); |
||
1432 | } |
||
1433 | |||
1434 | /// <summary> |
||
1435 | /// Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew |
||
1436 | /// parameters in to signed eight bit values |
||
1437 | /// </summary> |
||
1438 | /// <param name="pathTwist">Floating point parameter to pack</param> |
||
1439 | /// <returns>Signed eight bit value containing the packed parameter</returns> |
||
1440 | public static sbyte PackPathTwist(float pathTwist) |
||
1441 | { |
||
1442 | return (sbyte)Math.Round(pathTwist / SCALE_QUANTA); |
||
1443 | } |
||
1444 | |||
1445 | public static sbyte PackPathTaper(float pathTaper) |
||
1446 | { |
||
1447 | return (sbyte)Math.Round(pathTaper / TAPER_QUANTA); |
||
1448 | } |
||
1449 | |||
1450 | public static byte PackPathRevolutions(float pathRevolutions) |
||
1451 | { |
||
1452 | return (byte)Math.Round((pathRevolutions - 1f) / REV_QUANTA); |
||
1453 | } |
||
1454 | |||
1455 | public static ushort PackProfileHollow(float profileHollow) |
||
1456 | { |
||
1457 | return (ushort)Math.Round(profileHollow / HOLLOW_QUANTA); |
||
1458 | } |
||
1459 | |||
1460 | #endregion Parameter Packing Methods |
||
1461 | |||
1462 | #region Parameter Unpacking Methods |
||
1463 | |||
1464 | public static float UnpackBeginCut(ushort beginCut) |
||
1465 | { |
||
1466 | return (float)beginCut * CUT_QUANTA; |
||
1467 | } |
||
1468 | |||
1469 | public static float UnpackEndCut(ushort endCut) |
||
1470 | { |
||
1471 | return (float)(50000 - endCut) * CUT_QUANTA; |
||
1472 | } |
||
1473 | |||
1474 | public static float UnpackPathScale(byte pathScale) |
||
1475 | { |
||
1476 | return (float)(200 - pathScale) * SCALE_QUANTA; |
||
1477 | } |
||
1478 | |||
1479 | public static float UnpackPathShear(sbyte pathShear) |
||
1480 | { |
||
1481 | return (float)pathShear * SHEAR_QUANTA; |
||
1482 | } |
||
1483 | |||
1484 | /// <summary> |
||
1485 | /// Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew |
||
1486 | /// parameters from signed eight bit integers to floating point values |
||
1487 | /// </summary> |
||
1488 | /// <param name="pathTwist">Signed eight bit value to unpack</param> |
||
1489 | /// <returns>Unpacked floating point value</returns> |
||
1490 | public static float UnpackPathTwist(sbyte pathTwist) |
||
1491 | { |
||
1492 | return (float)pathTwist * SCALE_QUANTA; |
||
1493 | } |
||
1494 | |||
1495 | public static float UnpackPathTaper(sbyte pathTaper) |
||
1496 | { |
||
1497 | return (float)pathTaper * TAPER_QUANTA; |
||
1498 | } |
||
1499 | |||
1500 | public static float UnpackPathRevolutions(byte pathRevolutions) |
||
1501 | { |
||
1502 | return (float)pathRevolutions * REV_QUANTA + 1f; |
||
1503 | } |
||
1504 | |||
1505 | public static float UnpackProfileHollow(ushort profileHollow) |
||
1506 | { |
||
1507 | return (float)profileHollow * HOLLOW_QUANTA; |
||
1508 | } |
||
1509 | |||
1510 | #endregion Parameter Unpacking Methods |
||
1511 | } |
||
1512 | } |