AvatarAppearance.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  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. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Runtime.Serialization;
  31. using System.Security.Permissions;
  32. using OpenMetaverse;
  33. namespace OpenSim.Framework
  34. {
  35. public class AvatarAppearance
  36. {
  37. // private static readonly ILog m_log
  38. // = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  39. // these are guessed at by the list here -
  40. // http://wiki.secondlife.com/wiki/Avatar_Appearance. We'll
  41. // correct them over time for when were are wrong.
  42. public readonly static int BODY = 0;
  43. public readonly static int SKIN = 1;
  44. public readonly static int HAIR = 2;
  45. public readonly static int EYES = 3;
  46. public readonly static int SHIRT = 4;
  47. public readonly static int PANTS = 5;
  48. public readonly static int SHOES = 6;
  49. public readonly static int SOCKS = 7;
  50. public readonly static int JACKET = 8;
  51. public readonly static int GLOVES = 9;
  52. public readonly static int UNDERSHIRT = 10;
  53. public readonly static int UNDERPANTS = 11;
  54. public readonly static int SKIRT = 12;
  55. private readonly static int MAX_WEARABLES = 13;
  56. private static UUID BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
  57. private static UUID BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9");
  58. private static UUID SKIN_ASSET = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb");
  59. private static UUID SKIN_ITEM = new UUID("77c41e39-38f9-f75a-024e-585989bfabc9");
  60. private static UUID SHIRT_ASSET = new UUID("00000000-38f9-1111-024e-222222111110");
  61. private static UUID SHIRT_ITEM = new UUID("77c41e39-38f9-f75a-0000-585989bf0000");
  62. private static UUID PANTS_ASSET = new UUID("00000000-38f9-1111-024e-222222111120");
  63. private static UUID PANTS_ITEM = new UUID("77c41e39-38f9-f75a-0000-5859892f1111");
  64. public readonly static int VISUALPARAM_COUNT = 218;
  65. protected UUID m_owner;
  66. public virtual UUID Owner
  67. {
  68. get { return m_owner; }
  69. set { m_owner = value; }
  70. }
  71. protected int m_serial = 1;
  72. public virtual int Serial
  73. {
  74. get { return m_serial; }
  75. set { m_serial = value; }
  76. }
  77. protected byte[] m_visualparams;
  78. public virtual byte[] VisualParams
  79. {
  80. get { return m_visualparams; }
  81. set { m_visualparams = value; }
  82. }
  83. protected AvatarWearable[] m_wearables;
  84. public virtual AvatarWearable[] Wearables
  85. {
  86. get { return m_wearables; }
  87. set { m_wearables = value; }
  88. }
  89. public virtual UUID BodyItem {
  90. get { return m_wearables[BODY].ItemID; }
  91. set { m_wearables[BODY].ItemID = value; }
  92. }
  93. public virtual UUID BodyAsset {
  94. get { return m_wearables[BODY].AssetID; }
  95. set { m_wearables[BODY].AssetID = value; }
  96. }
  97. public virtual UUID SkinItem {
  98. get { return m_wearables[SKIN].ItemID; }
  99. set { m_wearables[SKIN].ItemID = value; }
  100. }
  101. public virtual UUID SkinAsset {
  102. get { return m_wearables[SKIN].AssetID; }
  103. set { m_wearables[SKIN].AssetID = value; }
  104. }
  105. public virtual UUID HairItem {
  106. get { return m_wearables[HAIR].ItemID; }
  107. set { m_wearables[HAIR].ItemID = value; }
  108. }
  109. public virtual UUID HairAsset {
  110. get { return m_wearables[HAIR].AssetID; }
  111. set { m_wearables[HAIR].AssetID = value; }
  112. }
  113. public virtual UUID EyesItem {
  114. get { return m_wearables[EYES].ItemID; }
  115. set { m_wearables[EYES].ItemID = value; }
  116. }
  117. public virtual UUID EyesAsset {
  118. get { return m_wearables[EYES].AssetID; }
  119. set { m_wearables[EYES].AssetID = value; }
  120. }
  121. public virtual UUID ShirtItem {
  122. get { return m_wearables[SHIRT].ItemID; }
  123. set { m_wearables[SHIRT].ItemID = value; }
  124. }
  125. public virtual UUID ShirtAsset {
  126. get { return m_wearables[SHIRT].AssetID; }
  127. set { m_wearables[SHIRT].AssetID = value; }
  128. }
  129. public virtual UUID PantsItem {
  130. get { return m_wearables[PANTS].ItemID; }
  131. set { m_wearables[PANTS].ItemID = value; }
  132. }
  133. public virtual UUID PantsAsset {
  134. get { return m_wearables[PANTS].AssetID; }
  135. set { m_wearables[PANTS].AssetID = value; }
  136. }
  137. public virtual UUID ShoesItem {
  138. get { return m_wearables[SHOES].ItemID; }
  139. set { m_wearables[SHOES].ItemID = value; }
  140. }
  141. public virtual UUID ShoesAsset {
  142. get { return m_wearables[SHOES].AssetID; }
  143. set { m_wearables[SHOES].AssetID = value; }
  144. }
  145. public virtual UUID SocksItem {
  146. get { return m_wearables[SOCKS].ItemID; }
  147. set { m_wearables[SOCKS].ItemID = value; }
  148. }
  149. public virtual UUID SocksAsset {
  150. get { return m_wearables[SOCKS].AssetID; }
  151. set { m_wearables[SOCKS].AssetID = value; }
  152. }
  153. public virtual UUID JacketItem {
  154. get { return m_wearables[JACKET].ItemID; }
  155. set { m_wearables[JACKET].ItemID = value; }
  156. }
  157. public virtual UUID JacketAsset {
  158. get { return m_wearables[JACKET].AssetID; }
  159. set { m_wearables[JACKET].AssetID = value; }
  160. }
  161. public virtual UUID GlovesItem {
  162. get { return m_wearables[GLOVES].ItemID; }
  163. set { m_wearables[GLOVES].ItemID = value; }
  164. }
  165. public virtual UUID GlovesAsset {
  166. get { return m_wearables[GLOVES].AssetID; }
  167. set { m_wearables[GLOVES].AssetID = value; }
  168. }
  169. public virtual UUID UnderShirtItem {
  170. get { return m_wearables[UNDERSHIRT].ItemID; }
  171. set { m_wearables[UNDERSHIRT].ItemID = value; }
  172. }
  173. public virtual UUID UnderShirtAsset {
  174. get { return m_wearables[UNDERSHIRT].AssetID; }
  175. set { m_wearables[UNDERSHIRT].AssetID = value; }
  176. }
  177. public virtual UUID UnderPantsItem {
  178. get { return m_wearables[UNDERPANTS].ItemID; }
  179. set { m_wearables[UNDERPANTS].ItemID = value; }
  180. }
  181. public virtual UUID UnderPantsAsset {
  182. get { return m_wearables[UNDERPANTS].AssetID; }
  183. set { m_wearables[UNDERPANTS].AssetID = value; }
  184. }
  185. public virtual UUID SkirtItem {
  186. get { return m_wearables[SKIRT].ItemID; }
  187. set { m_wearables[SKIRT].ItemID = value; }
  188. }
  189. public virtual UUID SkirtAsset {
  190. get { return m_wearables[SKIRT].AssetID; }
  191. set { m_wearables[SKIRT].AssetID = value; }
  192. }
  193. public virtual void SetDefaultWearables()
  194. {
  195. m_wearables[BODY].AssetID = BODY_ASSET;
  196. m_wearables[BODY].ItemID = BODY_ITEM;
  197. m_wearables[SKIN].AssetID = SKIN_ASSET;
  198. m_wearables[SKIN].ItemID = SKIN_ITEM;
  199. m_wearables[SHIRT].AssetID = SHIRT_ASSET;
  200. m_wearables[SHIRT].ItemID = SHIRT_ITEM;
  201. m_wearables[PANTS].AssetID = PANTS_ASSET;
  202. m_wearables[PANTS].ItemID = PANTS_ITEM;
  203. }
  204. public virtual void ClearWearables()
  205. {
  206. for (int i = 0; i < 13; i++)
  207. {
  208. m_wearables[i].AssetID = UUID.Zero;
  209. m_wearables[i].ItemID = UUID.Zero;
  210. }
  211. }
  212. public virtual void SetDefaultParams(byte[] vparams)
  213. {
  214. // TODO: Figure out better values then 'fat scientist 150' or 'alien 0'
  215. for (int i = 0; i < VISUALPARAM_COUNT; i++)
  216. {
  217. vparams[i] = 150;
  218. }
  219. }
  220. protected Primitive.TextureEntry m_texture;
  221. public virtual Primitive.TextureEntry Texture
  222. {
  223. get { return m_texture; }
  224. set { m_texture = value; }
  225. }
  226. protected float m_avatarHeight = 0;
  227. protected float m_hipOffset = 0;
  228. public virtual float AvatarHeight
  229. {
  230. get { return m_avatarHeight; }
  231. set { m_avatarHeight = value; }
  232. }
  233. public virtual float HipOffset
  234. {
  235. get { return m_hipOffset; }
  236. }
  237. public AvatarAppearance()
  238. : this(UUID.Zero)
  239. {
  240. }
  241. public AvatarAppearance(UUID owner)
  242. {
  243. m_wearables = new AvatarWearable[MAX_WEARABLES];
  244. for (int i = 0; i < MAX_WEARABLES; i++)
  245. {
  246. // this makes them all null
  247. m_wearables[i] = new AvatarWearable();
  248. }
  249. m_serial = 0;
  250. m_owner = owner;
  251. m_visualparams = new byte[VISUALPARAM_COUNT];
  252. // This sets Visual Params with *less* weirder values then default. Instead of a ugly alien, it looks like a fat scientist
  253. SetDefaultParams(m_visualparams);
  254. SetDefaultWearables();
  255. m_texture = GetDefaultTexture();
  256. }
  257. public AvatarAppearance(UUID avatarID, AvatarWearable[] wearables, byte[] visualParams)
  258. {
  259. m_owner = avatarID;
  260. m_serial = 1;
  261. m_wearables = wearables;
  262. m_visualparams = visualParams;
  263. m_texture = GetDefaultTexture();
  264. }
  265. /// <summary>
  266. /// Set up appearance textures and avatar parameters, including a height calculation
  267. /// </summary>
  268. /// <param name="texture"></param>
  269. /// <param name="visualParam"></param>
  270. public virtual void SetAppearance(byte[] texture, List<byte> visualParam)
  271. {
  272. Primitive.TextureEntry textureEnt = new Primitive.TextureEntry(texture, 0, texture.Length);
  273. m_texture = textureEnt;
  274. m_visualparams = visualParam.ToArray();
  275. m_avatarHeight = 1.23077f // Shortest possible avatar height
  276. + 0.516945f * (float)m_visualparams[25] / 255.0f // Body height
  277. + 0.072514f * (float)m_visualparams[120] / 255.0f // Head size
  278. + 0.3836f * (float)m_visualparams[125] / 255.0f // Leg length
  279. + 0.08f * (float)m_visualparams[77] / 255.0f // Shoe heel height
  280. + 0.07f * (float)m_visualparams[78] / 255.0f // Shoe platform height
  281. + 0.076f * (float)m_visualparams[148] / 255.0f; // Neck length
  282. m_hipOffset = (0.615385f // Half of avatar
  283. + 0.08f * (float)m_visualparams[77] / 255.0f // Shoe heel height
  284. + 0.07f * (float)m_visualparams[78] / 255.0f // Shoe platform height
  285. + 0.3836f * (float)m_visualparams[125] / 255.0f // Leg length
  286. - m_avatarHeight / 2) * 0.3f - 0.04f;
  287. //System.Console.WriteLine(">>>>>>> [APPEARANCE]: Height {0} Hip offset {1}" + m_avatarHeight + " " + m_hipOffset);
  288. //m_log.Debug("------------- Set Appearance Texture ---------------");
  289. //Primitive.TextureEntryFace[] faces = Texture.FaceTextures;
  290. //foreach (Primitive.TextureEntryFace face in faces)
  291. //{
  292. // if (face != null)
  293. // m_log.Debug(" ++ " + face.TextureID);
  294. // else
  295. // m_log.Debug(" ++ NULL ");
  296. //}
  297. //m_log.Debug("----------------------------");
  298. }
  299. public virtual void SetWearable(int wearableId, AvatarWearable wearable)
  300. {
  301. m_wearables[wearableId] = wearable;
  302. }
  303. public static Primitive.TextureEntry GetDefaultTexture()
  304. {
  305. Primitive.TextureEntry textu = new Primitive.TextureEntry(new UUID("C228D1CF-4B5D-4BA8-84F4-899A0796AA97"));
  306. textu.CreateFace(0).TextureID = new UUID("00000000-0000-1111-9999-000000000012");
  307. textu.CreateFace(1).TextureID = Util.BLANK_TEXTURE_UUID;
  308. textu.CreateFace(2).TextureID = Util.BLANK_TEXTURE_UUID;
  309. textu.CreateFace(3).TextureID = new UUID("6522E74D-1660-4E7F-B601-6F48C1659A77");
  310. textu.CreateFace(4).TextureID = new UUID("7CA39B4C-BD19-4699-AFF7-F93FD03D3E7B");
  311. textu.CreateFace(5).TextureID = new UUID("00000000-0000-1111-9999-000000000010");
  312. textu.CreateFace(6).TextureID = new UUID("00000000-0000-1111-9999-000000000011");
  313. return textu;
  314. }
  315. public static byte[] GetDefaultVisualParams()
  316. {
  317. byte[] visualParams;
  318. visualParams = new byte[VISUALPARAM_COUNT];
  319. for (int i = 0; i < VISUALPARAM_COUNT; i++)
  320. {
  321. visualParams[i] = 100;
  322. }
  323. return visualParams;
  324. }
  325. public override String ToString()
  326. {
  327. String s = "[Wearables] =>";
  328. s += " Body Item: " + BodyItem.ToString() + ";";
  329. s += " Skin Item: " + SkinItem.ToString() + ";";
  330. s += " Shirt Item: " + ShirtItem.ToString() + ";";
  331. s += " Pants Item: " + PantsItem.ToString() + ";";
  332. return s;
  333. }
  334. // this is used for OGS1
  335. public virtual Hashtable ToHashTable()
  336. {
  337. Hashtable h = new Hashtable();
  338. h["owner"] = Owner.ToString();
  339. h["serial"] = Serial.ToString();
  340. h["visual_params"] = VisualParams;
  341. h["texture"] = Texture.GetBytes();
  342. h["avatar_height"] = AvatarHeight.ToString();
  343. h["body_item"] = BodyItem.ToString();
  344. h["body_asset"] = BodyAsset.ToString();
  345. h["skin_item"] = SkinItem.ToString();
  346. h["skin_asset"] = SkinAsset.ToString();
  347. h["hair_item"] = HairItem.ToString();
  348. h["hair_asset"] = HairAsset.ToString();
  349. h["eyes_item"] = EyesItem.ToString();
  350. h["eyes_asset"] = EyesAsset.ToString();
  351. h["shirt_item"] = ShirtItem.ToString();
  352. h["shirt_asset"] = ShirtAsset.ToString();
  353. h["pants_item"] = PantsItem.ToString();
  354. h["pants_asset"] = PantsAsset.ToString();
  355. h["shoes_item"] = ShoesItem.ToString();
  356. h["shoes_asset"] = ShoesAsset.ToString();
  357. h["socks_item"] = SocksItem.ToString();
  358. h["socks_asset"] = SocksAsset.ToString();
  359. h["jacket_item"] = JacketItem.ToString();
  360. h["jacket_asset"] = JacketAsset.ToString();
  361. h["gloves_item"] = GlovesItem.ToString();
  362. h["gloves_asset"] = GlovesAsset.ToString();
  363. h["undershirt_item"] = UnderShirtItem.ToString();
  364. h["undershirt_asset"] = UnderShirtAsset.ToString();
  365. h["underpants_item"] = UnderPantsItem.ToString();
  366. h["underpants_asset"] = UnderPantsAsset.ToString();
  367. h["skirt_item"] = SkirtItem.ToString();
  368. h["skirt_asset"] = SkirtAsset.ToString();
  369. string attachments = GetAttachmentsString();
  370. if (attachments != String.Empty)
  371. h["attachments"] = attachments;
  372. return h;
  373. }
  374. public AvatarAppearance(Hashtable h)
  375. {
  376. Owner = new UUID((string)h["owner"]);
  377. Serial = Convert.ToInt32((string)h["serial"]);
  378. VisualParams = (byte[])h["visual_params"];
  379. Texture = new Primitive.TextureEntry((byte[])h["texture"], 0, ((byte[])h["texture"]).Length);
  380. AvatarHeight = (float)Convert.ToDouble((string)h["avatar_height"]);
  381. m_wearables = new AvatarWearable[MAX_WEARABLES];
  382. for (int i = 0; i < MAX_WEARABLES; i++)
  383. {
  384. // this makes them all null
  385. m_wearables[i] = new AvatarWearable();
  386. }
  387. BodyItem = new UUID((string)h["body_item"]);
  388. BodyAsset = new UUID((string)h["body_asset"]);
  389. SkinItem = new UUID((string)h["skin_item"]);
  390. SkinAsset = new UUID((string)h["skin_asset"]);
  391. HairItem = new UUID((string)h["hair_item"]);
  392. HairAsset = new UUID((string)h["hair_asset"]);
  393. EyesItem = new UUID((string)h["eyes_item"]);
  394. EyesAsset = new UUID((string)h["eyes_asset"]);
  395. ShirtItem = new UUID((string)h["shirt_item"]);
  396. ShirtAsset = new UUID((string)h["shirt_asset"]);
  397. PantsItem = new UUID((string)h["pants_item"]);
  398. PantsAsset = new UUID((string)h["pants_asset"]);
  399. ShoesItem = new UUID((string)h["shoes_item"]);
  400. ShoesAsset = new UUID((string)h["shoes_asset"]);
  401. SocksItem = new UUID((string)h["socks_item"]);
  402. SocksAsset = new UUID((string)h["socks_asset"]);
  403. JacketItem = new UUID((string)h["jacket_item"]);
  404. JacketAsset = new UUID((string)h["jacket_asset"]);
  405. GlovesItem = new UUID((string)h["gloves_item"]);
  406. GlovesAsset = new UUID((string)h["gloves_asset"]);
  407. UnderShirtItem = new UUID((string)h["undershirt_item"]);
  408. UnderShirtAsset = new UUID((string)h["undershirt_asset"]);
  409. UnderPantsItem = new UUID((string)h["underpants_item"]);
  410. UnderPantsAsset = new UUID((string)h["underpants_asset"]);
  411. SkirtItem = new UUID((string)h["skirt_item"]);
  412. SkirtAsset = new UUID((string)h["skirt_asset"]);
  413. if (h.ContainsKey("attachments"))
  414. {
  415. SetAttachmentsString(h["attachments"].ToString());
  416. }
  417. }
  418. private Dictionary<int, UUID[]> m_attachments = new Dictionary<int, UUID[]>();
  419. public void SetAttachments(Hashtable data)
  420. {
  421. m_attachments.Clear();
  422. if (data == null)
  423. return;
  424. foreach (DictionaryEntry e in data)
  425. {
  426. int attachpoint = Convert.ToInt32(e.Key);
  427. if (m_attachments.ContainsKey(attachpoint))
  428. continue;
  429. UUID item;
  430. UUID asset;
  431. Hashtable uuids = (Hashtable) e.Value;
  432. UUID.TryParse(uuids["item"].ToString(), out item);
  433. UUID.TryParse(uuids["asset"].ToString(), out asset);
  434. UUID[] attachment = new UUID[2];
  435. attachment[0] = item;
  436. attachment[1] = asset;
  437. m_attachments[attachpoint] = attachment;
  438. }
  439. }
  440. public Hashtable GetAttachments()
  441. {
  442. if (m_attachments.Count == 0)
  443. return null;
  444. Hashtable ret = new Hashtable();
  445. foreach (KeyValuePair<int, UUID[]> kvp in m_attachments)
  446. {
  447. int attachpoint = kvp.Key;
  448. UUID[] uuids = kvp.Value;
  449. Hashtable data = new Hashtable();
  450. data["item"] = uuids[0].ToString();
  451. data["asset"] = uuids[1].ToString();
  452. ret[attachpoint] = data;
  453. }
  454. return ret;
  455. }
  456. public List<int> GetAttachedPoints()
  457. {
  458. return new List<int>(m_attachments.Keys);
  459. }
  460. public UUID GetAttachedItem(int attachpoint)
  461. {
  462. if (!m_attachments.ContainsKey(attachpoint))
  463. return UUID.Zero;
  464. return m_attachments[attachpoint][0];
  465. }
  466. public UUID GetAttachedAsset(int attachpoint)
  467. {
  468. if (!m_attachments.ContainsKey(attachpoint))
  469. return UUID.Zero;
  470. return m_attachments[attachpoint][1];
  471. }
  472. public void SetAttachment(int attachpoint, UUID item, UUID asset)
  473. {
  474. if (attachpoint == 0)
  475. return;
  476. if (item == UUID.Zero)
  477. {
  478. if (m_attachments.ContainsKey(attachpoint))
  479. m_attachments.Remove(attachpoint);
  480. return;
  481. }
  482. if (!m_attachments.ContainsKey(attachpoint))
  483. m_attachments[attachpoint] = new UUID[2];
  484. m_attachments[attachpoint][0] = item;
  485. m_attachments[attachpoint][1] = asset;
  486. }
  487. public int GetAttachpoint(UUID itemID)
  488. {
  489. foreach (KeyValuePair<int, UUID[]> kvp in m_attachments)
  490. {
  491. if (kvp.Value[0] == itemID)
  492. {
  493. return kvp.Key;
  494. }
  495. }
  496. return 0;
  497. }
  498. public void DetachAttachment(UUID itemID)
  499. {
  500. int attachpoint = GetAttachpoint(itemID);
  501. if (attachpoint > 0)
  502. m_attachments.Remove(attachpoint);
  503. }
  504. public void ClearAttachments()
  505. {
  506. m_attachments.Clear();
  507. }
  508. string GetAttachmentsString()
  509. {
  510. List<string> strings = new List<string>();
  511. foreach (KeyValuePair<int, UUID[]> e in m_attachments)
  512. {
  513. strings.Add(e.Key.ToString());
  514. strings.Add(e.Value[0].ToString());
  515. strings.Add(e.Value[1].ToString());
  516. }
  517. return String.Join(",", strings.ToArray());
  518. }
  519. void SetAttachmentsString(string data)
  520. {
  521. string[] strings = data.Split(new char[] {','});
  522. int i = 0;
  523. m_attachments.Clear();
  524. while (strings.Length - i > 2)
  525. {
  526. int attachpoint = Int32.Parse(strings[i]);
  527. UUID item = new UUID(strings[i+1]);
  528. UUID asset = new UUID(strings[i+2]);
  529. i += 3;
  530. if (!m_attachments.ContainsKey(attachpoint))
  531. {
  532. m_attachments[attachpoint] = new UUID[2];
  533. m_attachments[attachpoint][0] = item;
  534. m_attachments[attachpoint][1] = asset;
  535. }
  536. }
  537. }
  538. }
  539. }