aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/AvatarAppearance.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/AvatarAppearance.cs')
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs987
1 files changed, 528 insertions, 459 deletions
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 5da8ba1..a4bb765 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -26,59 +26,139 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Reflection;
29using System.Collections; 30using System.Collections;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using OpenMetaverse; 32using OpenMetaverse;
33using OpenMetaverse.StructuredData;
34using log4net;
32 35
33namespace OpenSim.Framework 36namespace OpenSim.Framework
34{ 37{
38 // A special dictionary for avatar appearance
39 public struct LayerItem
40 {
41 public UUID ItemID;
42 public UUID AssetID;
43
44 public LayerItem(UUID itemID, UUID assetID)
45 {
46 ItemID = itemID;
47 AssetID = assetID;
48 }
49 }
50
51 public class Layer
52 {
53 protected int m_layerType;
54 protected Dictionary<UUID, UUID> m_items = new Dictionary<UUID, UUID>();
55 protected List<UUID> m_ids = new List<UUID>();
56
57 public Layer(int type)
58 {
59 m_layerType = type;
60 }
61
62 public int LayerType
63 {
64 get { return m_layerType; }
65 }
66
67 public int Count
68 {
69 get { return m_ids.Count; }
70 }
71
72 public void Add(UUID itemID, UUID assetID)
73 {
74 if (m_items.ContainsKey(itemID))
75 return;
76 if (m_ids.Count >= 5)
77 return;
78
79 m_ids.Add(itemID);
80 m_items[itemID] = assetID;
81 }
82
83 public void Wear(UUID itemID, UUID assetID)
84 {
85 Clear();
86 Add(itemID, assetID);
87 }
88
89 public void Clear()
90 {
91 m_ids.Clear();
92 m_items.Clear();
93 }
94
95 public void RemoveItem(UUID itemID)
96 {
97 if (m_items.ContainsKey(itemID))
98 {
99 m_ids.Remove(itemID);
100 m_items.Remove(itemID);
101 }
102 }
103
104 public void RemoveAsset(UUID assetID)
105 {
106 UUID itemID = UUID.Zero;
107
108 foreach (KeyValuePair<UUID, UUID> kvp in m_items)
109 {
110 if (kvp.Value == assetID)
111 {
112 itemID = kvp.Key;
113 break;
114 }
115 }
116
117 if (itemID != UUID.Zero)
118 {
119 m_ids.Remove(itemID);
120 m_items.Remove(itemID);
121 }
122 }
123
124 public LayerItem this [int idx]
125 {
126 get
127 {
128 if (idx >= m_ids.Count || idx < 0)
129 return new LayerItem(UUID.Zero, UUID.Zero);
130
131 return new LayerItem(m_ids[idx], m_items[m_ids[idx]]);
132 }
133 }
134 }
135
35 /// <summary> 136 /// <summary>
36 /// Contains the Avatar's Appearance and methods to manipulate the appearance. 137 /// Contains the Avatar's Appearance and methods to manipulate the appearance.
37 /// </summary> 138 /// </summary>
38 public class AvatarAppearance 139 public class AvatarAppearance
39 { 140 {
40 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 141 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 // these are guessed at by the list here -
43 // http://wiki.secondlife.com/wiki/Avatar_Appearance. We'll
44 // correct them over time for when were are wrong.
45 public readonly static int BODY = 0;
46 public readonly static int SKIN = 1;
47 public readonly static int HAIR = 2;
48 public readonly static int EYES = 3;
49 public readonly static int SHIRT = 4;
50 public readonly static int PANTS = 5;
51 public readonly static int SHOES = 6;
52 public readonly static int SOCKS = 7;
53 public readonly static int JACKET = 8;
54 public readonly static int GLOVES = 9;
55 public readonly static int UNDERSHIRT = 10;
56 public readonly static int UNDERPANTS = 11;
57 public readonly static int SKIRT = 12;
58
59 private readonly static int MAX_WEARABLES = 13;
60
61 private static UUID BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
62 private static UUID BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9");
63 private static UUID SKIN_ASSET = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb");
64 private static UUID SKIN_ITEM = new UUID("77c41e39-38f9-f75a-024e-585989bfabc9");
65 private static UUID SHIRT_ASSET = new UUID("00000000-38f9-1111-024e-222222111110");
66 private static UUID SHIRT_ITEM = new UUID("77c41e39-38f9-f75a-0000-585989bf0000");
67 private static UUID PANTS_ASSET = new UUID("00000000-38f9-1111-024e-222222111120");
68 private static UUID PANTS_ITEM = new UUID("77c41e39-38f9-f75a-0000-5859892f1111");
69 private static UUID HAIR_ASSET = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66");
70 private static UUID HAIR_ITEM = new UUID("d342e6c1-b9d2-11dc-95ff-0800200c9a66");
71 142
72 public readonly static int VISUALPARAM_COUNT = 218; 143 public readonly static int VISUALPARAM_COUNT = 218;
73 144
145 public readonly static int TEXTURE_COUNT = 21;
146 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
147
74 protected UUID m_owner; 148 protected UUID m_owner;
149 protected int m_serial = 1;
150 protected byte[] m_visualparams;
151 protected Primitive.TextureEntry m_texture;
152 protected AvatarWearable[] m_wearables;
153 protected Dictionary<int, List<AvatarAttachment>> m_attachments;
154 protected float m_avatarHeight = 0;
155 protected float m_hipOffset = 0;
75 156
76 public virtual UUID Owner 157 public virtual UUID Owner
77 { 158 {
78 get { return m_owner; } 159 get { return m_owner; }
79 set { m_owner = value; } 160 set { m_owner = value; }
80 } 161 }
81 protected int m_serial = 1;
82 162
83 public virtual int Serial 163 public virtual int Serial
84 { 164 {
@@ -86,15 +166,17 @@ namespace OpenSim.Framework
86 set { m_serial = value; } 166 set { m_serial = value; }
87 } 167 }
88 168
89 protected byte[] m_visualparams;
90
91 public virtual byte[] VisualParams 169 public virtual byte[] VisualParams
92 { 170 {
93 get { return m_visualparams; } 171 get { return m_visualparams; }
94 set { m_visualparams = value; } 172 set { m_visualparams = value; }
95 } 173 }
96 174
97 protected AvatarWearable[] m_wearables; 175 public virtual Primitive.TextureEntry Texture
176 {
177 get { return m_texture; }
178 set { m_texture = value; }
179 }
98 180
99 public virtual AvatarWearable[] Wearables 181 public virtual AvatarWearable[] Wearables
100 { 182 {
@@ -103,178 +185,135 @@ namespace OpenSim.Framework
103 } 185 }
104 186
105 public virtual UUID BodyItem { 187 public virtual UUID BodyItem {
106 get { return m_wearables[BODY].ItemID; } 188 get { return m_wearables[AvatarWearable.BODY].ItemID; }
107 set { m_wearables[BODY].ItemID = value; } 189 set { m_wearables[AvatarWearable.BODY].ItemID = value; }
108 } 190 }
109 191
110 public virtual UUID BodyAsset { 192 public virtual UUID BodyAsset {
111 get { return m_wearables[BODY].AssetID; } 193 get { return m_wearables[AvatarWearable.BODY].AssetID; }
112 set { m_wearables[BODY].AssetID = value; } 194 set { m_wearables[AvatarWearable.BODY].AssetID = value; }
113 } 195 }
114 196
115 public virtual UUID SkinItem { 197 public virtual UUID SkinItem {
116 get { return m_wearables[SKIN].ItemID; } 198 get { return m_wearables[AvatarWearable.SKIN].ItemID; }
117 set { m_wearables[SKIN].ItemID = value; } 199 set { m_wearables[AvatarWearable.SKIN].ItemID = value; }
118 } 200 }
119 201
120 public virtual UUID SkinAsset { 202 public virtual UUID SkinAsset {
121 get { return m_wearables[SKIN].AssetID; } 203 get { return m_wearables[AvatarWearable.SKIN].AssetID; }
122 set { m_wearables[SKIN].AssetID = value; } 204 set { m_wearables[AvatarWearable.SKIN].AssetID = value; }
123 } 205 }
124 206
125 public virtual UUID HairItem { 207 public virtual UUID HairItem {
126 get { return m_wearables[HAIR].ItemID; } 208 get { return m_wearables[AvatarWearable.HAIR].ItemID; }
127 set { m_wearables[HAIR].ItemID = value; } 209 set { m_wearables[AvatarWearable.HAIR].ItemID = value; }
128 } 210 }
129 211
130 public virtual UUID HairAsset { 212 public virtual UUID HairAsset {
131 get { return m_wearables[HAIR].AssetID; } 213 get { return m_wearables[AvatarWearable.HAIR].AssetID; }
132 set { m_wearables[HAIR].AssetID = value; } 214 set { m_wearables[AvatarWearable.HAIR].AssetID = value; }
133 } 215 }
134 216
135 public virtual UUID EyesItem { 217 public virtual UUID EyesItem {
136 get { return m_wearables[EYES].ItemID; } 218 get { return m_wearables[AvatarWearable.EYES].ItemID; }
137 set { m_wearables[EYES].ItemID = value; } 219 set { m_wearables[AvatarWearable.EYES].ItemID = value; }
138 } 220 }
139 221
140 public virtual UUID EyesAsset { 222 public virtual UUID EyesAsset {
141 get { return m_wearables[EYES].AssetID; } 223 get { return m_wearables[AvatarWearable.EYES].AssetID; }
142 set { m_wearables[EYES].AssetID = value; } 224 set { m_wearables[AvatarWearable.EYES].AssetID = value; }
143 } 225 }
144 226
145 public virtual UUID ShirtItem { 227 public virtual UUID ShirtItem {
146 get { return m_wearables[SHIRT].ItemID; } 228 get { return m_wearables[AvatarWearable.SHIRT].ItemID; }
147 set { m_wearables[SHIRT].ItemID = value; } 229 set { m_wearables[AvatarWearable.SHIRT].ItemID = value; }
148 } 230 }
149 231
150 public virtual UUID ShirtAsset { 232 public virtual UUID ShirtAsset {
151 get { return m_wearables[SHIRT].AssetID; } 233 get { return m_wearables[AvatarWearable.SHIRT].AssetID; }
152 set { m_wearables[SHIRT].AssetID = value; } 234 set { m_wearables[AvatarWearable.SHIRT].AssetID = value; }
153 } 235 }
154 236
155 public virtual UUID PantsItem { 237 public virtual UUID PantsItem {
156 get { return m_wearables[PANTS].ItemID; } 238 get { return m_wearables[AvatarWearable.PANTS].ItemID; }
157 set { m_wearables[PANTS].ItemID = value; } 239 set { m_wearables[AvatarWearable.PANTS].ItemID = value; }
158 } 240 }
159 241
160 public virtual UUID PantsAsset { 242 public virtual UUID PantsAsset {
161 get { return m_wearables[PANTS].AssetID; } 243 get { return m_wearables[AvatarWearable.PANTS].AssetID; }
162 set { m_wearables[PANTS].AssetID = value; } 244 set { m_wearables[AvatarWearable.PANTS].AssetID = value; }
163 } 245 }
164 246
165 public virtual UUID ShoesItem { 247 public virtual UUID ShoesItem {
166 get { return m_wearables[SHOES].ItemID; } 248 get { return m_wearables[AvatarWearable.SHOES].ItemID; }
167 set { m_wearables[SHOES].ItemID = value; } 249 set { m_wearables[AvatarWearable.SHOES].ItemID = value; }
168 } 250 }
169 251
170 public virtual UUID ShoesAsset { 252 public virtual UUID ShoesAsset {
171 get { return m_wearables[SHOES].AssetID; } 253 get { return m_wearables[AvatarWearable.SHOES].AssetID; }
172 set { m_wearables[SHOES].AssetID = value; } 254 set { m_wearables[AvatarWearable.SHOES].AssetID = value; }
173 } 255 }
174 256
175 public virtual UUID SocksItem { 257 public virtual UUID SocksItem {
176 get { return m_wearables[SOCKS].ItemID; } 258 get { return m_wearables[AvatarWearable.SOCKS].ItemID; }
177 set { m_wearables[SOCKS].ItemID = value; } 259 set { m_wearables[AvatarWearable.SOCKS].ItemID = value; }
178 } 260 }
179 261
180 public virtual UUID SocksAsset { 262 public virtual UUID SocksAsset {
181 get { return m_wearables[SOCKS].AssetID; } 263 get { return m_wearables[AvatarWearable.SOCKS].AssetID; }
182 set { m_wearables[SOCKS].AssetID = value; } 264 set { m_wearables[AvatarWearable.SOCKS].AssetID = value; }
183 } 265 }
184 266
185 public virtual UUID JacketItem { 267 public virtual UUID JacketItem {
186 get { return m_wearables[JACKET].ItemID; } 268 get { return m_wearables[AvatarWearable.JACKET].ItemID; }
187 set { m_wearables[JACKET].ItemID = value; } 269 set { m_wearables[AvatarWearable.JACKET].ItemID = value; }
188 } 270 }
189 271
190 public virtual UUID JacketAsset { 272 public virtual UUID JacketAsset {
191 get { return m_wearables[JACKET].AssetID; } 273 get { return m_wearables[AvatarWearable.JACKET].AssetID; }
192 set { m_wearables[JACKET].AssetID = value; } 274 set { m_wearables[AvatarWearable.JACKET].AssetID = value; }
193 } 275 }
194 276
195 public virtual UUID GlovesItem { 277 public virtual UUID GlovesItem {
196 get { return m_wearables[GLOVES].ItemID; } 278 get { return m_wearables[AvatarWearable.GLOVES].ItemID; }
197 set { m_wearables[GLOVES].ItemID = value; } 279 set { m_wearables[AvatarWearable.GLOVES].ItemID = value; }
198 } 280 }
199 281
200 public virtual UUID GlovesAsset { 282 public virtual UUID GlovesAsset {
201 get { return m_wearables[GLOVES].AssetID; } 283 get { return m_wearables[AvatarWearable.GLOVES].AssetID; }
202 set { m_wearables[GLOVES].AssetID = value; } 284 set { m_wearables[AvatarWearable.GLOVES].AssetID = value; }
203 } 285 }
204 286
205 public virtual UUID UnderShirtItem { 287 public virtual UUID UnderShirtItem {
206 get { return m_wearables[UNDERSHIRT].ItemID; } 288 get { return m_wearables[AvatarWearable.UNDERSHIRT].ItemID; }
207 set { m_wearables[UNDERSHIRT].ItemID = value; } 289 set { m_wearables[AvatarWearable.UNDERSHIRT].ItemID = value; }
208 } 290 }
209 291
210 public virtual UUID UnderShirtAsset { 292 public virtual UUID UnderShirtAsset {
211 get { return m_wearables[UNDERSHIRT].AssetID; } 293 get { return m_wearables[AvatarWearable.UNDERSHIRT].AssetID; }
212 set { m_wearables[UNDERSHIRT].AssetID = value; } 294 set { m_wearables[AvatarWearable.UNDERSHIRT].AssetID = value; }
213 } 295 }
214 296
215 public virtual UUID UnderPantsItem { 297 public virtual UUID UnderPantsItem {
216 get { return m_wearables[UNDERPANTS].ItemID; } 298 get { return m_wearables[AvatarWearable.UNDERPANTS].ItemID; }
217 set { m_wearables[UNDERPANTS].ItemID = value; } 299 set { m_wearables[AvatarWearable.UNDERPANTS].ItemID = value; }
218 } 300 }
219 301
220 public virtual UUID UnderPantsAsset { 302 public virtual UUID UnderPantsAsset {
221 get { return m_wearables[UNDERPANTS].AssetID; } 303 get { return m_wearables[AvatarWearable.UNDERPANTS].AssetID; }
222 set { m_wearables[UNDERPANTS].AssetID = value; } 304 set { m_wearables[AvatarWearable.UNDERPANTS].AssetID = value; }
223 } 305 }
224 306
225 public virtual UUID SkirtItem { 307 public virtual UUID SkirtItem {
226 get { return m_wearables[SKIRT].ItemID; } 308 get { return m_wearables[AvatarWearable.SKIRT].ItemID; }
227 set { m_wearables[SKIRT].ItemID = value; } 309 set { m_wearables[AvatarWearable.SKIRT].ItemID = value; }
228 } 310 }
229 311
230 public virtual UUID SkirtAsset { 312 public virtual UUID SkirtAsset {
231 get { return m_wearables[SKIRT].AssetID; } 313 get { return m_wearables[AvatarWearable.SKIRT].AssetID; }
232 set { m_wearables[SKIRT].AssetID = value; } 314 set { m_wearables[AvatarWearable.SKIRT].AssetID = value; }
233 } 315 }
234 316
235 public virtual void SetDefaultWearables()
236 {
237 m_wearables[BODY].AssetID = BODY_ASSET;
238 m_wearables[BODY].ItemID = BODY_ITEM;
239 m_wearables[SKIN].AssetID = SKIN_ASSET;
240 m_wearables[SKIN].ItemID = SKIN_ITEM;
241 m_wearables[HAIR].AssetID = HAIR_ASSET;
242 m_wearables[HAIR].ItemID = HAIR_ITEM;
243 m_wearables[SHIRT].AssetID = SHIRT_ASSET;
244 m_wearables[SHIRT].ItemID = SHIRT_ITEM;
245 m_wearables[PANTS].AssetID = PANTS_ASSET;
246 m_wearables[PANTS].ItemID = PANTS_ITEM;
247 }
248
249 public virtual void ClearWearables()
250 {
251 for (int i = 0; i < 13; i++)
252 {
253 m_wearables[i].AssetID = UUID.Zero;
254 m_wearables[i].ItemID = UUID.Zero;
255 }
256 }
257
258 public virtual void SetDefaultParams(byte[] vparams)
259 {
260 // TODO: Figure out better values then 'fat scientist 150' or 'alien 0'
261 for (int i = 0; i < VISUALPARAM_COUNT; i++)
262 {
263 vparams[i] = 150;
264 }
265 }
266
267 protected Primitive.TextureEntry m_texture;
268
269 public virtual Primitive.TextureEntry Texture
270 {
271 get { return m_texture; }
272 set { m_texture = value; }
273 }
274
275 protected float m_avatarHeight = 0;
276 protected float m_hipOffset = 0;
277
278 public virtual float AvatarHeight 317 public virtual float AvatarHeight
279 { 318 {
280 get { return m_avatarHeight; } 319 get { return m_avatarHeight; }
@@ -286,366 +325,295 @@ namespace OpenSim.Framework
286 get { return m_hipOffset; } 325 get { return m_hipOffset; }
287 } 326 }
288 327
289 //Builds the VisualParam Enum using LIBOMV's Visual Param NameValues
290 /*
291 public void BuildVisualParamEnum()
292 {
293 Dictionary<string, int> IndexedParams = new Dictionary<string, int>();
294 int vpIndex = 0;
295 IndexedParams = new Dictionary<string, int>();
296
297 System.Text.StringBuilder sb = new System.Text.StringBuilder();
298
299 sb.Append("public enum VPElement: int\n");
300 sb.Append("{\n");
301 foreach (KeyValuePair<int, VisualParam> kvp in OpenMetaverse.VisualParams.Params)
302 {
303 VisualParam vp = kvp.Value;
304
305 // Only Group-0 parameters are sent in AgentSetAppearance packets
306 if (kvp.Value.Group == 0)
307 {
308
309 if (!IndexedParams.ContainsKey(vp.Name))
310 {
311
312 if (vp.Label.Length > 0 || vp.LabelMin.Length > 0 || vp.LabelMax.Length > 0)
313 {
314
315 sb.Append("/// <summary>\n");
316 if (vp.LabelMin.Length > 0 && vp.LabelMax.Length > 0)
317 sb.Append(string.Format("/// {0} - {1} 0--+255 {2}\n", vp.Label, vp.LabelMin,
318 vp.LabelMax));
319
320 else
321 sb.Append(string.Format("/// {0}\n", vp.Label));
322
323 sb.Append("/// </summary>\n");
324 }
325 sb.Append(string.Format(" {0}_{1} = {2}", vp.Wearable.ToUpper(), vp.Name.ToUpper().Replace(" ", "_"),vpIndex));
326
327 IndexedParams.Add(vp.Name, vpIndex++);
328 }
329 else
330 {
331 sb.Append(string.Format(" {0}_{1}_{2} = {2}", vp.Wearable.ToUpper(), vp.Name.ToUpper().Replace(" ", "_"), vpIndex));
332 vpIndex++;
333 //int i = 0;
334 }
335 }
336 if (vpIndex < 217)
337 sb.Append(",\n");
338 else
339 sb.Append("\n");
340
341 }
342 sb.Append("}\n");
343
344 }
345 */
346
347 public AvatarAppearance() : this(UUID.Zero) {} 328 public AvatarAppearance() : this(UUID.Zero) {}
348 329
349 public AvatarAppearance(UUID owner) 330 public AvatarAppearance(UUID owner)
350 { 331 {
351 m_wearables = new AvatarWearable[MAX_WEARABLES]; 332// DEBUG ON
352 for (int i = 0; i < MAX_WEARABLES; i++) 333 m_log.WarnFormat("[AVATAR APPEARANCE] create empty appearance for {0}",owner);
353 { 334// DEBUG OFF
354 // this makes them all null 335 m_serial = 1;
355 m_wearables[i] = new AvatarWearable();
356 }
357 m_serial = 0;
358 m_owner = owner; 336 m_owner = owner;
359 //BuildVisualParamEnum() 337
360 m_visualparams = new byte[VISUALPARAM_COUNT];
361 // This sets Visual Params with *less* weirder values then default. Instead of a ugly alien, it looks like a fat scientist
362 SetDefaultParams(m_visualparams);
363 SetDefaultWearables(); 338 SetDefaultWearables();
364 m_texture = GetDefaultTexture(); 339 SetDefaultTexture();
340 SetDefaultParams();
341 SetHeight();
342
343 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
365 } 344 }
366 345
367 public AvatarAppearance(UUID avatarID, AvatarWearable[] wearables, byte[] visualParams) 346 public AvatarAppearance(UUID avatarID, OSDMap map)
368 { 347 {
348// DEBUG ON
349 m_log.WarnFormat("[AVATAR APPEARANCE] create appearance for {0} from OSDMap",avatarID);
350// DEBUG OFF
369 m_owner = avatarID; 351 m_owner = avatarID;
370 m_serial = 1; 352 Unpack(map);
371 m_wearables = wearables; 353 SetHeight();
372 m_visualparams = visualParams;
373 m_texture = GetDefaultTexture();
374 } 354 }
375 355
376 /// <summary> 356 public AvatarAppearance(UUID avatarID, AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams)
377 /// Set up appearance textures and avatar parameters, including a height calculation
378 /// </summary>
379 public virtual void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
380 { 357 {
358// DEBUG ON
359 m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance for {0}",avatarID);
360// DEBUG OFF
361 m_serial = 1;
362 m_owner = avatarID;
363
364 if (wearables != null)
365 m_wearables = wearables;
366 else
367 SetDefaultWearables();
368
381 if (textureEntry != null) 369 if (textureEntry != null)
382 m_texture = textureEntry; 370 m_texture = textureEntry;
371 else
372 SetDefaultTexture();
373
383 if (visualParams != null) 374 if (visualParams != null)
384 m_visualparams = visualParams; 375 m_visualparams = visualParams;
376 else
377 SetDefaultParams();
385 378
386 m_avatarHeight = 1.23077f // Shortest possible avatar height 379 SetHeight();
387 + 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f // Body height
388 + 0.072514f * (float)m_visualparams[(int)VPElement.SHAPE_HEAD_SIZE] / 255.0f // Head size
389 + 0.3836f * (float)m_visualparams[(int)VPElement.SHAPE_LEG_LENGTH] / 255.0f // Leg length
390 + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f // Shoe platform height
391 + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f // Shoe heel height
392 + 0.076f * (float)m_visualparams[(int)VPElement.SHAPE_NECK_LENGTH] / 255.0f; // Neck length
393 m_hipOffset = (((1.23077f // Half of avatar
394 + 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f // Body height
395 + 0.3836f * (float)m_visualparams[(int)VPElement.SHAPE_LEG_LENGTH] / 255.0f // Leg length
396 + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f // Shoe platform height
397 + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f // Shoe heel height
398 ) / 2) - m_avatarHeight / 2) * 0.31f - 0.0425f;
399
400
401
402 //System.Console.WriteLine(">>>>>>> [APPEARANCE]: Height {0} Hip offset {1}" + m_avatarHeight + " " + m_hipOffset);
403 //m_log.Debug("------------- Set Appearance Texture ---------------");
404 //Primitive.TextureEntryFace[] faces = Texture.FaceTextures;
405 //foreach (Primitive.TextureEntryFace face in faces)
406 //{
407 // if (face != null)
408 // m_log.Debug(" ++ " + face.TextureID);
409 // else
410 // m_log.Debug(" ++ NULL ");
411 //}
412 //m_log.Debug("----------------------------");
413
414 }
415 380
416 public virtual void SetWearable(int wearableId, AvatarWearable wearable) 381 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
417 {
418 m_wearables[wearableId] = wearable;
419 } 382 }
420 383
421 public static Primitive.TextureEntry GetDefaultTexture() 384 public AvatarAppearance(AvatarAppearance appearance)
422 { 385 {
423 Primitive.TextureEntry textu = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97")); 386// DEBUG ON
424 textu.CreateFace(0).TextureID = new UUID("00000000-0000-1111-9999-000000000012"); 387 m_log.WarnFormat("[AVATAR APPEARANCE] create from an existing appearance");
425 textu.CreateFace(1).TextureID = Util.BLANK_TEXTURE_UUID; 388// DEBUG OFF
426 textu.CreateFace(2).TextureID = Util.BLANK_TEXTURE_UUID; 389 if (appearance == null)
427 textu.CreateFace(3).TextureID = new UUID("6522E74D-1660-4E7F-B601-6F48C1659A77");
428 textu.CreateFace(4).TextureID = new UUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B");
429 textu.CreateFace(5).TextureID = new UUID("00000000-0000-1111-9999-000000000010");
430 textu.CreateFace(6).TextureID = new UUID("00000000-0000-1111-9999-000000000011");
431 return textu;
432 }
433
434 public static byte[] GetDefaultVisualParams()
435 {
436 byte[] visualParams;
437 visualParams = new byte[VISUALPARAM_COUNT];
438 for (int i = 0; i < VISUALPARAM_COUNT; i++)
439 { 390 {
440 visualParams[i] = 100; 391 m_serial = 1;
441 } 392 m_owner = UUID.Zero;
442 return visualParams;
443 }
444 393
445 public override String ToString() 394 SetDefaultWearables();
446 { 395 SetDefaultTexture();
447 String s = "[Wearables] =>"; 396 SetDefaultParams();
448 s += " Body Item: " + BodyItem.ToString() + ";"; 397 SetHeight();
449 s += " Skin Item: " + SkinItem.ToString() + ";";
450 s += " Shirt Item: " + ShirtItem.ToString() + ";";
451 s += " Pants Item: " + PantsItem.ToString() + ";";
452 return s;
453 }
454 398
455 // this is used for OGS1 399 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
456 public virtual Hashtable ToHashTable()
457 {
458 Hashtable h = new Hashtable();
459 h["owner"] = Owner.ToString();
460 h["serial"] = Serial.ToString();
461 h["visual_params"] = VisualParams;
462 h["texture"] = Texture.GetBytes();
463 h["avatar_height"] = AvatarHeight.ToString();
464 h["body_item"] = BodyItem.ToString();
465 h["body_asset"] = BodyAsset.ToString();
466 h["skin_item"] = SkinItem.ToString();
467 h["skin_asset"] = SkinAsset.ToString();
468 h["hair_item"] = HairItem.ToString();
469 h["hair_asset"] = HairAsset.ToString();
470 h["eyes_item"] = EyesItem.ToString();
471 h["eyes_asset"] = EyesAsset.ToString();
472 h["shirt_item"] = ShirtItem.ToString();
473 h["shirt_asset"] = ShirtAsset.ToString();
474 h["pants_item"] = PantsItem.ToString();
475 h["pants_asset"] = PantsAsset.ToString();
476 h["shoes_item"] = ShoesItem.ToString();
477 h["shoes_asset"] = ShoesAsset.ToString();
478 h["socks_item"] = SocksItem.ToString();
479 h["socks_asset"] = SocksAsset.ToString();
480 h["jacket_item"] = JacketItem.ToString();
481 h["jacket_asset"] = JacketAsset.ToString();
482 h["gloves_item"] = GlovesItem.ToString();
483 h["gloves_asset"] = GlovesAsset.ToString();
484 h["undershirt_item"] = UnderShirtItem.ToString();
485 h["undershirt_asset"] = UnderShirtAsset.ToString();
486 h["underpants_item"] = UnderPantsItem.ToString();
487 h["underpants_asset"] = UnderPantsAsset.ToString();
488 h["skirt_item"] = SkirtItem.ToString();
489 h["skirt_asset"] = SkirtAsset.ToString();
490
491 string attachments = GetAttachmentsString();
492 if (attachments != String.Empty)
493 h["attachments"] = attachments;
494
495 return h;
496 }
497
498 public AvatarAppearance(Hashtable h)
499 {
500 Owner = new UUID((string)h["owner"]);
501 Serial = Convert.ToInt32((string)h["serial"]);
502 VisualParams = (byte[])h["visual_params"];
503 400
504 if (h.Contains("texture")) 401 return;
505 {
506 byte[] te = h["texture"] as byte[];
507 if (te != null && te.Length > 0)
508 Texture = new Primitive.TextureEntry(te, 0, te.Length);
509 }
510 else
511 {
512 // We shouldn't be receiving appearance hashtables without a TextureEntry,
513 // but in case we do this will prevent a failure when saving to the database
514 Texture = GetDefaultTexture();
515 } 402 }
516
517 403
518 AvatarHeight = (float)Convert.ToDouble((string)h["avatar_height"]); 404 m_serial = appearance.Serial;
405 m_owner = appearance.Owner;
519 406
520 m_wearables = new AvatarWearable[MAX_WEARABLES]; 407 m_wearables = null;
521 for (int i = 0; i < MAX_WEARABLES; i++) 408 if (appearance.Wearables != null)
522 { 409 {
523 // this makes them all null 410 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES]; //should be 13 of these
524 m_wearables[i] = new AvatarWearable(); 411 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
412 SetWearable(i,appearance.Wearables[i]);
525 } 413 }
526 414
527 BodyItem = new UUID((string)h["body_item"]); 415 m_texture = null;
528 BodyAsset = new UUID((string)h["body_asset"]); 416 if (appearance.Texture != null)
529 SkinItem = new UUID((string)h["skin_item"]);
530 SkinAsset = new UUID((string)h["skin_asset"]);
531 HairItem = new UUID((string)h["hair_item"]);
532 HairAsset = new UUID((string)h["hair_asset"]);
533 EyesItem = new UUID((string)h["eyes_item"]);
534 EyesAsset = new UUID((string)h["eyes_asset"]);
535 ShirtItem = new UUID((string)h["shirt_item"]);
536 ShirtAsset = new UUID((string)h["shirt_asset"]);
537 PantsItem = new UUID((string)h["pants_item"]);
538 PantsAsset = new UUID((string)h["pants_asset"]);
539 ShoesItem = new UUID((string)h["shoes_item"]);
540 ShoesAsset = new UUID((string)h["shoes_asset"]);
541 SocksItem = new UUID((string)h["socks_item"]);
542 SocksAsset = new UUID((string)h["socks_asset"]);
543 JacketItem = new UUID((string)h["jacket_item"]);
544 JacketAsset = new UUID((string)h["jacket_asset"]);
545 GlovesItem = new UUID((string)h["gloves_item"]);
546 GlovesAsset = new UUID((string)h["gloves_asset"]);
547 UnderShirtItem = new UUID((string)h["undershirt_item"]);
548 UnderShirtAsset = new UUID((string)h["undershirt_asset"]);
549 UnderPantsItem = new UUID((string)h["underpants_item"]);
550 UnderPantsAsset = new UUID((string)h["underpants_asset"]);
551 SkirtItem = new UUID((string)h["skirt_item"]);
552 SkirtAsset = new UUID((string)h["skirt_asset"]);
553
554 if (h.ContainsKey("attachments"))
555 { 417 {
556 SetAttachmentsString(h["attachments"].ToString()); 418 byte[] tbytes = appearance.Texture.GetBytes();
419 m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length);
557 } 420 }
421
422 m_visualparams = null;
423 if (appearance.VisualParams != null)
424 m_visualparams = (byte[])appearance.VisualParams.Clone();
425
426 // Copy the attachment, force append mode since that ensures consistency
427 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
428 foreach (AvatarAttachment attachment in appearance.GetAttachments())
429 AppendAttachment(new AvatarAttachment(attachment));
430 }
431
432 protected virtual void SetDefaultWearables()
433 {
434 m_wearables = AvatarWearable.DefaultWearables;
558 } 435 }
559 436
560 private Dictionary<int, UUID[]> m_attachments = new Dictionary<int, UUID[]>(); 437 protected virtual void SetDefaultParams()
561
562 public void SetAttachments(AttachmentData[] data)
563 { 438 {
564 foreach (AttachmentData a in data) 439 m_visualparams = new byte[VISUALPARAM_COUNT];
440 for (int i = 0; i < VISUALPARAM_COUNT; i++)
565 { 441 {
566 m_attachments[a.AttachPoint] = new UUID[2]; 442 m_visualparams[i] = 150;
567 m_attachments[a.AttachPoint][0] = a.ItemID;
568 m_attachments[a.AttachPoint][1] = a.AssetID;
569 } 443 }
570 } 444 }
571 445
572 public void SetAttachments(Hashtable data) 446 protected virtual void SetDefaultTexture()
573 { 447 {
574 m_attachments.Clear(); 448 m_texture = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97"));
575 449 for (uint i = 0; i < TEXTURE_COUNT; i++)
576 if (data == null) 450 m_texture.CreateFace(i).TextureID = new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE);
577 return; 451 }
578 452
579 foreach (DictionaryEntry e in data) 453 /// <summary>
454 /// Set up appearance textures.
455 /// Returns boolean that indicates whether the new entries actually change the
456 /// existing values.
457 /// </summary>
458 public virtual bool SetTextureEntries(Primitive.TextureEntry textureEntry)
459 {
460 if (textureEntry == null)
461 return false;
462
463 // There are much simpler versions of this copy that could be
464 // made. We determine if any of the textures actually
465 // changed to know if the appearance should be saved later
466 bool changed = false;
467 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
580 { 468 {
581 int attachpoint = Convert.ToInt32(e.Key); 469 Primitive.TextureEntryFace newface = textureEntry.FaceTextures[i];
582 470 Primitive.TextureEntryFace oldface = m_texture.FaceTextures[i];
583 if (m_attachments.ContainsKey(attachpoint)) 471
584 continue; 472 if (newface == null)
473 {
474 if (oldface == null) continue;
475 }
476 else
477 {
478 if (oldface != null && oldface.TextureID == newface.TextureID) continue;
479 }
585 480
586 UUID item; 481 changed = true;
587 UUID asset; 482// DEBUG ON
483 if (newface != null)
484 m_log.WarnFormat("[AVATAR APPEARANCE] index {0}, new texture id {1}",i,newface.TextureID);
485// DEBUG OFF
486 }
588 487
589 Hashtable uuids = (Hashtable) e.Value; 488 m_texture = textureEntry;
590 UUID.TryParse(uuids["item"].ToString(), out item); 489 return changed;
591 UUID.TryParse(uuids["asset"].ToString(), out asset); 490 }
491
492 /// <summary>
493 /// Set up visual parameters for the avatar and refresh the avatar height
494 /// Returns boolean that indicates whether the new entries actually change the
495 /// existing values.
496 /// </summary>
497 public virtual bool SetVisualParams(byte[] visualParams)
498 {
499 if (visualParams == null)
500 return false;
501
502 // There are much simpler versions of this copy that could be
503 // made. We determine if any of the visual parameters actually
504 // changed to know if the appearance should be saved later
505 bool changed = false;
506 for (int i = 0; i < AvatarAppearance.VISUALPARAM_COUNT; i++)
507 {
508 if (visualParams[i] != m_visualparams[i])
509 {
510// DEBUG ON
511// m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}",
512// i,m_visualparams[i],visualParams[i]);
513// DEBUG OFF
514 m_visualparams[i] = visualParams[i];
515 changed = true;
516 }
517 }
592 518
593 UUID[] attachment = new UUID[2]; 519 // Reset the height if the visual parameters actually changed
594 attachment[0] = item; 520 if (changed)
595 attachment[1] = asset; 521 SetHeight();
596 522
597 m_attachments[attachpoint] = attachment; 523 return changed;
598 }
599 } 524 }
600 525
601 public Dictionary<int, UUID[]> GetAttachmentDictionary() 526 public virtual void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
602 { 527 {
603 return m_attachments; 528 SetTextureEntries(textureEntry);
529 SetVisualParams(visualParams);
604 } 530 }
531
532 public virtual void SetHeight()
533 {
534 m_avatarHeight = 1.23077f // Shortest possible avatar height
535 + 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f // Body height
536 + 0.072514f * (float)m_visualparams[(int)VPElement.SHAPE_HEAD_SIZE] / 255.0f // Head size
537 + 0.3836f * (float)m_visualparams[(int)VPElement.SHAPE_LEG_LENGTH] / 255.0f // Leg length
538 + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f // Shoe platform height
539 + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f // Shoe heel height
540 + 0.076f * (float)m_visualparams[(int)VPElement.SHAPE_NECK_LENGTH] / 255.0f; // Neck length
605 541
606 public Hashtable GetAttachments() 542 m_hipOffset = (((1.23077f // Half of avatar
543 + 0.516945f * (float)m_visualparams[(int)VPElement.SHAPE_HEIGHT] / 255.0f // Body height
544 + 0.3836f * (float)m_visualparams[(int)VPElement.SHAPE_LEG_LENGTH] / 255.0f // Leg length
545 + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f // Shoe platform height
546 + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f // Shoe heel height
547 ) / 2) - m_avatarHeight / 2) * 0.31f - 0.0425f;
548 }
549
550 public virtual void SetWearable(int wearableId, AvatarWearable wearable)
607 { 551 {
608 if (m_attachments.Count == 0) 552// DEBUG ON
609 return null; 553// m_log.WarnFormat("[AVATARAPPEARANCE] set wearable {0} --> {1}:{2}",wearableId,wearable.ItemID,wearable.AssetID);
554// DEBUG OFF
555 m_wearables[wearableId] = new AvatarWearable(wearable.ItemID,wearable.AssetID);
556 }
610 557
611 Hashtable ret = new Hashtable();
612 558
613 foreach (KeyValuePair<int, UUID[]> kvp in m_attachments) 559// DEBUG ON
614 { 560 public override String ToString()
615 int attachpoint = kvp.Key; 561 {
616 UUID[] uuids = kvp.Value; 562 String s = "";
617 563
618 Hashtable data = new Hashtable(); 564 s += String.Format("Serial: {0}\n",m_serial);
619 data["item"] = uuids[0].ToString(); 565
620 data["asset"] = uuids[1].ToString(); 566 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
567 if (m_texture.FaceTextures[i] != null)
568 s += String.Format("Texture: {0} --> {1}\n",i,m_texture.FaceTextures[i].TextureID);
621 569
622 ret[attachpoint] = data; 570 foreach (AvatarWearable awear in m_wearables)
623 } 571 s += String.Format("Wearable: item={0}, asset={1}\n",awear.ItemID,awear.AssetID);
624 572
625 return ret; 573 s += "Visual Params: ";
574 for (uint j = 0; j < AvatarAppearance.VISUALPARAM_COUNT; j++)
575 s += String.Format("{0},",m_visualparams[j]);
576 s += "\n";
577
578 return s;
626 } 579 }
580// DEBUG OFF
627 581
628 public List<int> GetAttachedPoints() 582 /// <summary>
583 /// Get a list of the attachments, note that there may be
584 /// duplicate attachpoints
585 /// </summary>
586 public List<AvatarAttachment> GetAttachments()
629 { 587 {
630 return new List<int>(m_attachments.Keys); 588 List<AvatarAttachment> alist = new List<AvatarAttachment>();
589 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
590 {
591 foreach (AvatarAttachment attach in kvp.Value)
592 alist.Add(new AvatarAttachment(attach));
593 }
594
595 return alist;
631 } 596 }
632 597
633 public UUID GetAttachedItem(int attachpoint) 598 internal void AppendAttachment(AvatarAttachment attach)
634 { 599 {
635 if (!m_attachments.ContainsKey(attachpoint)) 600 if (! m_attachments.ContainsKey(attach.AttachPoint))
636 return UUID.Zero; 601 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
637 602 m_attachments[attach.AttachPoint].Add(attach);
638 return m_attachments[attachpoint][0];
639 } 603 }
640 604
641 public UUID GetAttachedAsset(int attachpoint) 605 internal void ReplaceAttachment(AvatarAttachment attach)
642 { 606 {
643 if (!m_attachments.ContainsKey(attachpoint)) 607 m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
644 return UUID.Zero; 608 m_attachments[attach.AttachPoint].Add(attach);
645
646 return m_attachments[attachpoint][1];
647 } 609 }
648 610
611 /// <summary>
612 /// Add an attachment, if the attachpoint has the
613 /// 0x80 bit set then we assume this is an append
614 /// operation otherwise we replace whatever is
615 /// currently attached at the attachpoint
616 /// </summary>
649 public void SetAttachment(int attachpoint, UUID item, UUID asset) 617 public void SetAttachment(int attachpoint, UUID item, UUID asset)
650 { 618 {
651 if (attachpoint == 0) 619 if (attachpoint == 0)
@@ -658,31 +626,47 @@ namespace OpenSim.Framework
658 return; 626 return;
659 } 627 }
660 628
661 if (!m_attachments.ContainsKey(attachpoint)) 629 // check if this is an append or a replace, 0x80 marks it as an append
662 m_attachments[attachpoint] = new UUID[2]; 630 if ((attachpoint & 0x80) > 0)
663 631 {
664 m_attachments[attachpoint][0] = item; 632 // strip the append bit
665 m_attachments[attachpoint][1] = asset; 633 int point = attachpoint & 0x7F;
634 AppendAttachment(new AvatarAttachment(point, item, asset));
635 }
636 else
637 {
638 ReplaceAttachment(new AvatarAttachment(attachpoint,item,asset));
639 }
666 } 640 }
667 641
668 public int GetAttachpoint(UUID itemID) 642 public int GetAttachpoint(UUID itemID)
669 { 643 {
670 foreach (KeyValuePair<int, UUID[]> kvp in m_attachments) 644 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
671 { 645 {
672 if (kvp.Value[0] == itemID) 646 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
673 { 647 if (index >= 0)
674 return kvp.Key; 648 return kvp.Key;
675 }
676 } 649 }
650
677 return 0; 651 return 0;
678 } 652 }
679 653
680 public void DetachAttachment(UUID itemID) 654 public void DetachAttachment(UUID itemID)
681 { 655 {
682 int attachpoint = GetAttachpoint(itemID); 656 foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
657 {
658 int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
659 if (index >= 0)
660 {
661 // Remove it from the list of attachments at that attach point
662 m_attachments[kvp.Key].RemoveAt(index);
683 663
684 if (attachpoint > 0) 664 // And remove the list if there are no more attachments here
685 m_attachments.Remove(attachpoint); 665 if (m_attachments[kvp.Key].Count == 0)
666 m_attachments.Remove(kvp.Key);
667 return;
668 }
669 }
686 } 670 }
687 671
688 public void ClearAttachments() 672 public void ClearAttachments()
@@ -690,42 +674,126 @@ namespace OpenSim.Framework
690 m_attachments.Clear(); 674 m_attachments.Clear();
691 } 675 }
692 676
693 string GetAttachmentsString() 677 #region Packing Functions
678
679 /// <summary>
680 /// Create an OSDMap from the appearance data
681 /// </summary>
682 public OSDMap Pack()
694 { 683 {
695 List<string> strings = new List<string>(); 684 OSDMap data = new OSDMap();
696 685
697 foreach (KeyValuePair<int, UUID[]> e in m_attachments) 686 data["serial"] = OSD.FromInteger(m_serial);
687 data["height"] = OSD.FromReal(m_avatarHeight);
688 data["hipoffset"] = OSD.FromReal(m_hipOffset);
689
690 // Wearables
691 OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES);
692 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
693 wears.Add(m_wearables[i].Pack());
694 data["wearables"] = wears;
695
696 // Avatar Textures
697 OSDArray textures = new OSDArray(AvatarAppearance.TEXTURE_COUNT);
698 for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++)
698 { 699 {
699 strings.Add(e.Key.ToString()); 700 if (m_texture.FaceTextures[i] != null)
700 strings.Add(e.Value[0].ToString()); 701 textures.Add(OSD.FromUUID(m_texture.FaceTextures[i].TextureID));
701 strings.Add(e.Value[1].ToString()); 702 else
703 textures.Add(OSD.FromUUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE));
702 } 704 }
705 data["textures"] = textures;
706
707 // Visual Parameters
708 OSDBinary visualparams = new OSDBinary(m_visualparams);
709 data["visualparams"] = visualparams;
710
711 // Attachments
712 OSDArray attachs = new OSDArray(m_attachments.Count);
713 foreach (AvatarAttachment attach in GetAttachments())
714 attachs.Add(attach.Pack());
715 data["attachments"] = attachs;
703 716
704 return String.Join(",", strings.ToArray()); 717 return data;
705 } 718 }
706 719
707 void SetAttachmentsString(string data) 720 /// <summary>
721 /// Unpack and OSDMap and initialize the appearance
722 /// from it
723 /// </summary>
724 public void Unpack(OSDMap data)
708 { 725 {
709 string[] strings = data.Split(new char[] {','}); 726 if ((data != null) && (data["serial"] != null))
710 int i = 0; 727 m_serial = data["serial"].AsInteger();
728 if ((data != null) && (data["height"] != null))
729 m_avatarHeight = (float)data["height"].AsReal();
730 if ((data != null) && (data["hipoffset"] != null))
731 m_hipOffset = (float)data["hipoffset"].AsReal();
732
733 try
734 {
735 // Wearables
736 SetDefaultWearables();
737 if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)
738 {
739 OSDArray wears = (OSDArray)(data["wearables"]);
740 for (int i = 0; i < wears.Count; i++)
741 m_wearables[i] = new AvatarWearable((OSDMap)wears[i]);
742 }
743 else
744 {
745 m_log.Warn("[AVATARAPPEARANCE] failed to unpack wearables");
746 }
711 747
712 m_attachments.Clear(); 748 // Avatar Textures
749 SetDefaultTexture();
750 if ((data != null) && (data["textures"] != null) && (data["textures"]).Type == OSDType.Array)
751 {
752 OSDArray textures = (OSDArray)(data["textures"]);
753 for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT && i < textures.Count; i++)
754 {
755 UUID textureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
756 if (textures[i] != null)
757 textureID = textures[i].AsUUID();
758 m_texture.CreateFace((uint)i).TextureID = new UUID(textureID);
759 }
760 }
761 else
762 {
763 m_log.Warn("[AVATARAPPEARANCE] failed to unpack textures");
764 }
713 765
714 while (strings.Length - i > 2) 766 // Visual Parameters
715 { 767 SetDefaultParams();
716 int attachpoint = Int32.Parse(strings[i]); 768 if ((data != null) && (data["visualparams"] != null))
717 UUID item = new UUID(strings[i+1]); 769 {
718 UUID asset = new UUID(strings[i+2]); 770 if ((data["visualparams"].Type == OSDType.Binary) || (data["visualparams"].Type == OSDType.Array))
719 i += 3; 771 m_visualparams = data["visualparams"].AsBinary();
772 }
773 else
774 {
775 m_log.Warn("[AVATARAPPEARANCE] failed to unpack visual parameters");
776 }
720 777
721 if (!m_attachments.ContainsKey(attachpoint)) 778 // Attachments
779 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
780 if ((data != null) && (data["attachments"] != null) && (data["attachments"]).Type == OSDType.Array)
722 { 781 {
723 m_attachments[attachpoint] = new UUID[2]; 782 OSDArray attachs = (OSDArray)(data["attachments"]);
724 m_attachments[attachpoint][0] = item; 783 for (int i = 0; i < attachs.Count; i++)
725 m_attachments[attachpoint][1] = asset; 784 AppendAttachment(new AvatarAttachment((OSDMap)attachs[i]));
726 } 785 }
727 } 786 }
787 catch (Exception e)
788 {
789 m_log.ErrorFormat("[AVATARAPPEARANCE] unpack failed badly: {0}",e.Message);
790 }
728 } 791 }
792
793 #endregion
794
795 #region VPElement
796
729 /// <summary> 797 /// <summary>
730 /// Viewer Params Array Element for AgentSetAppearance 798 /// Viewer Params Array Element for AgentSetAppearance
731 /// Generated from LibOMV's Visual Params list 799 /// Generated from LibOMV's Visual Params list
@@ -1488,5 +1556,6 @@ namespace OpenSim.Framework
1488 SKIRT_SKIRT_GREEN = 216, 1556 SKIRT_SKIRT_GREEN = 216,
1489 SKIRT_SKIRT_BLUE = 217 1557 SKIRT_SKIRT_BLUE = 217
1490 } 1558 }
1559 #endregion
1491 } 1560 }
1492} \ No newline at end of file 1561}