MaterialsDemoModule.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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.Generic;
  29. using System.IO;
  30. using System.Reflection;
  31. using System.Security.Cryptography; // for computing md5 hash
  32. using log4net;
  33. using Mono.Addins;
  34. using Nini.Config;
  35. using OpenMetaverse;
  36. using OpenMetaverse.StructuredData;
  37. using OpenSim.Framework;
  38. using OpenSim.Framework.Servers;
  39. using OpenSim.Framework.Servers.HttpServer;
  40. using OpenSim.Region.Framework.Interfaces;
  41. using OpenSim.Region.Framework.Scenes;
  42. using Ionic.Zlib;
  43. // You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
  44. // specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
  45. // the available DLLs
  46. //[assembly: Addin("MaterialsDemoModule", "1.0")]
  47. //[assembly: AddinDependency("OpenSim", "0.5")]
  48. namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
  49. {
  50. /// <summary>
  51. ///
  52. // # # ## ##### # # # # # ####
  53. // # # # # # # ## # # ## # # #
  54. // # # # # # # # # # # # # # #
  55. // # ## # ###### ##### # # # # # # # # ###
  56. // ## ## # # # # # ## # # ## # #
  57. // # # # # # # # # # # # ####
  58. //
  59. // THIS MODULE IS FOR EXPERIMENTAL USE ONLY AND MAY CAUSE REGION OR ASSET CORRUPTION!
  60. //
  61. ////////////// WARNING //////////////////////////////////////////////////////////////////
  62. /// This is an *Experimental* module for developing support for materials-capable viewers
  63. /// This module should NOT be used in a production environment! It may cause data corruption and
  64. /// viewer crashes. It should be only used to evaluate implementations of materials.
  65. ///
  66. /// Materials are persisted via SceneObjectPart.dynattrs. This is a relatively new feature
  67. /// of OpenSimulator and is not field proven at the time this module was written. Persistence
  68. /// may fail or become corrupt and this could cause viewer crashes due to erroneous materials
  69. /// data being sent to viewers. Materials descriptions might survive IAR, OAR, or other means
  70. /// of archiving however the texture resources used by these materials probably will not as they
  71. /// may not be adequately referenced to ensure proper archiving.
  72. ///
  73. ///
  74. ///
  75. /// To enable this module, add this string at the bottom of OpenSim.ini:
  76. /// [MaterialsDemoModule]
  77. ///
  78. /// </summary>
  79. ///
  80. [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
  81. public class MaterialsDemoModule : INonSharedRegionModule
  82. {
  83. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  84. public string Name { get { return "MaterialsDemoModule"; } }
  85. public Type ReplaceableInterface { get { return null; } }
  86. private Scene m_scene = null;
  87. private bool m_enabled = false;
  88. public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>();
  89. public void Initialise(IConfigSource source)
  90. {
  91. m_enabled = (source.Configs["MaterialsDemoModule"] != null);
  92. if (!m_enabled)
  93. return;
  94. m_log.DebugFormat("[MaterialsDemoModule]: INITIALIZED MODULE");
  95. }
  96. public void Close()
  97. {
  98. if (!m_enabled)
  99. return;
  100. m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
  101. }
  102. public void AddRegion(Scene scene)
  103. {
  104. if (!m_enabled)
  105. return;
  106. m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
  107. m_scene = scene;
  108. m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
  109. m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
  110. // m_scene.EventManager.OnGatherUuids += GatherMaterialsUuids;
  111. }
  112. void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
  113. {
  114. foreach (var part in obj.Parts)
  115. if (part != null)
  116. GetStoredMaterialsForPart(part);
  117. }
  118. void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
  119. {
  120. string capsBase = "/CAPS/" + caps.CapsObjectPath;
  121. IRequestHandler renderMaterialsPostHandler
  122. = new RestStreamHandler("POST", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
  123. caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
  124. // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
  125. // and POST handlers, (at least at the time this was originally written), so we first set up a POST
  126. // handler normally and then add a GET handler via MainServer
  127. IRequestHandler renderMaterialsGetHandler
  128. = new RestStreamHandler("GET", capsBase + "/", RenderMaterialsGetCap, "RenderMaterials", null);
  129. MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
  130. // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
  131. IRequestHandler renderMaterialsPutHandler
  132. = new RestStreamHandler("PUT", capsBase + "/", RenderMaterialsPostCap, "RenderMaterials", null);
  133. MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
  134. }
  135. public void RemoveRegion(Scene scene)
  136. {
  137. if (!m_enabled)
  138. return;
  139. m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
  140. m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
  141. // m_scene.EventManager.OnGatherUuids -= GatherMaterialsUuids;
  142. m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
  143. }
  144. public void RegionLoaded(Scene scene)
  145. {
  146. }
  147. OSDMap GetMaterial(UUID id)
  148. {
  149. OSDMap map = null;
  150. lock (m_knownMaterials)
  151. {
  152. if (m_knownMaterials.ContainsKey(id))
  153. {
  154. map = new OSDMap();
  155. map["ID"] = OSD.FromBinary(id.GetBytes());
  156. map["Material"] = m_knownMaterials[id];
  157. }
  158. }
  159. return map;
  160. }
  161. void GetStoredMaterialsForPart(SceneObjectPart part)
  162. {
  163. OSD OSMaterials = null;
  164. OSDArray matsArr = null;
  165. if (part.DynAttrs == null)
  166. {
  167. m_log.Warn("[MaterialsDemoModule]: NULL DYNATTRS :( ");
  168. }
  169. lock (part.DynAttrs)
  170. {
  171. if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
  172. {
  173. OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
  174. if (materialsStore == null)
  175. return;
  176. materialsStore.TryGetValue("Materials", out OSMaterials);
  177. }
  178. if (OSMaterials != null && OSMaterials is OSDArray)
  179. matsArr = OSMaterials as OSDArray;
  180. else
  181. return;
  182. }
  183. m_log.Info("[MaterialsDemoModule]: OSMaterials: " + OSDParser.SerializeJsonString(OSMaterials));
  184. if (matsArr == null)
  185. {
  186. m_log.Info("[MaterialsDemoModule]: matsArr is null :( ");
  187. return;
  188. }
  189. foreach (OSD elemOsd in matsArr)
  190. {
  191. if (elemOsd != null && elemOsd is OSDMap)
  192. {
  193. OSDMap matMap = elemOsd as OSDMap;
  194. if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
  195. {
  196. try
  197. {
  198. lock (m_knownMaterials)
  199. m_knownMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
  200. }
  201. catch (Exception e)
  202. {
  203. m_log.Warn("[MaterialsDemoModule]: exception decoding persisted material: " + e.ToString());
  204. }
  205. }
  206. }
  207. }
  208. }
  209. void StoreMaterialsForPart(SceneObjectPart part)
  210. {
  211. try
  212. {
  213. if (part == null || part.Shape == null)
  214. return;
  215. Dictionary<UUID, OSDMap> mats = new Dictionary<UUID, OSDMap>();
  216. Primitive.TextureEntry te = part.Shape.Textures;
  217. if (te.DefaultTexture != null)
  218. {
  219. lock (m_knownMaterials)
  220. {
  221. if (m_knownMaterials.ContainsKey(te.DefaultTexture.MaterialID))
  222. mats[te.DefaultTexture.MaterialID] = m_knownMaterials[te.DefaultTexture.MaterialID];
  223. }
  224. }
  225. if (te.FaceTextures != null)
  226. {
  227. foreach (var face in te.FaceTextures)
  228. {
  229. if (face != null)
  230. {
  231. lock (m_knownMaterials)
  232. {
  233. if (m_knownMaterials.ContainsKey(face.MaterialID))
  234. mats[face.MaterialID] = m_knownMaterials[face.MaterialID];
  235. }
  236. }
  237. }
  238. }
  239. if (mats.Count == 0)
  240. return;
  241. OSDArray matsArr = new OSDArray();
  242. foreach (KeyValuePair<UUID, OSDMap> kvp in mats)
  243. {
  244. OSDMap matOsd = new OSDMap();
  245. matOsd["ID"] = OSD.FromUUID(kvp.Key);
  246. matOsd["Material"] = kvp.Value;
  247. matsArr.Add(matOsd);
  248. }
  249. OSDMap OSMaterials = new OSDMap();
  250. OSMaterials["Materials"] = matsArr;
  251. lock (part.DynAttrs)
  252. part.DynAttrs.SetStore("OpenSim", "Materials", OSMaterials);
  253. }
  254. catch (Exception e)
  255. {
  256. m_log.Warn("[MaterialsDemoModule]: exception in StoreMaterialsForPart(): " + e.ToString());
  257. }
  258. }
  259. public string RenderMaterialsPostCap(string request, string path,
  260. string param, IOSHttpRequest httpRequest,
  261. IOSHttpResponse httpResponse)
  262. {
  263. m_log.Debug("[MaterialsDemoModule]: POST cap handler");
  264. OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
  265. OSDMap resp = new OSDMap();
  266. OSDMap materialsFromViewer = null;
  267. OSDArray respArr = new OSDArray();
  268. if (req.ContainsKey("Zipped"))
  269. {
  270. OSD osd = null;
  271. byte[] inBytes = req["Zipped"].AsBinary();
  272. try
  273. {
  274. osd = ZDecompressBytesToOsd(inBytes);
  275. if (osd != null)
  276. {
  277. if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
  278. {
  279. foreach (OSD elem in (OSDArray)osd)
  280. {
  281. try
  282. {
  283. UUID id = new UUID(elem.AsBinary(), 0);
  284. lock (m_knownMaterials)
  285. {
  286. if (m_knownMaterials.ContainsKey(id))
  287. {
  288. m_log.Info("[MaterialsDemoModule]: request for known material ID: " + id.ToString());
  289. OSDMap matMap = new OSDMap();
  290. matMap["ID"] = OSD.FromBinary(id.GetBytes());
  291. matMap["Material"] = m_knownMaterials[id];
  292. respArr.Add(matMap);
  293. }
  294. else
  295. m_log.Info("[MaterialsDemoModule]: request for UNKNOWN material ID: " + id.ToString());
  296. }
  297. }
  298. catch (Exception e)
  299. {
  300. // report something here?
  301. continue;
  302. }
  303. }
  304. }
  305. else if (osd is OSDMap) // reqest to assign a material
  306. {
  307. materialsFromViewer = osd as OSDMap;
  308. if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
  309. {
  310. OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
  311. if (matsOsd is OSDArray)
  312. {
  313. OSDArray matsArr = matsOsd as OSDArray;
  314. try
  315. {
  316. foreach (OSDMap matsMap in matsArr)
  317. {
  318. m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
  319. uint matLocalID = 0;
  320. try { matLocalID = matsMap["ID"].AsUInteger(); }
  321. catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); }
  322. m_log.Debug("[MaterialsDemoModule]: matLocalId: " + matLocalID.ToString());
  323. OSDMap mat = null;
  324. try { mat = matsMap["Material"] as OSDMap; }
  325. catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); }
  326. m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat));
  327. UUID id = HashOsd(mat);
  328. lock (m_knownMaterials)
  329. m_knownMaterials[id] = mat;
  330. var sop = m_scene.GetSceneObjectPart(matLocalID);
  331. if (sop == null)
  332. m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + matLocalID.ToString());
  333. else
  334. {
  335. var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
  336. if (te == null)
  337. {
  338. m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + matLocalID.ToString());
  339. }
  340. else
  341. {
  342. int face = -1;
  343. if (matsMap.ContainsKey("Face"))
  344. {
  345. face = matsMap["Face"].AsInteger();
  346. if (te.FaceTextures == null) // && face == 0)
  347. {
  348. if (te.DefaultTexture == null)
  349. m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
  350. else
  351. te.DefaultTexture.MaterialID = id;
  352. }
  353. else
  354. {
  355. if (te.FaceTextures.Length >= face - 1)
  356. {
  357. if (te.FaceTextures[face] == null)
  358. te.DefaultTexture.MaterialID = id;
  359. else
  360. te.FaceTextures[face].MaterialID = id;
  361. }
  362. }
  363. }
  364. else
  365. {
  366. if (te.DefaultTexture != null)
  367. te.DefaultTexture.MaterialID = id;
  368. }
  369. m_log.Debug("[MaterialsDemoModule]: setting material ID for face " + face.ToString() + " to " + id.ToString());
  370. //we cant use sop.UpdateTextureEntry(te); because it filters so do it manually
  371. if (sop.ParentGroup != null)
  372. {
  373. sop.Shape.TextureEntry = te.GetBytes();
  374. sop.TriggerScriptChangedEvent(Changed.TEXTURE);
  375. sop.UpdateFlag = UpdateRequired.FULL;
  376. sop.ParentGroup.HasGroupChanged = true;
  377. sop.ScheduleFullUpdate();
  378. StoreMaterialsForPart(sop);
  379. }
  380. }
  381. }
  382. }
  383. }
  384. catch (Exception e)
  385. {
  386. m_log.Warn("[MaterialsDemoModule]: exception processing received material: " + e.Message);
  387. }
  388. }
  389. }
  390. }
  391. }
  392. }
  393. catch (Exception e)
  394. {
  395. m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload: " + e.Message);
  396. //return "";
  397. }
  398. m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
  399. }
  400. resp["Zipped"] = ZCompressOSD(respArr, false);
  401. string response = OSDParser.SerializeLLSDXmlString(resp);
  402. //m_log.Debug("[MaterialsDemoModule]: cap request: " + request);
  403. m_log.Debug("[MaterialsDemoModule]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
  404. m_log.Debug("[MaterialsDemoModule]: cap response: " + response);
  405. return response;
  406. }
  407. public string RenderMaterialsGetCap(string request, string path,
  408. string param, IOSHttpRequest httpRequest,
  409. IOSHttpResponse httpResponse)
  410. {
  411. m_log.Debug("[MaterialsDemoModule]: GET cap handler");
  412. OSDMap resp = new OSDMap();
  413. int matsCount = 0;
  414. OSDArray allOsd = new OSDArray();
  415. lock (m_knownMaterials)
  416. {
  417. foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials)
  418. {
  419. OSDMap matMap = new OSDMap();
  420. matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
  421. matMap["Material"] = kvp.Value;
  422. allOsd.Add(matMap);
  423. matsCount++;
  424. }
  425. }
  426. resp["Zipped"] = ZCompressOSD(allOsd, false);
  427. m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
  428. return OSDParser.SerializeLLSDXmlString(resp);
  429. }
  430. static string ZippedOsdBytesToString(byte[] bytes)
  431. {
  432. try
  433. {
  434. return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
  435. }
  436. catch (Exception e)
  437. {
  438. return "ZippedOsdBytesToString caught an exception: " + e.ToString();
  439. }
  440. }
  441. /// <summary>
  442. /// computes a UUID by hashing a OSD object
  443. /// </summary>
  444. /// <param name="osd"></param>
  445. /// <returns></returns>
  446. private static UUID HashOsd(OSD osd)
  447. {
  448. using (var md5 = MD5.Create())
  449. using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false)))
  450. return new UUID(md5.ComputeHash(ms), 0);
  451. }
  452. public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
  453. {
  454. OSD osd = null;
  455. using (MemoryStream msSinkCompressed = new MemoryStream())
  456. {
  457. using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
  458. Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
  459. {
  460. CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut);
  461. zOut.Close();
  462. }
  463. msSinkCompressed.Seek(0L, SeekOrigin.Begin);
  464. osd = OSD.FromBinary( msSinkCompressed.ToArray());
  465. }
  466. return osd;
  467. }
  468. public static OSD ZDecompressBytesToOsd(byte[] input)
  469. {
  470. OSD osd = null;
  471. using (MemoryStream msSinkUnCompressed = new MemoryStream())
  472. {
  473. using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
  474. {
  475. CopyStream(new MemoryStream(input), zOut);
  476. zOut.Close();
  477. }
  478. msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
  479. osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
  480. }
  481. return osd;
  482. }
  483. static void CopyStream(System.IO.Stream input, System.IO.Stream output)
  484. {
  485. byte[] buffer = new byte[2048];
  486. int len;
  487. while ((len = input.Read(buffer, 0, 2048)) > 0)
  488. {
  489. output.Write(buffer, 0, len);
  490. }
  491. output.Flush();
  492. }
  493. // FIXME: This code is currently still in UuidGatherer since we cannot use Scene.EventManager as some
  494. // calls to the gatherer are done for objects with no scene.
  495. // /// <summary>
  496. // /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
  497. // /// </summary>
  498. // /// <param name="part"></param>
  499. // /// <param name="assetUuids"></param>
  500. // private void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
  501. // {
  502. // // scan thru the dynAttrs map of this part for any textures used as materials
  503. // OSD osdMaterials = null;
  504. //
  505. // lock (part.DynAttrs)
  506. // {
  507. // if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
  508. // {
  509. // OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
  510. // if (materialsStore == null)
  511. // return;
  512. //
  513. // materialsStore.TryGetValue("Materials", out osdMaterials);
  514. // }
  515. //
  516. // if (osdMaterials != null)
  517. // {
  518. // //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
  519. //
  520. // if (osdMaterials is OSDArray)
  521. // {
  522. // OSDArray matsArr = osdMaterials as OSDArray;
  523. // foreach (OSDMap matMap in matsArr)
  524. // {
  525. // try
  526. // {
  527. // if (matMap.ContainsKey("Material"))
  528. // {
  529. // OSDMap mat = matMap["Material"] as OSDMap;
  530. // if (mat.ContainsKey("NormMap"))
  531. // {
  532. // UUID normalMapId = mat["NormMap"].AsUUID();
  533. // if (normalMapId != UUID.Zero)
  534. // {
  535. // assetUuids[normalMapId] = AssetType.Texture;
  536. // //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
  537. // }
  538. // }
  539. // if (mat.ContainsKey("SpecMap"))
  540. // {
  541. // UUID specularMapId = mat["SpecMap"].AsUUID();
  542. // if (specularMapId != UUID.Zero)
  543. // {
  544. // assetUuids[specularMapId] = AssetType.Texture;
  545. // //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
  546. // }
  547. // }
  548. // }
  549. //
  550. // }
  551. // catch (Exception e)
  552. // {
  553. // m_log.Warn("[MaterialsDemoModule]: exception getting materials: " + e.Message);
  554. // }
  555. // }
  556. // }
  557. // }
  558. // }
  559. // }
  560. }
  561. }