clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
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 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Reflection;
30 using System.Collections;
31 using System.Collections.Generic;
32 using OpenMetaverse;
33 using OpenMetaverse.StructuredData;
34 using log4net;
35  
36 namespace OpenSim.Framework
37 {
38 /// <summary>
39 /// Contains the Avatar's Appearance and methods to manipulate the appearance.
40 /// </summary>
41 public class AvatarAppearance
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44  
45 public readonly static int VISUALPARAM_COUNT = 218;
46  
47 public readonly static int TEXTURE_COUNT = 21;
48 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
49  
50 protected int m_serial = 0;
51 protected byte[] m_visualparams;
52 protected Primitive.TextureEntry m_texture;
53 protected AvatarWearable[] m_wearables;
54 protected Dictionary<int, List<AvatarAttachment>> m_attachments;
55 protected float m_avatarHeight = 0;
56 protected UUID[] m_texturehashes;
57  
58 public virtual int Serial
59 {
60 get { return m_serial; }
61 set { m_serial = value; }
62 }
63  
64 public virtual byte[] VisualParams
65 {
66 get { return m_visualparams; }
67 set { m_visualparams = value; }
68 }
69  
70 public virtual Primitive.TextureEntry Texture
71 {
72 get { return m_texture; }
73 set
74 {
75 // m_log.DebugFormat("[AVATAR APPEARANCE]: Set TextureEntry to {0}", value);
76 m_texture = value;
77 }
78 }
79  
80 public virtual AvatarWearable[] Wearables
81 {
82 get { return m_wearables; }
83 set { m_wearables = value; }
84 }
85  
86 public virtual float AvatarHeight
87 {
88 get { return m_avatarHeight; }
89 set { m_avatarHeight = value; }
90 }
91  
92 public AvatarAppearance()
93 {
94 // m_log.WarnFormat("[AVATAR APPEARANCE]: create empty appearance");
95  
96 m_serial = 0;
97 SetDefaultWearables();
98 SetDefaultTexture();
99 SetDefaultParams();
100 SetHeight();
101 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
102  
103 ResetTextureHashes();
104 }
105  
106 public AvatarAppearance(OSDMap map)
107 {
108 // m_log.WarnFormat("[AVATAR APPEARANCE]: create appearance from OSDMap");
109  
110 Unpack(map);
111 SetHeight();
112 }
113  
114 public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true)
115 {
116 }
117  
118 public AvatarAppearance(AvatarAppearance appearance, bool copyWearables)
119 {
120 // m_log.WarnFormat("[AVATAR APPEARANCE] create from an existing appearance");
121  
122 if (appearance == null)
123 {
124 m_serial = 0;
125 SetDefaultWearables();
126 SetDefaultTexture();
127 SetDefaultParams();
128 SetHeight();
129 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
130  
131 ResetTextureHashes();
132  
133 return;
134 }
135  
136 m_serial = appearance.Serial;
137  
138 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
139 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
140 m_wearables[i] = new AvatarWearable();
141  
142 if (copyWearables && (appearance.Wearables != null))
143 {
144 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
145 SetWearable(i,appearance.Wearables[i]);
146 }
147  
148 m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
149 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
150 m_texturehashes[i] = new UUID(appearance.m_texturehashes[i]);
151  
152 m_texture = null;
153 if (appearance.Texture != null)
154 {
155 byte[] tbytes = appearance.Texture.GetBytes();
156 m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length);
157 }
158  
159 m_visualparams = null;
160 if (appearance.VisualParams != null)
161 m_visualparams = (byte[])appearance.VisualParams.Clone();
162  
163 m_avatarHeight = appearance.m_avatarHeight;
164  
165 // Copy the attachment, force append mode since that ensures consistency
166 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
167 foreach (AvatarAttachment attachment in appearance.GetAttachments())
168 AppendAttachment(new AvatarAttachment(attachment));
169 }
170  
171 public void GetAssetsFrom(AvatarAppearance app)
172 {
173 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
174 {
175 for (int j = 0; j < m_wearables[i].Count; j++)
176 {
177 UUID itemID = m_wearables[i][j].ItemID;
178 UUID assetID = app.Wearables[i].GetAsset(itemID);
179  
180 if (assetID != UUID.Zero)
181 m_wearables[i].Add(itemID, assetID);
182 }
183 }
184 }
185  
186 public void ResetTextureHashes()
187 {
188 m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
189 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
190 m_texturehashes[i] = UUID.Zero;
191 }
192  
193 public UUID GetTextureHash(int textureIndex)
194 {
195 return m_texturehashes[NormalizeBakedTextureIndex(textureIndex)];
196 }
197  
198 public void SetTextureHash(int textureIndex, UUID textureHash)
199 {
200 m_texturehashes[NormalizeBakedTextureIndex(textureIndex)] = new UUID(textureHash);
201 }
202  
203 /// <summary>
204 /// Normalizes the texture index to the actual bake index, this is done to
205 /// accommodate older viewers that send the BAKE_INDICES index rather than
206 /// the actual texture index
207 /// </summary>
208 private int NormalizeBakedTextureIndex(int textureIndex)
209 {
210 // Earlier viewer send the index into the baked index array, just trying to be careful here
211 if (textureIndex < BAKE_INDICES.Length)
212 return BAKE_INDICES[textureIndex];
213  
214 return textureIndex;
215 }
216  
217 public void ClearWearables()
218 {
219 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
220 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
221 m_wearables[i] = new AvatarWearable();
222 }
223  
224 protected virtual void SetDefaultWearables()
225 {
226 m_wearables = AvatarWearable.DefaultWearables;
227 }
228  
229 /// <summary>
230 /// Invalidate all of the baked textures in the appearance, useful
231 /// if you know that none are valid
232 /// </summary>
233 public virtual void ResetAppearance()
234 {
235 // m_log.WarnFormat("[AVATAR APPEARANCE]: Reset appearance");
236  
237 m_serial = 0;
238  
239 SetDefaultTexture();
240 ResetTextureHashes();
241 }
242  
243 protected virtual void SetDefaultParams()
244 {
245 m_visualparams = new byte[] { 33,61,85,23,58,127,63,85,63,42,0,85,63,36,85,95,153,63,34,0,63,109,88,132,63,136,81,85,103,136,127,0,150,150,150,127,0,0,0,0,0,127,0,0,255,127,114,127,99,63,127,140,127,127,0,0,0,191,0,104,0,0,0,0,0,0,0,0,0,145,216,133,0,127,0,127,170,0,0,127,127,109,85,127,127,63,85,42,150,150,150,150,150,150,150,25,150,150,150,0,127,0,0,144,85,127,132,127,85,0,127,127,127,127,127,127,59,127,85,127,127,106,47,79,127,127,204,2,141,66,0,0,127,127,0,0,0,0,127,0,159,0,0,178,127,36,85,131,127,127,127,153,95,0,140,75,27,127,127,0,150,150,198,0,0,63,30,127,165,209,198,127,127,153,204,51,51,255,255,255,204,0,255,150,150,150,150,150,150,150,150,150,150,0,150,150,150,150,150,0,127,127,150,150,150,150,150,150,150,150,0,0,150,51,132,150,150,150 };
246 // for (int i = 0; i < VISUALPARAM_COUNT; i++)
247 // {
248 // m_visualparams[i] = 150;
249 // }
250 }
251  
252 protected virtual void SetDefaultTexture()
253 {
254 m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
255  
256 // for (uint i = 0; i < TEXTURE_COUNT; i++)
257 // m_texture.CreateFace(i).TextureID = new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
258 }
259  
260 /// <summary>
261 /// Set up appearance texture ids.
262 /// </summary>
263 /// <returns>
264 /// True if any existing texture id was changed by the new data.
265 /// False if there were no changes or no existing texture ids.
266 /// </returns>
267 public virtual bool SetTextureEntries(Primitive.TextureEntry textureEntry)
268 {
269 if (textureEntry == null)
270 return false;
271  
272 // There are much simpler versions of this copy that could be
273 // made. We determine if any of the textures actually
274 // changed to know if the appearance should be saved later
275 bool changed = false;
276 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
277 {
278 Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i];
279 Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i];
280  
281 if (newface == null)
282 {
283 if (oldface == null)
284 continue;
285 }
286 else
287 {
288 if (oldface != null && oldface.TextureID == newface.TextureID)
289 continue;
290 }
291  
292 changed = true;
293 }
294  
295 m_texture = textureEntry;
296  
297 return changed;
298 }
299  
300 /// <summary>
301 /// Set up visual parameters for the avatar and refresh the avatar height
302 /// </summary>
303 /// <returns>
304 /// True if any existing visual parameter was changed by the new data.
305 /// False if there were no changes or no existing visual parameters.
306 /// </returns>
307 public virtual bool SetVisualParams(byte[] visualParams)
308 {
309 if (visualParams == null)
310 return false;
311  
312 // There are much simpler versions of this copy that could be
313 // made. We determine if any of the visual parameters actually
314 // changed to know if the appearance should be saved later
315 bool changed = false;
316 for (int i = 0; i < AvatarAppearance.VISUALPARAM_COUNT; i++)
317 {
318 if (visualParams[i] != m_visualparams[i])
319 {
320 // DEBUG ON
321 // m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}",
322 // i,m_visualparams[i],visualParams[i]);
323 // DEBUG OFF
324 m_visualparams[i] = visualParams[i];
325 changed = true;
326 }
327 }
328  
329 // Reset the height if the visual parameters actually changed
330 if (changed)
331 SetHeight();
332  
333 return changed;
334 }
335  
336 public virtual void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
337 {
338 SetTextureEntries(textureEntry);
339 SetVisualParams(visualParams);
340 }
341  
342 /// <summary>
343 /// Set avatar height by a calculation based on their visual parameters.
344 /// </summary>
345 public virtual void SetHeight()
346 {
347 // Start with shortest possible female avatar height
348 m_avatarHeight = 1.14597f;
349 // Add offset for male avatars
350 if (m_visualparams[(int)VPElement.SHAPE_MALE] != 0)
351 m_avatarHeight += 0.0848f;
352 // Add offsets for visual params
353 m_avatarHeight += 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f
354 + 0.08117f * (float)m_visualparams[(int)VPElement.SHAPE_HEAD_SIZE] / 255.0f
355 + 0.3836f * (float)m_visualparams[(int)VPElement.SHAPE_LEG_LENGTH] / 255.0f
356 + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f
357 + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f
358 + 0.076f * (float)m_visualparams[(int)VPElement.SHAPE_NECK_LENGTH] / 255.0f;
359 }
360  
361 public virtual void SetWearable(int wearableId, AvatarWearable wearable)
362 {
363 // DEBUG ON
364 // m_log.WarnFormat("[AVATARAPPEARANCE] set wearable {0} --> {1}:{2}",wearableId,wearable.ItemID,wearable.AssetID);
365 // DEBUG OFF
366 m_wearables[wearableId].Clear();
367 for (int i = 0; i < wearable.Count; i++)
368 m_wearables[wearableId].Add(wearable[i].ItemID, wearable[i].AssetID);
369 }
370  
371 // DEBUG ON
372 public override String ToString()
373 {
374 String s = "";
375  
376 s += String.Format("Serial: {0}\n",m_serial);
377  
378 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
379 if (m_texture.FaceTextures[i] != null)
380 s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID);
381  
382 foreach (AvatarWearable awear in m_wearables)
383 {
384 for (int i = 0; i < awear.Count; i++)
385 s += String.Format("Wearable: item={0}, asset={1}\n",awear[i].ItemID,awear[i].AssetID);
386 }
387  
388 s += "Visual Params: ";
389 for (uint j = 0; j < AvatarAppearance.VISUALPARAM_COUNT; j++)
390 s += String.Format("{0},",m_visualparams[j]);
391 s += "\n";
392  
393 return s;
394 }
395 // DEBUG OFF
396  
397 /// <summary>
398 /// Get a list of the attachments.
399 /// </summary>
400 /// <remarks>
401 /// There may be duplicate attachpoints
402 /// </remarks>
403 public List<AvatarAttachment> GetAttachments()
404 {
405 List<AvatarAttachment> alist = new List<AvatarAttachment>();
406  
407 lock (m_attachments)
408 {
409 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
410 {
411 foreach (AvatarAttachment attach in kvp.Value)
412 alist.Add(new AvatarAttachment(attach));
413 }
414 }
415  
416 return alist;
417 }
418  
419 internal void AppendAttachment(AvatarAttachment attach)
420 {
421 // m_log.DebugFormat(
422 // "[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}",
423 // attach.ItemID, attach.AssetID, attach.AttachPoint);
424  
425 lock (m_attachments)
426 {
427 if (!m_attachments.ContainsKey(attach.AttachPoint))
428 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
429  
430 m_attachments[attach.AttachPoint].Add(attach);
431 }
432 }
433  
434 internal void ReplaceAttachment(AvatarAttachment attach)
435 {
436 // m_log.DebugFormat(
437 // "[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}",
438 // attach.ItemID, attach.AssetID, attach.AttachPoint);
439  
440 lock (m_attachments)
441 {
442 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
443 m_attachments[attach.AttachPoint].Add(attach);
444 }
445 }
446  
447 /// <summary>
448 /// Set an attachment
449 /// </summary>
450 /// <remarks>
451 /// If the attachpoint has the
452 /// 0x80 bit set then we assume this is an append
453 /// operation otherwise we replace whatever is
454 /// currently attached at the attachpoint
455 /// </remarks>
456 /// <param name="attachpoint"></param>
457 /// <param name="item">If UUID.Zero, then an any attachment at the attachpoint is removed.</param>
458 /// <param name="asset"></param>
459 /// <returns>
460 /// return true if something actually changed
461 /// </returns>
462 public bool SetAttachment(int attachpoint, UUID item, UUID asset)
463 {
464 // m_log.DebugFormat(
465 // "[AVATAR APPEARANCE]: Setting attachment at {0} with item ID {1}, asset ID {2}",
466 // attachpoint, item, asset);
467  
468 if (attachpoint == 0)
469 return false;
470  
471 lock (m_attachments)
472 {
473 if (item == UUID.Zero)
474 {
475 if (m_attachments.ContainsKey(attachpoint))
476 {
477 m_attachments.Remove(attachpoint);
478 return true;
479 }
480  
481 return false;
482 }
483  
484 // When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
485 // the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
486 // we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
487 // later fail unless the attachment is detached and reattached.
488 //
489 // Therefore, we will carry on with the set if the existing attachment has no asset id.
490 AvatarAttachment existingAttachment = GetAttachmentForItem(item);
491 if (existingAttachment != null)
492 {
493 // m_log.DebugFormat(
494 // "[AVATAR APPEARANCE]: Found existing attachment for {0}, asset {1} at point {2}",
495 // existingAttachment.ItemID, existingAttachment.AssetID, existingAttachment.AttachPoint);
496  
497 if (existingAttachment.AssetID != UUID.Zero && existingAttachment.AttachPoint == (attachpoint & 0x7F))
498 {
499 m_log.DebugFormat(
500 "[AVATAR APPEARANCE]: Ignoring attempt to attach an already attached item {0} at point {1}",
501 item, attachpoint);
502  
503 return false;
504 }
505 else
506 {
507 // Remove it here so that the later append does not add a second attachment but we still update
508 // the assetID
509 DetachAttachment(existingAttachment.ItemID);
510 }
511 }
512  
513 // check if this is an append or a replace, 0x80 marks it as an append
514 if ((attachpoint & 0x80) > 0)
515 {
516 // strip the append bit
517 int point = attachpoint & 0x7F;
518 AppendAttachment(new AvatarAttachment(point, item, asset));
519 }
520 else
521 {
522 ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
523 }
524 }
525  
526 return true;
527 }
528  
529 /// <summary>
530 /// If the item is already attached, return it.
531 /// </summary>
532 /// <param name="itemID"></param>
533 /// <returns>Returns null if this item is not attached.</returns>
534 public AvatarAttachment GetAttachmentForItem(UUID itemID)
535 {
536 lock (m_attachments)
537 {
538 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
539 {
540 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
541 if (index >= 0)
542 return kvp.Value[index];
543 }
544 }
545  
546 return null;
547 }
548  
549 public int GetAttachpoint(UUID itemID)
550 {
551 lock (m_attachments)
552 {
553 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
554 {
555 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
556 if (index >= 0)
557 return kvp.Key;
558 }
559 }
560  
561 return 0;
562 }
563  
564 public bool DetachAttachment(UUID itemID)
565 {
566 lock (m_attachments)
567 {
568 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
569 {
570 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
571 if (index >= 0)
572 {
573 // m_log.DebugFormat(
574 // "[AVATAR APPEARANCE]: Detaching attachment {0}, index {1}, point {2}",
575 // m_attachments[kvp.Key][index].ItemID, index, m_attachments[kvp.Key][index].AttachPoint);
576  
577 // Remove it from the list of attachments at that attach point
578 m_attachments[kvp.Key].RemoveAt(index);
579  
580 // And remove the list if there are no more attachments here
581 if (m_attachments[kvp.Key].Count == 0)
582 m_attachments.Remove(kvp.Key);
583  
584 return true;
585 }
586 }
587 }
588  
589 return false;
590 }
591  
592 public void ClearAttachments()
593 {
594 lock (m_attachments)
595 m_attachments.Clear();
596 }
597  
598 #region Packing Functions
599  
600 /// <summary>
601 /// Create an OSDMap from the appearance data
602 /// </summary>
603 public OSDMap Pack()
604 {
605 OSDMap data = new OSDMap();
606  
607 data["serial"] = OSD.FromInteger(m_serial);
608 data["height"] = OSD.FromReal(m_avatarHeight);
609  
610 // Hashes
611 OSDArray hashes = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
612 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
613 hashes.Add(OSD.FromUUID(m_texturehashes[i]));
614 data["hashes"] = hashes;
615  
616 // Wearables
617 OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
618 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
619 wears.Add(m_wearables[i].Pack());
620 data["wearables"] = wears;
621  
622 // Avatar Textures
623 OSDArray textures = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
624 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
625 {
626 if (m_texture.FaceTextures[i] != null)
627 textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID));
628 else
629 textures.Add(OSD.FromUUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
630 }
631 data["textures"] = textures;
632  
633 // Visual Parameters
634 OSDBinary visualparams = new OSDBinary(m_visualparams);
635 data["visualparams"] = visualparams;
636  
637 // Attachments
638 List<AvatarAttachment> attachments = GetAttachments();
639 OSDArray attachs = new OSDArray(attachments.Count);
640 foreach (AvatarAttachment attach in GetAttachments())
641 attachs.Add(attach.Pack());
642 data["attachments"] = attachs;
643  
644 return data;
645 }
646  
647 /// <summary>
648 /// Unpack and OSDMap and initialize the appearance
649 /// from it
650 /// </summary>
651 public void Unpack(OSDMap data)
652 {
653 if ((data != null) && (data["serial"] != null))
654 m_serial = data["serial"].AsInteger();
655 if ((data != null) && (data["height"] != null))
656 m_avatarHeight = (float)data["height"].AsReal();
657  
658 try
659 {
660 // Hashes
661 m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT];
662 if ((data != null) && (data["hashes"] != null) && (data["hashes"]).Type == OSDType.Array)
663 {
664 OSDArray hashes = (OSDArray)(data["hashes"]);
665 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
666 {
667 UUID hashID = UUID.Zero;
668 if (i < hashes.Count && hashes[i] != null)
669 hashID = hashes[i].AsUUID();
670 m_texturehashes[i] = hashID;
671 }
672 }
673 else
674 {
675 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
676 m_texturehashes[i] = UUID.Zero;
677 }
678  
679 // Wearables
680 SetDefaultWearables();
681 if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)
682 {
683 OSDArray wears = (OSDArray)(data["wearables"]);
684 for (int i = 0; i < wears.Count; i++)
685 m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
686 }
687 else
688 {
689 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack wearables");
690 }
691  
692 // Avatar Textures
693 SetDefaultTexture();
694 if ((data != null) && (data["textures"] != null) && (data["textures"]).Type == OSDType.Array)
695 {
696 OSDArray textures = (OSDArray)(data["textures"]);
697 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++)
698 {
699 UUID textureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
700 if (textures[i] != null)
701 textureID = textures[i].AsUUID();
702 m_texture.CreateFace((uint)i).TextureID = new UUID(textureID);
703 }
704 }
705 else
706 {
707 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack textures");
708 }
709  
710 // Visual Parameters
711 SetDefaultParams();
712 if ((data != null) && (data["visualparams"] != null))
713 {
714 if ((data["visualparams"].Type == OSDType.Binary) || (data["visualparams"].Type == OSDType.Array))
715 m_visualparams = data["visualparams"].AsBinary();
716 }
717 else
718 {
719 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack visual parameters");
720 }
721  
722 // Attachments
723 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
724 if ((data != null) && (data["attachments"] != null) && (data["attachments"]).Type == OSDType.Array)
725 {
726 OSDArray attachs = (OSDArray)(data["attachments"]);
727 for (int i = 0; i < attachs.Count; i++)
728 {
729 AvatarAttachment att = new AvatarAttachment((OSDMap)attachs[i]);
730 AppendAttachment(att);
731  
732 // m_log.DebugFormat(
733 // "[AVATAR APPEARANCE]: Unpacked attachment itemID {0}, assetID {1}, point {2}",
734 // att.ItemID, att.AssetID, att.AttachPoint);
735 }
736 }
737 }
738 catch (Exception e)
739 {
740 m_log.ErrorFormat("[AVATAR APPEARANCE]: unpack failed badly: {0}{1}", e.Message, e.StackTrace);
741 }
742 }
743  
744 #endregion
745  
746 #region VPElement
747  
748 /// <summary>
749 /// Viewer Params Array Element for AgentSetAppearance
750 /// Generated from LibOMV's Visual Params list
751 /// </summary>
752 public enum VPElement : int
753 {
754 /// <summary>
755 /// Brow Size - Small 0--+255 Large
756 /// </summary>
757 SHAPE_BIG_BROW = 0,
758 /// <summary>
759 /// Nose Size - Small 0--+255 Large
760 /// </summary>
761 SHAPE_NOSE_BIG_OUT = 1,
762 /// <summary>
763 /// Nostril Width - Narrow 0--+255 Broad
764 /// </summary>
765 SHAPE_BROAD_NOSTRILS = 2,
766 /// <summary>
767 /// Chin Cleft - Round 0--+255 Cleft
768 /// </summary>
769 SHAPE_CLEFT_CHIN = 3,
770 /// <summary>
771 /// Nose Tip Shape - Pointy 0--+255 Bulbous
772 /// </summary>
773 SHAPE_BULBOUS_NOSE_TIP = 4,
774 /// <summary>
775 /// Chin Angle - Chin Out 0--+255 Chin In
776 /// </summary>
777 SHAPE_WEAK_CHIN = 5,
778 /// <summary>
779 /// Chin-Neck - Tight Chin 0--+255 Double Chin
780 /// </summary>
781 SHAPE_DOUBLE_CHIN = 6,
782 /// <summary>
783 /// Lower Cheeks - Well-Fed 0--+255 Sunken
784 /// </summary>
785 SHAPE_SUNKEN_CHEEKS = 7,
786 /// <summary>
787 /// Upper Bridge - Low 0--+255 High
788 /// </summary>
789 SHAPE_NOBLE_NOSE_BRIDGE = 8,
790 /// <summary>
791 /// - Less 0--+255 More
792 /// </summary>
793 SHAPE_JOWLS = 9,
794 /// <summary>
795 /// Upper Chin Cleft - Round 0--+255 Cleft
796 /// </summary>
797 SHAPE_CLEFT_CHIN_UPPER = 10,
798 /// <summary>
799 /// Cheek Bones - Low 0--+255 High
800 /// </summary>
801 SHAPE_HIGH_CHEEK_BONES = 11,
802 /// <summary>
803 /// Ear Angle - In 0--+255 Out
804 /// </summary>
805 SHAPE_EARS_OUT = 12,
806 /// <summary>
807 /// Eyebrow Points - Smooth 0--+255 Pointy
808 /// </summary>
809 HAIR_POINTY_EYEBROWS = 13,
810 /// <summary>
811 /// Jaw Shape - Pointy 0--+255 Square
812 /// </summary>
813 SHAPE_SQUARE_JAW = 14,
814 /// <summary>
815 /// Upper Cheeks - Thin 0--+255 Puffy
816 /// </summary>
817 SHAPE_PUFFY_UPPER_CHEEKS = 15,
818 /// <summary>
819 /// Nose Tip Angle - Downturned 0--+255 Upturned
820 /// </summary>
821 SHAPE_UPTURNED_NOSE_TIP = 16,
822 /// <summary>
823 /// Nose Thickness - Thin Nose 0--+255 Bulbous Nose
824 /// </summary>
825 SHAPE_BULBOUS_NOSE = 17,
826 /// <summary>
827 /// Upper Eyelid Fold - Uncreased 0--+255 Creased
828 /// </summary>
829 SHAPE_UPPER_EYELID_FOLD = 18,
830 /// <summary>
831 /// Attached Earlobes - Unattached 0--+255 Attached
832 /// </summary>
833 SHAPE_ATTACHED_EARLOBES = 19,
834 /// <summary>
835 /// Eye Bags - Smooth 0--+255 Baggy
836 /// </summary>
837 SHAPE_BAGGY_EYES = 20,
838 /// <summary>
839 /// Eye Opening - Narrow 0--+255 Wide
840 /// </summary>
841 SHAPE_WIDE_EYES = 21,
842 /// <summary>
843 /// Lip Cleft - Narrow 0--+255 Wide
844 /// </summary>
845 SHAPE_WIDE_LIP_CLEFT = 22,
846 /// <summary>
847 /// Bridge Width - Narrow 0--+255 Wide
848 /// </summary>
849 SHAPE_WIDE_NOSE_BRIDGE = 23,
850 /// <summary>
851 /// Eyebrow Arc - Flat 0--+255 Arced
852 /// </summary>
853 HAIR_ARCED_EYEBROWS = 24,
854 /// <summary>
855 /// Height - Short 0--+255 Tall
856 /// </summary>
857 SHAPE_HEIGHT = 25,
858 /// <summary>
859 /// Body Thickness - Body Thin 0--+255 Body Thick
860 /// </summary>
861 SHAPE_THICKNESS = 26,
862 /// <summary>
863 /// Ear Size - Small 0--+255 Large
864 /// </summary>
865 SHAPE_BIG_EARS = 27,
866 /// <summary>
867 /// Shoulders - Narrow 0--+255 Broad
868 /// </summary>
869 SHAPE_SHOULDERS = 28,
870 /// <summary>
871 /// Hip Width - Narrow 0--+255 Wide
872 /// </summary>
873 SHAPE_HIP_WIDTH = 29,
874 /// <summary>
875 /// - Short Torso 0--+255 Long Torso
876 /// </summary>
877 SHAPE_TORSO_LENGTH = 30,
878 SHAPE_MALE = 31,
879 /// <summary>
880 /// - Short 0--+255 Long
881 /// </summary>
882 GLOVES_GLOVE_LENGTH = 32,
883 /// <summary>
884 /// - Darker 0--+255 Lighter
885 /// </summary>
886 EYES_EYE_LIGHTNESS = 33,
887 /// <summary>
888 /// - Natural 0--+255 Unnatural
889 /// </summary>
890 EYES_EYE_COLOR = 34,
891 /// <summary>
892 /// - Small 0--+255 Large
893 /// </summary>
894 SHAPE_BREAST_SIZE = 35,
895 /// <summary>
896 /// - None 0--+255 Wild
897 /// </summary>
898 SKIN_RAINBOW_COLOR = 36,
899 /// <summary>
900 /// Ruddiness - Pale 0--+255 Ruddy
901 /// </summary>
902 SKIN_RED_SKIN = 37,
903 /// <summary>
904 /// - Light 0--+255 Dark
905 /// </summary>
906 SKIN_PIGMENT = 38,
907 HAIR_RAINBOW_COLOR_39 = 39,
908 /// <summary>
909 /// - No Red 0--+255 Very Red
910 /// </summary>
911 HAIR_RED_HAIR = 40,
912 /// <summary>
913 /// - Black 0--+255 Blonde
914 /// </summary>
915 HAIR_BLONDE_HAIR = 41,
916 /// <summary>
917 /// - No White 0--+255 All White
918 /// </summary>
919 HAIR_WHITE_HAIR = 42,
920 /// <summary>
921 /// - Less Rosy 0--+255 More Rosy
922 /// </summary>
923 SKIN_ROSY_COMPLEXION = 43,
924 /// <summary>
925 /// - Darker 0--+255 Pinker
926 /// </summary>
927 SKIN_LIP_PINKNESS = 44,
928 /// <summary>
929 /// - Thin Eyebrows 0--+255 Bushy Eyebrows
930 /// </summary>
931 HAIR_EYEBROW_SIZE = 45,
932 /// <summary>
933 /// - Short 0--+255 Long
934 /// </summary>
935 HAIR_FRONT_FRINGE = 46,
936 /// <summary>
937 /// - Short 0--+255 Long
938 /// </summary>
939 HAIR_SIDE_FRINGE = 47,
940 /// <summary>
941 /// - Short 0--+255 Long
942 /// </summary>
943 HAIR_BACK_FRINGE = 48,
944 /// <summary>
945 /// - Short 0--+255 Long
946 /// </summary>
947 HAIR_HAIR_FRONT = 49,
948 /// <summary>
949 /// - Short 0--+255 Long
950 /// </summary>
951 HAIR_HAIR_SIDES = 50,
952 /// <summary>
953 /// - Short 0--+255 Long
954 /// </summary>
955 HAIR_HAIR_BACK = 51,
956 /// <summary>
957 /// - Sweep Forward 0--+255 Sweep Back
958 /// </summary>
959 HAIR_HAIR_SWEEP = 52,
960 /// <summary>
961 /// - Left 0--+255 Right
962 /// </summary>
963 HAIR_HAIR_TILT = 53,
964 /// <summary>
965 /// Middle Part - No Part 0--+255 Part
966 /// </summary>
967 HAIR_HAIR_PART_MIDDLE = 54,
968 /// <summary>
969 /// Right Part - No Part 0--+255 Part
970 /// </summary>
971 HAIR_HAIR_PART_RIGHT = 55,
972 /// <summary>
973 /// Left Part - No Part 0--+255 Part
974 /// </summary>
975 HAIR_HAIR_PART_LEFT = 56,
976 /// <summary>
977 /// Full Hair Sides - Mowhawk 0--+255 Full Sides
978 /// </summary>
979 HAIR_HAIR_SIDES_FULL = 57,
980 /// <summary>
981 /// - Less 0--+255 More
982 /// </summary>
983 SKIN_BODY_DEFINITION = 58,
984 /// <summary>
985 /// Lip Width - Narrow Lips 0--+255 Wide Lips
986 /// </summary>
987 SHAPE_LIP_WIDTH = 59,
988 /// <summary>
989 /// - Small 0--+255 Big
990 /// </summary>
991 SHAPE_BELLY_SIZE = 60,
992 /// <summary>
993 /// - Less 0--+255 More
994 /// </summary>
995 SKIN_FACIAL_DEFINITION = 61,
996 /// <summary>
997 /// - Less 0--+255 More
998 /// </summary>
999 SKIN_WRINKLES = 62,
1000 /// <summary>
1001 /// - Less 0--+255 More
1002 /// </summary>
1003 SKIN_FRECKLES = 63,
1004 /// <summary>
1005 /// - Short Sideburns 0--+255 Mutton Chops
1006 /// </summary>
1007 HAIR_SIDEBURNS = 64,
1008 /// <summary>
1009 /// - Chaplin 0--+255 Handlebars
1010 /// </summary>
1011 HAIR_MOUSTACHE = 65,
1012 /// <summary>
1013 /// - Less soul 0--+255 More soul
1014 /// </summary>
1015 HAIR_SOULPATCH = 66,
1016 /// <summary>
1017 /// - Less Curtains 0--+255 More Curtains
1018 /// </summary>
1019 HAIR_CHIN_CURTAINS = 67,
1020 /// <summary>
1021 /// Rumpled Hair - Smooth Hair 0--+255 Rumpled Hair
1022 /// </summary>
1023 HAIR_HAIR_RUMPLED = 68,
1024 /// <summary>
1025 /// Big Hair Front - Less 0--+255 More
1026 /// </summary>
1027 HAIR_HAIR_BIG_FRONT = 69,
1028 /// <summary>
1029 /// Big Hair Top - Less 0--+255 More
1030 /// </summary>
1031 HAIR_HAIR_BIG_TOP = 70,
1032 /// <summary>
1033 /// Big Hair Back - Less 0--+255 More
1034 /// </summary>
1035 HAIR_HAIR_BIG_BACK = 71,
1036 /// <summary>
1037 /// Spiked Hair - No Spikes 0--+255 Big Spikes
1038 /// </summary>
1039 HAIR_HAIR_SPIKED = 72,
1040 /// <summary>
1041 /// Chin Depth - Shallow 0--+255 Deep
1042 /// </summary>
1043 SHAPE_DEEP_CHIN = 73,
1044 /// <summary>
1045 /// Part Bangs - No Part 0--+255 Part Bangs
1046 /// </summary>
1047 HAIR_BANGS_PART_MIDDLE = 74,
1048 /// <summary>
1049 /// Head Shape - More Square 0--+255 More Round
1050 /// </summary>
1051 SHAPE_HEAD_SHAPE = 75,
1052 /// <summary>
1053 /// Eye Spacing - Close Set Eyes 0--+255 Far Set Eyes
1054 /// </summary>
1055 SHAPE_EYE_SPACING = 76,
1056 /// <summary>
1057 /// - Low Heels 0--+255 High Heels
1058 /// </summary>
1059 SHOES_HEEL_HEIGHT = 77,
1060 /// <summary>
1061 /// - Low Platforms 0--+255 High Platforms
1062 /// </summary>
1063 SHOES_PLATFORM_HEIGHT = 78,
1064 /// <summary>
1065 /// - Thin Lips 0--+255 Fat Lips
1066 /// </summary>
1067 SHAPE_LIP_THICKNESS = 79,
1068 /// <summary>
1069 /// Mouth Position - High 0--+255 Low
1070 /// </summary>
1071 SHAPE_MOUTH_HEIGHT = 80,
1072 /// <summary>
1073 /// Breast Buoyancy - Less Gravity 0--+255 More Gravity
1074 /// </summary>
1075 SHAPE_BREAST_GRAVITY = 81,
1076 /// <summary>
1077 /// Platform Width - Narrow 0--+255 Wide
1078 /// </summary>
1079 SHOES_SHOE_PLATFORM_WIDTH = 82,
1080 /// <summary>
1081 /// - Pointy Heels 0--+255 Thick Heels
1082 /// </summary>
1083 SHOES_HEEL_SHAPE = 83,
1084 /// <summary>
1085 /// - Pointy 0--+255 Square
1086 /// </summary>
1087 SHOES_TOE_SHAPE = 84,
1088 /// <summary>
1089 /// Foot Size - Small 0--+255 Big
1090 /// </summary>
1091 SHAPE_FOOT_SIZE = 85,
1092 /// <summary>
1093 /// Nose Width - Narrow 0--+255 Wide
1094 /// </summary>
1095 SHAPE_WIDE_NOSE = 86,
1096 /// <summary>
1097 /// Eyelash Length - Short 0--+255 Long
1098 /// </summary>
1099 SHAPE_EYELASHES_LONG = 87,
1100 /// <summary>
1101 /// - Short 0--+255 Long
1102 /// </summary>
1103 UNDERSHIRT_SLEEVE_LENGTH = 88,
1104 /// <summary>
1105 /// - Short 0--+255 Long
1106 /// </summary>
1107 UNDERSHIRT_BOTTOM = 89,
1108 /// <summary>
1109 /// - Low 0--+255 High
1110 /// </summary>
1111 UNDERSHIRT_COLLAR_FRONT = 90,
1112 JACKET_SLEEVE_LENGTH_91 = 91,
1113 JACKET_COLLAR_FRONT_92 = 92,
1114 /// <summary>
1115 /// Jacket Length - Short 0--+255 Long
1116 /// </summary>
1117 JACKET_BOTTOM_LENGTH_LOWER = 93,
1118 /// <summary>
1119 /// Open Front - Open 0--+255 Closed
1120 /// </summary>
1121 JACKET_OPEN_JACKET = 94,
1122 /// <summary>
1123 /// - Short 0--+255 Tall
1124 /// </summary>
1125 SHOES_SHOE_HEIGHT = 95,
1126 /// <summary>
1127 /// - Short 0--+255 Long
1128 /// </summary>
1129 SOCKS_SOCKS_LENGTH = 96,
1130 /// <summary>
1131 /// - Short 0--+255 Long
1132 /// </summary>
1133 UNDERPANTS_PANTS_LENGTH = 97,
1134 /// <summary>
1135 /// - Low 0--+255 High
1136 /// </summary>
1137 UNDERPANTS_PANTS_WAIST = 98,
1138 /// <summary>
1139 /// Cuff Flare - Tight Cuffs 0--+255 Flared Cuffs
1140 /// </summary>
1141 PANTS_LEG_PANTFLAIR = 99,
1142 /// <summary>
1143 /// - More Vertical 0--+255 More Sloped
1144 /// </summary>
1145 SHAPE_FOREHEAD_ANGLE = 100,
1146 /// <summary>
1147 /// - Less Body Fat 0--+255 More Body Fat
1148 /// </summary>
1149 SHAPE_BODY_FAT = 101,
1150 /// <summary>
1151 /// Pants Crotch - High and Tight 0--+255 Low and Loose
1152 /// </summary>
1153 PANTS_LOW_CROTCH = 102,
1154 /// <summary>
1155 /// Egg Head - Chin Heavy 0--+255 Forehead Heavy
1156 /// </summary>
1157 SHAPE_EGG_HEAD = 103,
1158 /// <summary>
1159 /// Head Stretch - Squash Head 0--+255 Stretch Head
1160 /// </summary>
1161 SHAPE_SQUASH_STRETCH_HEAD = 104,
1162 /// <summary>
1163 /// Torso Muscles - Less Muscular 0--+255 More Muscular
1164 /// </summary>
1165 SHAPE_TORSO_MUSCLES = 105,
1166 /// <summary>
1167 /// Outer Eye Corner - Corner Down 0--+255 Corner Up
1168 /// </summary>
1169 SHAPE_EYELID_CORNER_UP = 106,
1170 /// <summary>
1171 /// - Less Muscular 0--+255 More Muscular
1172 /// </summary>
1173 SHAPE_LEG_MUSCLES = 107,
1174 /// <summary>
1175 /// Lip Fullness - Less Full 0--+255 More Full
1176 /// </summary>
1177 SHAPE_TALL_LIPS = 108,
1178 /// <summary>
1179 /// Toe Thickness - Flat Toe 0--+255 Thick Toe
1180 /// </summary>
1181 SHOES_SHOE_TOE_THICK = 109,
1182 /// <summary>
1183 /// Crooked Nose - Nose Left 0--+255 Nose Right
1184 /// </summary>
1185 SHAPE_CROOKED_NOSE = 110,
1186 /// <summary>
1187 /// - Corner Down 0--+255 Corner Up
1188 /// </summary>
1189 SHAPE_MOUTH_CORNER = 111,
1190 /// <summary>
1191 /// - Shear Right Up 0--+255 Shear Left Up
1192 /// </summary>
1193 SHAPE_FACE_SHEAR = 112,
1194 /// <summary>
1195 /// Shift Mouth - Shift Left 0--+255 Shift Right
1196 /// </summary>
1197 SHAPE_SHIFT_MOUTH = 113,
1198 /// <summary>
1199 /// Eye Pop - Pop Right Eye 0--+255 Pop Left Eye
1200 /// </summary>
1201 SHAPE_POP_EYE = 114,
1202 /// <summary>
1203 /// Jaw Jut - Overbite 0--+255 Underbite
1204 /// </summary>
1205 SHAPE_JAW_JUT = 115,
1206 /// <summary>
1207 /// Shear Back - Full Back 0--+255 Sheared Back
1208 /// </summary>
1209 HAIR_HAIR_SHEAR_BACK = 116,
1210 /// <summary>
1211 /// - Small Hands 0--+255 Large Hands
1212 /// </summary>
1213 SHAPE_HAND_SIZE = 117,
1214 /// <summary>
1215 /// Love Handles - Less Love 0--+255 More Love
1216 /// </summary>
1217 SHAPE_LOVE_HANDLES = 118,
1218 SHAPE_TORSO_MUSCLES_119 = 119,
1219 /// <summary>
1220 /// Head Size - Small Head 0--+255 Big Head
1221 /// </summary>
1222 SHAPE_HEAD_SIZE = 120,
1223 /// <summary>
1224 /// - Skinny Neck 0--+255 Thick Neck
1225 /// </summary>
1226 SHAPE_NECK_THICKNESS = 121,
1227 /// <summary>
1228 /// Breast Cleavage - Separate 0--+255 Join
1229 /// </summary>
1230 SHAPE_BREAST_FEMALE_CLEAVAGE = 122,
1231 /// <summary>
1232 /// Pectorals - Big Pectorals 0--+255 Sunken Chest
1233 /// </summary>
1234 SHAPE_CHEST_MALE_NO_PECS = 123,
1235 /// <summary>
1236 /// Eye Size - Beady Eyes 0--+255 Anime Eyes
1237 /// </summary>
1238 SHAPE_EYE_SIZE = 124,
1239 /// <summary>
1240 /// - Short Legs 0--+255 Long Legs
1241 /// </summary>
1242 SHAPE_LEG_LENGTH = 125,
1243 /// <summary>
1244 /// - Short Arms 0--+255 Long arms
1245 /// </summary>
1246 SHAPE_ARM_LENGTH = 126,
1247 /// <summary>
1248 /// - Pink 0--+255 Black
1249 /// </summary>
1250 SKIN_LIPSTICK_COLOR = 127,
1251 /// <summary>
1252 /// - No Lipstick 0--+255 More Lipstick
1253 /// </summary>
1254 SKIN_LIPSTICK = 128,
1255 /// <summary>
1256 /// - No Lipgloss 0--+255 Glossy
1257 /// </summary>
1258 SKIN_LIPGLOSS = 129,
1259 /// <summary>
1260 /// - No Eyeliner 0--+255 Full Eyeliner
1261 /// </summary>
1262 SKIN_EYELINER = 130,
1263 /// <summary>
1264 /// - No Blush 0--+255 More Blush
1265 /// </summary>
1266 SKIN_BLUSH = 131,
1267 /// <summary>
1268 /// - Pink 0--+255 Orange
1269 /// </summary>
1270 SKIN_BLUSH_COLOR = 132,
1271 /// <summary>
1272 /// - Clear 0--+255 Opaque
1273 /// </summary>
1274 SKIN_OUT_SHDW_OPACITY = 133,
1275 /// <summary>
1276 /// - No Eyeshadow 0--+255 More Eyeshadow
1277 /// </summary>
1278 SKIN_OUTER_SHADOW = 134,
1279 /// <summary>
1280 /// - Light 0--+255 Dark
1281 /// </summary>
1282 SKIN_OUT_SHDW_COLOR = 135,
1283 /// <summary>
1284 /// - No Eyeshadow 0--+255 More Eyeshadow
1285 /// </summary>
1286 SKIN_INNER_SHADOW = 136,
1287 /// <summary>
1288 /// - No Polish 0--+255 Painted Nails
1289 /// </summary>
1290 SKIN_NAIL_POLISH = 137,
1291 /// <summary>
1292 /// - Clear 0--+255 Opaque
1293 /// </summary>
1294 SKIN_BLUSH_OPACITY = 138,
1295 /// <summary>
1296 /// - Light 0--+255 Dark
1297 /// </summary>
1298 SKIN_IN_SHDW_COLOR = 139,
1299 /// <summary>
1300 /// - Clear 0--+255 Opaque
1301 /// </summary>
1302 SKIN_IN_SHDW_OPACITY = 140,
1303 /// <summary>
1304 /// - Dark Green 0--+255 Black
1305 /// </summary>
1306 SKIN_EYELINER_COLOR = 141,
1307 /// <summary>
1308 /// - Pink 0--+255 Black
1309 /// </summary>
1310 SKIN_NAIL_POLISH_COLOR = 142,
1311 /// <summary>
1312 /// - Sparse 0--+255 Dense
1313 /// </summary>
1314 HAIR_EYEBROW_DENSITY = 143,
1315 /// <summary>
1316 /// - 5 O'Clock Shadow 0--+255 Bushy Hair
1317 /// </summary>
1318 HAIR_HAIR_THICKNESS = 144,
1319 /// <summary>
1320 /// Saddle Bags - Less Saddle 0--+255 More Saddle
1321 /// </summary>
1322 SHAPE_SADDLEBAGS = 145,
1323 /// <summary>
1324 /// Taper Back - Wide Back 0--+255 Narrow Back
1325 /// </summary>
1326 HAIR_HAIR_TAPER_BACK = 146,
1327 /// <summary>
1328 /// Taper Front - Wide Front 0--+255 Narrow Front
1329 /// </summary>
1330 HAIR_HAIR_TAPER_FRONT = 147,
1331 /// <summary>
1332 /// - Short Neck 0--+255 Long Neck
1333 /// </summary>
1334 SHAPE_NECK_LENGTH = 148,
1335 /// <summary>
1336 /// Eyebrow Height - Higher 0--+255 Lower
1337 /// </summary>
1338 HAIR_LOWER_EYEBROWS = 149,
1339 /// <summary>
1340 /// Lower Bridge - Low 0--+255 High
1341 /// </summary>
1342 SHAPE_LOWER_BRIDGE_NOSE = 150,
1343 /// <summary>
1344 /// Nostril Division - High 0--+255 Low
1345 /// </summary>
1346 SHAPE_LOW_SEPTUM_NOSE = 151,
1347 /// <summary>
1348 /// Jaw Angle - Low Jaw 0--+255 High Jaw
1349 /// </summary>
1350 SHAPE_JAW_ANGLE = 152,
1351 /// <summary>
1352 /// Shear Front - Full Front 0--+255 Sheared Front
1353 /// </summary>
1354 HAIR_HAIR_SHEAR_FRONT = 153,
1355 /// <summary>
1356 /// - Less Volume 0--+255 More Volume
1357 /// </summary>
1358 HAIR_HAIR_VOLUME = 154,
1359 /// <summary>
1360 /// Lip Cleft Depth - Shallow 0--+255 Deep
1361 /// </summary>
1362 SHAPE_LIP_CLEFT_DEEP = 155,
1363 /// <summary>
1364 /// Puffy Eyelids - Flat 0--+255 Puffy
1365 /// </summary>
1366 SHAPE_PUFFY_LOWER_LIDS = 156,
1367 /// <summary>
1368 /// - Sunken Eyes 0--+255 Bugged Eyes
1369 /// </summary>
1370 SHAPE_EYE_DEPTH = 157,
1371 /// <summary>
1372 /// - Flat Head 0--+255 Long Head
1373 /// </summary>
1374 SHAPE_HEAD_LENGTH = 158,
1375 /// <summary>
1376 /// - Less Freckles 0--+255 More Freckles
1377 /// </summary>
1378 SKIN_BODY_FRECKLES = 159,
1379 /// <summary>
1380 /// - Low 0--+255 High
1381 /// </summary>
1382 UNDERSHIRT_COLLAR_BACK = 160,
1383 JACKET_COLLAR_BACK_161 = 161,
1384 SHIRT_COLLAR_BACK_162 = 162,
1385 /// <summary>
1386 /// - Short Pigtails 0--+255 Long Pigtails
1387 /// </summary>
1388 HAIR_PIGTAILS = 163,
1389 /// <summary>
1390 /// - Short Ponytail 0--+255 Long Ponytail
1391 /// </summary>
1392 HAIR_PONYTAIL = 164,
1393 /// <summary>
1394 /// Butt Size - Flat Butt 0--+255 Big Butt
1395 /// </summary>
1396 SHAPE_BUTT_SIZE = 165,
1397 /// <summary>
1398 /// Ear Tips - Flat 0--+255 Pointy
1399 /// </summary>
1400 SHAPE_POINTY_EARS = 166,
1401 /// <summary>
1402 /// Lip Ratio - More Upper Lip 0--+255 More Lower Lip
1403 /// </summary>
1404 SHAPE_LIP_RATIO = 167,
1405 SHIRT_SLEEVE_LENGTH_168 = 168,
1406 /// <summary>
1407 /// - Short 0--+255 Long
1408 /// </summary>
1409 SHIRT_SHIRT_BOTTOM = 169,
1410 SHIRT_COLLAR_FRONT_170 = 170,
1411 SHIRT_SHIRT_RED = 171,
1412 SHIRT_SHIRT_GREEN = 172,
1413 SHIRT_SHIRT_BLUE = 173,
1414 PANTS_PANTS_RED = 174,
1415 PANTS_PANTS_GREEN = 175,
1416 PANTS_PANTS_BLUE = 176,
1417 SHOES_SHOES_RED = 177,
1418 SHOES_SHOES_GREEN = 178,
1419 /// <summary>
1420 /// - Low 0--+255 High
1421 /// </summary>
1422 PANTS_WAIST_HEIGHT = 179,
1423 PANTS_PANTS_LENGTH_180 = 180,
1424 /// <summary>
1425 /// Pants Fit - Tight Pants 0--+255 Loose Pants
1426 /// </summary>
1427 PANTS_LOOSE_LOWER_CLOTHING = 181,
1428 SHOES_SHOES_BLUE = 182,
1429 SOCKS_SOCKS_RED = 183,
1430 SOCKS_SOCKS_GREEN = 184,
1431 SOCKS_SOCKS_BLUE = 185,
1432 UNDERSHIRT_UNDERSHIRT_RED = 186,
1433 UNDERSHIRT_UNDERSHIRT_GREEN = 187,
1434 UNDERSHIRT_UNDERSHIRT_BLUE = 188,
1435 UNDERPANTS_UNDERPANTS_RED = 189,
1436 UNDERPANTS_UNDERPANTS_GREEN = 190,
1437 UNDERPANTS_UNDERPANTS_BLUE = 191,
1438 GLOVES_GLOVES_RED = 192,
1439 /// <summary>
1440 /// Shirt Fit - Tight Shirt 0--+255 Loose Shirt
1441 /// </summary>
1442 SHIRT_LOOSE_UPPER_CLOTHING = 193,
1443 GLOVES_GLOVES_GREEN = 194,
1444 GLOVES_GLOVES_BLUE = 195,
1445 JACKET_JACKET_RED = 196,
1446 JACKET_JACKET_GREEN = 197,
1447 JACKET_JACKET_BLUE = 198,
1448 /// <summary>
1449 /// Sleeve Looseness - Tight Sleeves 0--+255 Loose Sleeves
1450 /// </summary>
1451 SHIRT_SHIRTSLEEVE_FLAIR = 199,
1452 /// <summary>
1453 /// Knee Angle - Knock Kneed 0--+255 Bow Legged
1454 /// </summary>
1455 SHAPE_BOWED_LEGS = 200,
1456 /// <summary>
1457 /// - Short hips 0--+255 Long Hips
1458 /// </summary>
1459 SHAPE_HIP_LENGTH = 201,
1460 /// <summary>
1461 /// - Fingerless 0--+255 Fingers
1462 /// </summary>
1463 GLOVES_GLOVE_FINGERS = 202,
1464 /// <summary>
1465 /// bustle skirt - no bustle 0--+255 more bustle
1466 /// </summary>
1467 SKIRT_SKIRT_BUSTLE = 203,
1468 /// <summary>
1469 /// - Short 0--+255 Long
1470 /// </summary>
1471 SKIRT_SKIRT_LENGTH = 204,
1472 /// <summary>
1473 /// - Open Front 0--+255 Closed Front
1474 /// </summary>
1475 SKIRT_SLIT_FRONT = 205,
1476 /// <summary>
1477 /// - Open Back 0--+255 Closed Back
1478 /// </summary>
1479 SKIRT_SLIT_BACK = 206,
1480 /// <summary>
1481 /// - Open Left 0--+255 Closed Left
1482 /// </summary>
1483 SKIRT_SLIT_LEFT = 207,
1484 /// <summary>
1485 /// - Open Right 0--+255 Closed Right
1486 /// </summary>
1487 SKIRT_SLIT_RIGHT = 208,
1488 /// <summary>
1489 /// Skirt Fit - Tight Skirt 0--+255 Poofy Skirt
1490 /// </summary>
1491 SKIRT_SKIRT_LOOSENESS = 209,
1492 SHIRT_SHIRT_WRINKLES = 210,
1493 PANTS_PANTS_WRINKLES = 211,
1494 /// <summary>
1495 /// Jacket Wrinkles - No Wrinkles 0--+255 Wrinkles
1496 /// </summary>
1497 JACKET_JACKET_WRINKLES = 212,
1498 /// <summary>
1499 /// Package - Coin Purse 0--+255 Duffle Bag
1500 /// </summary>
1501 SHAPE_MALE_PACKAGE = 213,
1502 /// <summary>
1503 /// Inner Eye Corner - Corner Down 0--+255 Corner Up
1504 /// </summary>
1505 SHAPE_EYELID_INNER_CORNER_UP = 214,
1506 SKIRT_SKIRT_RED = 215,
1507 SKIRT_SKIRT_GREEN = 216,
1508 SKIRT_SKIRT_BLUE = 217
1509 }
1510 #endregion
1511 }
1512 }