aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
diff options
context:
space:
mode:
authorOren Hurvitz2013-12-06 16:21:11 +0200
committerdahlia2014-01-20 00:38:42 -0800
commit3018b2c5d7c9de0e8da6d158f0848c840b7864ab (patch)
treef06f5b35360de9010e618b2cf7c6c109c0527631 /OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
parentRenamed MaterialsDemoModule to MaterialsModule (diff)
downloadopensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.zip
opensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.tar.gz
opensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.tar.bz2
opensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.tar.xz
Materials module: a) Store materials as assets; b) Finalized it (removed the "Demo" label; removed most of the logging); c) Enabled by default
Changed UuidGatherer to use 'sbyte' to identify assets instead of 'AssetType'. This lets UuidGatherer handle Materials, which are defined in a different enum from 'AssetType'.
Diffstat (limited to 'OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs518
1 files changed, 191 insertions, 327 deletions
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index e707154..09041e8 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -42,77 +42,49 @@ using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer; 42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
45using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
45 46
46using Ionic.Zlib; 47using Ionic.Zlib;
47 48
48// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already 49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
49// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans 50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
50// the available DLLs 51// the available DLLs
51//[assembly: Addin("MaterialsDemoModule", "1.0")] 52//[assembly: Addin("MaterialsModule", "1.0")]
52//[assembly: AddinDependency("OpenSim", "0.5")] 53//[assembly: AddinDependency("OpenSim", "0.5")]
53 54
54namespace OpenSim.Region.OptionalModules.MaterialsDemoModule 55namespace OpenSim.Region.OptionalModules.Materials
55{ 56{
56 /// <summary> 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
57 /// 58 public class MaterialsModule : INonSharedRegionModule
58 // # # ## ##### # # # # # ####
59 // # # # # # # ## # # ## # # #
60 // # # # # # # # # # # # # # #
61 // # ## # ###### ##### # # # # # # # # ###
62 // ## ## # # # # # ## # # ## # #
63 // # # # # # # # # # # # ####
64 //
65 // THIS MODULE IS FOR EXPERIMENTAL USE ONLY AND MAY CAUSE REGION OR ASSET CORRUPTION!
66 //
67 ////////////// WARNING //////////////////////////////////////////////////////////////////
68 /// This is an *Experimental* module for developing support for materials-capable viewers
69 /// This module should NOT be used in a production environment! It may cause data corruption and
70 /// viewer crashes. It should be only used to evaluate implementations of materials.
71 ///
72 /// Materials are persisted via SceneObjectPart.dynattrs. This is a relatively new feature
73 /// of OpenSimulator and is not field proven at the time this module was written. Persistence
74 /// may fail or become corrupt and this could cause viewer crashes due to erroneous materials
75 /// data being sent to viewers. Materials descriptions might survive IAR, OAR, or other means
76 /// of archiving however the texture resources used by these materials probably will not as they
77 /// may not be adequately referenced to ensure proper archiving.
78 ///
79 ///
80 ///
81 /// To enable this module, add this string at the bottom of OpenSim.ini:
82 /// [MaterialsDemoModule]
83 ///
84 /// </summary>
85 ///
86
87 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
88 public class MaterialsDemoModule : INonSharedRegionModule
89 { 59 {
90 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
91 61
92 public string Name { get { return "MaterialsDemoModule"; } } 62 public string Name { get { return "MaterialsModule"; } }
93 63
94 public Type ReplaceableInterface { get { return null; } } 64 public Type ReplaceableInterface { get { return null; } }
95 65
96 private Scene m_scene = null; 66 private Scene m_scene = null;
97 private bool m_enabled = false; 67 private bool m_enabled = false;
98 68
99 public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>(); 69 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
100 70
101 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
102 { 72 {
103 m_enabled = (source.Configs["MaterialsDemoModule"] != null); 73 IConfig config = source.Configs["Materials"];
74 if (config == null)
75 return;
76
77 m_enabled = config.GetBoolean("enable_materials", true);
104 if (!m_enabled) 78 if (!m_enabled)
105 return; 79 return;
106 80
107 m_log.DebugFormat("[MaterialsDemoModule]: Initialized"); 81 m_log.DebugFormat("[Materials]: Initialized");
108 } 82 }
109 83
110 public void Close() 84 public void Close()
111 { 85 {
112 if (!m_enabled) 86 if (!m_enabled)
113 return; 87 return;
114
115 //m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
116 } 88 }
117 89
118 public void AddRegion(Scene scene) 90 public void AddRegion(Scene scene)
@@ -120,22 +92,19 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
120 if (!m_enabled) 92 if (!m_enabled)
121 return; 93 return;
122 94
123 //m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
124
125 m_scene = scene; 95 m_scene = scene;
126 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 96 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
127 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; 97 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
128// m_scene.EventManager.OnGatherUuids += GatherMaterialsUuids;
129 } 98 }
130 99
131 void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) 100 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
132 { 101 {
133 foreach (var part in obj.Parts) 102 foreach (var part in obj.Parts)
134 if (part != null) 103 if (part != null)
135 GetStoredMaterialsForPart(part); 104 GetStoredMaterialsInPart(part);
136 } 105 }
137 106
138 void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps) 107 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
139 { 108 {
140 string capsBase = "/CAPS/" + caps.CapsObjectPath; 109 string capsBase = "/CAPS/" + caps.CapsObjectPath;
141 110
@@ -164,143 +133,65 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
164 133
165 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 134 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
166 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene; 135 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
167// m_scene.EventManager.OnGatherUuids -= GatherMaterialsUuids;
168
169 //m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
170 } 136 }
171 137
172 public void RegionLoaded(Scene scene) 138 public void RegionLoaded(Scene scene)
173 { 139 {
174 } 140 }
175 141
176 OSDMap GetMaterial(UUID id) 142 /// <summary>
177 { 143 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
178 OSDMap map = null; 144 /// </summary>
179 lock (m_knownMaterials) 145 private void GetStoredMaterialsInPart(SceneObjectPart part)
180 {
181 if (m_knownMaterials.ContainsKey(id))
182 {
183 map = new OSDMap();
184 map["ID"] = OSD.FromBinary(id.GetBytes());
185 map["Material"] = m_knownMaterials[id];
186 }
187 }
188 return map;
189 }
190
191 void GetStoredMaterialsForPart(SceneObjectPart part)
192 { 146 {
193 OSD OSMaterials = null; 147 if (part.Shape == null)
194 OSDArray matsArr = null;
195
196 if (part.DynAttrs == null)
197 {
198 //m_log.Warn("[MaterialsDemoModule]: NULL DYNATTRS :( ");
199 return; 148 return;
200 } 149 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
201 150 if (te == null)
202 lock (part.DynAttrs)
203 {
204 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
205 {
206 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
207
208 if (materialsStore == null)
209 return;
210
211 materialsStore.TryGetValue("Materials", out OSMaterials);
212 }
213
214 if (OSMaterials != null && OSMaterials is OSDArray)
215 matsArr = OSMaterials as OSDArray;
216 else
217 return;
218 }
219
220 //m_log.Info("[MaterialsDemoModule]: OSMaterials: " + OSDParser.SerializeJsonString(OSMaterials));
221
222 if (matsArr == null)
223 {
224 //m_log.Info("[MaterialsDemoModule]: matsArr is null :( ");
225 return; 151 return;
226 }
227 152
228 foreach (OSD elemOsd in matsArr) 153 GetStoredMaterialInFace(part, te.DefaultTexture);
154
155 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
229 { 156 {
230 if (elemOsd != null && elemOsd is OSDMap) 157 if (face != null)
231 { 158 GetStoredMaterialInFace(part, face);
232 OSDMap matMap = elemOsd as OSDMap;
233 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
234 {
235 try
236 {
237 lock (m_knownMaterials)
238 m_knownMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
239 }
240 catch (Exception e)
241 {
242 m_log.Warn("[MaterialsDemoModule]: exception decoding persisted material ", e);
243 }
244 }
245 }
246 } 159 }
247 } 160 }
248 161
249 void StoreMaterialsForPart(SceneObjectPart part) 162 /// <summary>
163 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
164 /// </summary>
165 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
250 { 166 {
251 try 167 UUID id = face.MaterialID;
168 if (id == UUID.Zero)
169 return;
170
171 lock (m_regionMaterials)
252 { 172 {
253 if (part == null || part.Shape == null) 173 if (m_regionMaterials.ContainsKey(id))
254 return; 174 return;
255 175
256 Dictionary<UUID, OSDMap> mats = new Dictionary<UUID, OSDMap>(); 176 byte[] data = m_scene.AssetService.GetData(id.ToString());
257 177 if (data == null)
258 Primitive.TextureEntry te = part.Shape.Textures;
259
260 if (te.DefaultTexture != null)
261 { 178 {
262 lock (m_knownMaterials) 179 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
263 { 180 return;
264 if (m_knownMaterials.ContainsKey(te.DefaultTexture.MaterialID))
265 mats[te.DefaultTexture.MaterialID] = m_knownMaterials[te.DefaultTexture.MaterialID];
266 }
267 } 181 }
268 182
269 if (te.FaceTextures != null) 183 OSDMap mat;
184 try
270 { 185 {
271 foreach (var face in te.FaceTextures) 186 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
272 {
273 if (face != null)
274 {
275 lock (m_knownMaterials)
276 {
277 if (m_knownMaterials.ContainsKey(face.MaterialID))
278 mats[face.MaterialID] = m_knownMaterials[face.MaterialID];
279 }
280 }
281 }
282 } 187 }
283 if (mats.Count == 0) 188 catch (Exception e)
284 return;
285
286 OSDArray matsArr = new OSDArray();
287 foreach (KeyValuePair<UUID, OSDMap> kvp in mats)
288 { 189 {
289 OSDMap matOsd = new OSDMap(); 190 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
290 matOsd["ID"] = OSD.FromUUID(kvp.Key); 191 return;
291 matOsd["Material"] = kvp.Value;
292 matsArr.Add(matOsd);
293 } 192 }
294 193
295 OSDMap OSMaterials = new OSDMap(); 194 m_regionMaterials[id] = mat;
296 OSMaterials["Materials"] = matsArr;
297
298 lock (part.DynAttrs)
299 part.DynAttrs.SetStore("OpenSim", "Materials", OSMaterials);
300 }
301 catch (Exception e)
302 {
303 m_log.Warn("[MaterialsDemoModule]: exception in StoreMaterialsForPart() ", e);
304 } 195 }
305 } 196 }
306 197
@@ -308,8 +199,6 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
308 string param, IOSHttpRequest httpRequest, 199 string param, IOSHttpRequest httpRequest,
309 IOSHttpResponse httpResponse) 200 IOSHttpResponse httpResponse)
310 { 201 {
311 //m_log.Debug("[MaterialsDemoModule]: POST cap handler");
312
313 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); 202 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
314 OSDMap resp = new OSDMap(); 203 OSDMap resp = new OSDMap();
315 204
@@ -333,34 +222,38 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
333 { 222 {
334 foreach (OSD elem in (OSDArray)osd) 223 foreach (OSD elem in (OSDArray)osd)
335 { 224 {
336
337 try 225 try
338 { 226 {
339 UUID id = new UUID(elem.AsBinary(), 0); 227 UUID id = new UUID(elem.AsBinary(), 0);
340 228
341 lock (m_knownMaterials) 229 lock (m_regionMaterials)
342 { 230 {
343 if (m_knownMaterials.ContainsKey(id)) 231 if (m_regionMaterials.ContainsKey(id))
344 { 232 {
345 //m_log.Info("[MaterialsDemoModule]: request for known material ID: " + id.ToString());
346 OSDMap matMap = new OSDMap(); 233 OSDMap matMap = new OSDMap();
347 matMap["ID"] = OSD.FromBinary(id.GetBytes()); 234 matMap["ID"] = OSD.FromBinary(id.GetBytes());
348 235 matMap["Material"] = m_regionMaterials[id];
349 matMap["Material"] = m_knownMaterials[id];
350 respArr.Add(matMap); 236 respArr.Add(matMap);
351 } 237 }
352 else 238 else
353 m_log.Info("[MaterialsDemoModule]: request for UNKNOWN material ID: " + id.ToString()); 239 {
240 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
241
242 // Theoretically we could try to load the material from the assets service,
243 // but that shouldn't be necessary because the viewer should only request
244 // materials that exist in a prim on the region, and all of these materials
245 // are already stored in m_regionMaterials.
246 }
354 } 247 }
355 } 248 }
356 catch (Exception e) 249 catch (Exception e)
357 { 250 {
358 // report something here? 251 m_log.Error("Error getting materials in response to viewer request", e);
359 continue; 252 continue;
360 } 253 }
361 } 254 }
362 } 255 }
363 else if (osd is OSDMap) // reqest to assign a material 256 else if (osd is OSDMap) // request to assign a material
364 { 257 {
365 materialsFromViewer = osd as OSDMap; 258 materialsFromViewer = osd as OSDMap;
366 259
@@ -375,94 +268,118 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
375 { 268 {
376 foreach (OSDMap matsMap in matsArr) 269 foreach (OSDMap matsMap in matsArr)
377 { 270 {
378 //m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
379
380 uint primLocalID = 0; 271 uint primLocalID = 0;
381 try { primLocalID = matsMap["ID"].AsUInteger(); } 272 try {
382 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); } 273 primLocalID = matsMap["ID"].AsUInteger();
383 //m_log.Debug("[MaterialsDemoModule]: primLocalID: " + primLocalID.ToString()); 274 }
275 catch (Exception e) {
276 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
277 continue;
278 }
384 279
385 OSDMap mat = null; 280 OSDMap mat = null;
386 try { mat = matsMap["Material"] as OSDMap; } 281 try
387 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); } 282 {
388 //m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat)); 283 mat = matsMap["Material"] as OSDMap;
284 }
285 catch (Exception e)
286 {
287 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
288 continue;
289 }
290
291 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
292 if (sop == null)
293 {
294 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
295 continue;
296 }
297
298 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
299 if (te == null)
300 {
301 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
302 continue;
303 }
304
389 305
390 UUID id; 306 UUID id;
391 if (mat == null) 307 if (mat == null)
392 { 308 {
309 // This happens then the user removes a material from a prim
393 id = UUID.Zero; 310 id = UUID.Zero;
394 } 311 }
395 else 312 else
396 { 313 {
397 id = HashOsd(mat); 314 // Material UUID = hash of the material's data.
398 lock (m_knownMaterials) 315 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
399 m_knownMaterials[id] = mat; 316 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
317 using (var md5 = MD5.Create())
318 id = new UUID(md5.ComputeHash(data), 0);
319
320 lock (m_regionMaterials)
321 {
322 if (!m_regionMaterials.ContainsKey(id))
323 {
324 m_regionMaterials[id] = mat;
325
326 // This asset might exist already, but it's ok to try to store it again
327 string name = "Material " + ChooseMaterialName(mat, sop);
328 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
329 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, sop.OwnerID.ToString());
330 asset.Data = data;
331 m_scene.AssetService.Store(asset);
332 }
333 }
400 } 334 }
401 335
402 var sop = m_scene.GetSceneObjectPart(primLocalID);
403 if (sop == null)
404 m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + primLocalID.ToString());
405 else
406 {
407 var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
408 336
409 if (te == null) 337 int face = -1;
338
339 if (matsMap.ContainsKey("Face"))
340 {
341 face = matsMap["Face"].AsInteger();
342 if (te.FaceTextures == null) // && face == 0)
410 { 343 {
411 m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + primLocalID.ToString()); 344 if (te.DefaultTexture == null)
345 m_log.WarnFormat("[Materials]: te.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
346 else
347 te.DefaultTexture.MaterialID = id;
412 } 348 }
413 else 349 else
414 { 350 {
415 int face = -1; 351 if (te.FaceTextures.Length >= face - 1)
416
417 if (matsMap.ContainsKey("Face"))
418 {
419 face = matsMap["Face"].AsInteger();
420 if (te.FaceTextures == null) // && face == 0)
421 {
422 if (te.DefaultTexture == null)
423 m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
424 else
425 te.DefaultTexture.MaterialID = id;
426 }
427 else
428 {
429 if (te.FaceTextures.Length >= face - 1)
430 {
431 if (te.FaceTextures[face] == null)
432 te.DefaultTexture.MaterialID = id;
433 else
434 te.FaceTextures[face].MaterialID = id;
435 }
436 }
437 }
438 else
439 { 352 {
440 if (te.DefaultTexture != null) 353 if (te.FaceTextures[face] == null)
441 te.DefaultTexture.MaterialID = id; 354 te.DefaultTexture.MaterialID = id;
355 else
356 te.FaceTextures[face].MaterialID = id;
442 } 357 }
358 }
359 }
360 else
361 {
362 if (te.DefaultTexture != null)
363 te.DefaultTexture.MaterialID = id;
364 }
443 365
444 //m_log.DebugFormat("[MaterialsDemoModule]: in \"{0}\", setting material ID for face {1} to {2}", sop.Name, face, id); 366 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
445
446 //we cant use sop.UpdateTextureEntry(te); because it filters so do it manually
447
448 if (sop.ParentGroup != null)
449 {
450 sop.Shape.TextureEntry = te.GetBytes();
451 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
452 sop.UpdateFlag = UpdateRequired.FULL;
453 sop.ParentGroup.HasGroupChanged = true;
454 367
455 sop.ScheduleFullUpdate(); 368 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
369 sop.Shape.TextureEntry = te.GetBytes();
456 370
457 StoreMaterialsForPart(sop); 371 if (sop.ParentGroup != null)
458 } 372 {
459 } 373 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
374 sop.UpdateFlag = UpdateRequired.FULL;
375 sop.ParentGroup.HasGroupChanged = true;
376 sop.ScheduleFullUpdate();
460 } 377 }
461 } 378 }
462 } 379 }
463 catch (Exception e) 380 catch (Exception e)
464 { 381 {
465 m_log.Warn("[MaterialsDemoModule]: exception processing received material ", e); 382 m_log.Warn("[Materials]: exception processing received material ", e);
466 } 383 }
467 } 384 }
468 } 385 }
@@ -472,36 +389,63 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
472 } 389 }
473 catch (Exception e) 390 catch (Exception e)
474 { 391 {
475 m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload ", e); 392 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
476 //return ""; 393 //return "";
477 } 394 }
478 //m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
479 } 395 }
480 396
481 397
482 resp["Zipped"] = ZCompressOSD(respArr, false); 398 resp["Zipped"] = ZCompressOSD(respArr, false);
483 string response = OSDParser.SerializeLLSDXmlString(resp); 399 string response = OSDParser.SerializeLLSDXmlString(resp);
484 400
485 //m_log.Debug("[MaterialsDemoModule]: cap request: " + request); 401 //m_log.Debug("[Materials]: cap request: " + request);
486 //m_log.Debug("[MaterialsDemoModule]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary())); 402 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
487 //m_log.Debug("[MaterialsDemoModule]: cap response: " + response); 403 //m_log.Debug("[Materials]: cap response: " + response);
488 return response; 404 return response;
489 } 405 }
490 406
407 /// <summary>
408 /// Use heuristics to choose a good name for the material.
409 /// </summary>
410 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
411 {
412 UUID normMap = mat["NormMap"].AsUUID();
413 if (normMap != UUID.Zero)
414 {
415 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
416 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
417 return asset.Name;
418 }
419
420 UUID specMap = mat["SpecMap"].AsUUID();
421 if (specMap != UUID.Zero)
422 {
423 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
424 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
425 return asset.Name;
426 }
427
428 if (sop.Name != "Primitive")
429 return sop.Name;
430
431 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
432 return sop.ParentGroup.Name;
433
434 return "";
435 }
436
491 437
492 public string RenderMaterialsGetCap(string request, string path, 438 public string RenderMaterialsGetCap(string request, string path,
493 string param, IOSHttpRequest httpRequest, 439 string param, IOSHttpRequest httpRequest,
494 IOSHttpResponse httpResponse) 440 IOSHttpResponse httpResponse)
495 { 441 {
496 //m_log.Debug("[MaterialsDemoModule]: GET cap handler");
497
498 OSDMap resp = new OSDMap(); 442 OSDMap resp = new OSDMap();
499 int matsCount = 0; 443 int matsCount = 0;
500 OSDArray allOsd = new OSDArray(); 444 OSDArray allOsd = new OSDArray();
501 445
502 lock (m_knownMaterials) 446 lock (m_regionMaterials)
503 { 447 {
504 foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials) 448 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
505 { 449 {
506 OSDMap matMap = new OSDMap(); 450 OSDMap matMap = new OSDMap();
507 451
@@ -513,12 +457,11 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
513 } 457 }
514 458
515 resp["Zipped"] = ZCompressOSD(allOsd, false); 459 resp["Zipped"] = ZCompressOSD(allOsd, false);
516 //m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
517 460
518 return OSDParser.SerializeLLSDXmlString(resp); 461 return OSDParser.SerializeLLSDXmlString(resp);
519 } 462 }
520 463
521 static string ZippedOsdBytesToString(byte[] bytes) 464 private static string ZippedOsdBytesToString(byte[] bytes)
522 { 465 {
523 try 466 try
524 { 467 {
@@ -537,26 +480,27 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
537 /// <returns></returns> 480 /// <returns></returns>
538 private static UUID HashOsd(OSD osd) 481 private static UUID HashOsd(OSD osd)
539 { 482 {
483 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
540 using (var md5 = MD5.Create()) 484 using (var md5 = MD5.Create())
541 using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false))) 485 return new UUID(md5.ComputeHash(data), 0);
542 return new UUID(md5.ComputeHash(ms), 0);
543 } 486 }
544 487
545 public static OSD ZCompressOSD(OSD inOsd, bool useHeader) 488 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
546 { 489 {
547 OSD osd = null; 490 OSD osd = null;
548 491
492 byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
493
549 using (MemoryStream msSinkCompressed = new MemoryStream()) 494 using (MemoryStream msSinkCompressed = new MemoryStream())
550 { 495 {
551 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed, 496 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
552 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true)) 497 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
553 { 498 {
554 CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut); 499 zOut.Write(data, 0, data.Length);
555 zOut.Close();
556 } 500 }
557 501
558 msSinkCompressed.Seek(0L, SeekOrigin.Begin); 502 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
559 osd = OSD.FromBinary( msSinkCompressed.ToArray()); 503 osd = OSD.FromBinary(msSinkCompressed.ToArray());
560 } 504 }
561 505
562 return osd; 506 return osd;
@@ -571,94 +515,14 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
571 { 515 {
572 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true)) 516 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
573 { 517 {
574 CopyStream(new MemoryStream(input), zOut); 518 zOut.Write(input, 0, input.Length);
575 zOut.Close();
576 } 519 }
520
577 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin); 521 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
578 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray()); 522 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
579 } 523 }
580 524
581 return osd; 525 return osd;
582 } 526 }
583
584 static void CopyStream(System.IO.Stream input, System.IO.Stream output)
585 {
586 byte[] buffer = new byte[2048];
587 int len;
588 while ((len = input.Read(buffer, 0, 2048)) > 0)
589 {
590 output.Write(buffer, 0, len);
591 }
592
593 output.Flush();
594 }
595
596 // FIXME: This code is currently still in UuidGatherer since we cannot use Scene.EventManager as some
597 // calls to the gatherer are done for objects with no scene.
598// /// <summary>
599// /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
600// /// </summary>
601// /// <param name="part"></param>
602// /// <param name="assetUuids"></param>
603// private void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
604// {
605// // scan thru the dynAttrs map of this part for any textures used as materials
606// OSD osdMaterials = null;
607//
608// lock (part.DynAttrs)
609// {
610// if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
611// {
612// OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
613// if (materialsStore == null)
614// return;
615//
616// materialsStore.TryGetValue("Materials", out osdMaterials);
617// }
618//
619// if (osdMaterials != null)
620// {
621// //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
622//
623// if (osdMaterials is OSDArray)
624// {
625// OSDArray matsArr = osdMaterials as OSDArray;
626// foreach (OSDMap matMap in matsArr)
627// {
628// try
629// {
630// if (matMap.ContainsKey("Material"))
631// {
632// OSDMap mat = matMap["Material"] as OSDMap;
633// if (mat.ContainsKey("NormMap"))
634// {
635// UUID normalMapId = mat["NormMap"].AsUUID();
636// if (normalMapId != UUID.Zero)
637// {
638// assetUuids[normalMapId] = AssetType.Texture;
639// //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
640// }
641// }
642// if (mat.ContainsKey("SpecMap"))
643// {
644// UUID specularMapId = mat["SpecMap"].AsUUID();
645// if (specularMapId != UUID.Zero)
646// {
647// assetUuids[specularMapId] = AssetType.Texture;
648// //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
649// }
650// }
651// }
652//
653// }
654// catch (Exception e)
655// {
656// m_log.Warn("[MaterialsDemoModule]: exception getting materials: " + e.Message);
657// }
658// }
659// }
660// }
661// }
662// }
663 } 527 }
664} 528}