aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
parentAdd a build script. (diff)
downloadopensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs453
1 files changed, 314 insertions, 139 deletions
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index e95889d..e8cb052 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -59,15 +59,20 @@ namespace OpenSim.Region.OptionalModules.Materials
59 { 59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61 61
62 public string Name { get { return "MaterialsModule"; } } 62 public string Name { get { return "MaterialsModule"; } }
63 63
64 public Type ReplaceableInterface { get { return null; } } 64 public Type ReplaceableInterface { get { return null; } }
65 65
66 IAssetCache m_cache;
66 private Scene m_scene = null; 67 private Scene m_scene = null;
67 private bool m_enabled = false; 68 private bool m_enabled = false;
68 private int m_maxMaterialsPerTransaction = 50; 69 private int m_maxMaterialsPerTransaction = 50;
69 70
70 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>(); 71 public Dictionary<UUID, OSDMap> m_Materials = new Dictionary<UUID, OSDMap>();
72 public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>();
73
74 private Dictionary<ulong, AssetBase> m_changes = new Dictionary<ulong, AssetBase>();
75 private Dictionary<ulong, double> m_changesTime = new Dictionary<ulong, double>();
71 76
72 public void Initialise(IConfigSource source) 77 public void Initialise(IConfigSource source)
73 { 78 {
@@ -83,13 +88,13 @@ namespace OpenSim.Region.OptionalModules.Materials
83 if (m_enabled) 88 if (m_enabled)
84 m_log.DebugFormat("[Materials]: Initialized"); 89 m_log.DebugFormat("[Materials]: Initialized");
85 } 90 }
86 91
87 public void Close() 92 public void Close()
88 { 93 {
89 if (!m_enabled) 94 if (!m_enabled)
90 return; 95 return;
91 } 96 }
92 97
93 public void AddRegion(Scene scene) 98 public void AddRegion(Scene scene)
94 { 99 {
95 if (!m_enabled) 100 if (!m_enabled)
@@ -98,6 +103,56 @@ namespace OpenSim.Region.OptionalModules.Materials
98 m_scene = scene; 103 m_scene = scene;
99 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 104 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
100 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; 105 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
106 m_scene.EventManager.OnBackup += EventManager_OnBackup;
107 }
108
109 private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup)
110 {
111 List<AssetBase> toStore;
112 List<ulong> hashlist;
113
114
115 lock (m_Materials)
116 {
117 if(m_changes.Count == 0)
118 return;
119
120 if(forcedBackup)
121 {
122 toStore = new List<AssetBase>(m_changes.Values);
123 m_changes.Clear();
124 m_changesTime.Clear();
125 }
126 else
127 {
128 toStore = new List<AssetBase>();
129 hashlist = new List<ulong>();
130 double storetime = Util.GetTimeStampMS() - 60000;
131 foreach(KeyValuePair<ulong,double> kvp in m_changesTime)
132 {
133 if(kvp.Value < storetime)
134 {
135 toStore.Add(m_changes[kvp.Key]);
136 hashlist.Add(kvp.Key);
137 }
138 }
139 foreach(ulong u in hashlist)
140 {
141 m_changesTime.Remove(u);
142 m_changes.Remove(u);
143 }
144 }
145
146 if(toStore.Count > 0)
147 Util.FireAndForget(delegate
148 {
149 foreach(AssetBase a in toStore)
150 {
151 a.Local = false;
152 m_scene.AssetService.Store(a);
153 }
154 });
155 }
101 } 156 }
102 157
103 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) 158 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
@@ -111,7 +166,7 @@ namespace OpenSim.Region.OptionalModules.Materials
111 { 166 {
112 string capsBase = "/CAPS/" + caps.CapsObjectPath; 167 string capsBase = "/CAPS/" + caps.CapsObjectPath;
113 168
114 IRequestHandler renderMaterialsPostHandler 169 IRequestHandler renderMaterialsPostHandler
115 = new RestStreamHandler("POST", capsBase + "/", 170 = new RestStreamHandler("POST", capsBase + "/",
116 (request, path, param, httpRequest, httpResponse) 171 (request, path, param, httpRequest, httpResponse)
117 => RenderMaterialsPostCap(request, agentID), 172 => RenderMaterialsPostCap(request, agentID),
@@ -122,7 +177,7 @@ namespace OpenSim.Region.OptionalModules.Materials
122 // and POST handlers, (at least at the time this was originally written), so we first set up a POST 177 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
123 // handler normally and then add a GET handler via MainServer 178 // handler normally and then add a GET handler via MainServer
124 179
125 IRequestHandler renderMaterialsGetHandler 180 IRequestHandler renderMaterialsGetHandler
126 = new RestStreamHandler("GET", capsBase + "/", 181 = new RestStreamHandler("GET", capsBase + "/",
127 (request, path, param, httpRequest, httpResponse) 182 (request, path, param, httpRequest, httpResponse)
128 => RenderMaterialsGetCap(request), 183 => RenderMaterialsGetCap(request),
@@ -130,14 +185,14 @@ namespace OpenSim.Region.OptionalModules.Materials
130 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler); 185 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
131 186
132 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well 187 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
133 IRequestHandler renderMaterialsPutHandler 188 IRequestHandler renderMaterialsPutHandler
134 = new RestStreamHandler("PUT", capsBase + "/", 189 = new RestStreamHandler("PUT", capsBase + "/",
135 (request, path, param, httpRequest, httpResponse) 190 (request, path, param, httpRequest, httpResponse)
136 => RenderMaterialsPostCap(request, agentID), 191 => RenderMaterialsPutCap(request, agentID),
137 "RenderMaterials", null); 192 "RenderMaterials", null);
138 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler); 193 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
139 } 194 }
140 195
141 public void RemoveRegion(Scene scene) 196 public void RemoveRegion(Scene scene)
142 { 197 {
143 if (!m_enabled) 198 if (!m_enabled)
@@ -145,12 +200,14 @@ namespace OpenSim.Region.OptionalModules.Materials
145 200
146 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 201 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
147 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene; 202 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
148 } 203 m_scene.EventManager.OnBackup -= EventManager_OnBackup;
149 204 }
205
150 public void RegionLoaded(Scene scene) 206 public void RegionLoaded(Scene scene)
151 { 207 {
152 if (!m_enabled) return; 208 if (!m_enabled) return;
153 209
210 m_cache = scene.RequestModuleInterface<IAssetCache>();
154 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>(); 211 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
155 if (featuresModule != null) 212 if (featuresModule != null)
156 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest; 213 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
@@ -203,8 +260,17 @@ namespace OpenSim.Region.OptionalModules.Materials
203 { 260 {
204 try 261 try
205 { 262 {
206 lock (m_regionMaterials) 263 lock (m_Materials)
207 m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"]; 264 {
265 UUID id = matMap["ID"].AsUUID();
266 if(m_Materials.ContainsKey(id))
267 m_MaterialsRefCount[id]++;
268 else
269 {
270 m_Materials[id] = (OSDMap)matMap["Material"];
271 m_MaterialsRefCount[id] = 1;
272 }
273 }
208 } 274 }
209 catch (Exception e) 275 catch (Exception e)
210 { 276 {
@@ -219,7 +285,7 @@ namespace OpenSim.Region.OptionalModules.Materials
219 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'. 285 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
220 /// </summary> 286 /// </summary>
221 private void GetStoredMaterialsInPart(SceneObjectPart part) 287 private void GetStoredMaterialsInPart(SceneObjectPart part)
222 { 288 {
223 if (part.Shape == null) 289 if (part.Shape == null)
224 return; 290 return;
225 291
@@ -233,7 +299,7 @@ namespace OpenSim.Region.OptionalModules.Materials
233 GetStoredMaterialInFace(part, te.DefaultTexture); 299 GetStoredMaterialInFace(part, te.DefaultTexture);
234 else 300 else
235 m_log.WarnFormat( 301 m_log.WarnFormat(
236 "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.", 302 "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.",
237 part.Name, part.ParentGroup.Name, m_scene.Name); 303 part.Name, part.ParentGroup.Name, m_scene.Name);
238 304
239 foreach (Primitive.TextureEntryFace face in te.FaceTextures) 305 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
@@ -252,18 +318,22 @@ namespace OpenSim.Region.OptionalModules.Materials
252 if (id == UUID.Zero) 318 if (id == UUID.Zero)
253 return; 319 return;
254 320
255 lock (m_regionMaterials) 321 lock (m_Materials)
256 { 322 {
257 if (m_regionMaterials.ContainsKey(id)) 323 if (m_Materials.ContainsKey(id))
324 {
325 m_MaterialsRefCount[id]++;
258 return; 326 return;
259 327 }
260 byte[] data = m_scene.AssetService.GetData(id.ToString()); 328
261 if (data == null) 329 AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
330 if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
262 { 331 {
263 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id); 332 //m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
264 return; 333 return;
265 } 334 }
266 335
336 byte[] data = matAsset.Data;
267 OSDMap mat; 337 OSDMap mat;
268 try 338 try
269 { 339 {
@@ -275,7 +345,8 @@ namespace OpenSim.Region.OptionalModules.Materials
275 return; 345 return;
276 } 346 }
277 347
278 m_regionMaterials[id] = mat; 348 m_Materials[id] = mat;
349 m_MaterialsRefCount[id] = 1;
279 } 350 }
280 } 351 }
281 352
@@ -284,8 +355,6 @@ namespace OpenSim.Region.OptionalModules.Materials
284 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); 355 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
285 OSDMap resp = new OSDMap(); 356 OSDMap resp = new OSDMap();
286 357
287 OSDMap materialsFromViewer = null;
288
289 OSDArray respArr = new OSDArray(); 358 OSDArray respArr = new OSDArray();
290 359
291 if (req.ContainsKey("Zipped")) 360 if (req.ContainsKey("Zipped"))
@@ -294,154 +363,224 @@ namespace OpenSim.Region.OptionalModules.Materials
294 363
295 byte[] inBytes = req["Zipped"].AsBinary(); 364 byte[] inBytes = req["Zipped"].AsBinary();
296 365
297 try 366 try
298 { 367 {
299 osd = ZDecompressBytesToOsd(inBytes); 368 osd = ZDecompressBytesToOsd(inBytes);
300 369
301 if (osd != null) 370 if (osd != null && osd is OSDArray)
302 { 371 {
303 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries 372 foreach (OSD elem in (OSDArray)osd)
304 { 373 {
305 foreach (OSD elem in (OSDArray)osd) 374 try
306 { 375 {
307 try 376 UUID id = new UUID(elem.AsBinary(), 0);
308 {
309 UUID id = new UUID(elem.AsBinary(), 0);
310 377
311 lock (m_regionMaterials) 378 lock (m_Materials)
379 {
380 if (m_Materials.ContainsKey(id))
312 { 381 {
313 if (m_regionMaterials.ContainsKey(id)) 382 OSDMap matMap = new OSDMap();
314 { 383 matMap["ID"] = OSD.FromBinary(id.GetBytes());
315 OSDMap matMap = new OSDMap(); 384 matMap["Material"] = m_Materials[id];
316 matMap["ID"] = OSD.FromBinary(id.GetBytes()); 385 respArr.Add(matMap);
317 matMap["Material"] = m_regionMaterials[id]; 386 }
318 respArr.Add(matMap); 387 else
319 } 388 {
320 else 389 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
321 {
322 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
323 390
324 // Theoretically we could try to load the material from the assets service, 391 // Theoretically we could try to load the material from the assets service,
325 // but that shouldn't be necessary because the viewer should only request 392 // but that shouldn't be necessary because the viewer should only request
326 // materials that exist in a prim on the region, and all of these materials 393 // materials that exist in a prim on the region, and all of these materials
327 // are already stored in m_regionMaterials. 394 // are already stored in m_regionMaterials.
328 }
329 } 395 }
330 } 396 }
331 catch (Exception e) 397 }
332 { 398 catch (Exception e)
333 m_log.Error("Error getting materials in response to viewer request", e); 399 {
334 continue; 400 m_log.Error("Error getting materials in response to viewer request", e);
335 } 401 continue;
336 } 402 }
337 } 403 }
338 else if (osd is OSDMap) // request to assign a material 404 }
339 { 405 }
340 materialsFromViewer = osd as OSDMap; 406 catch (Exception e)
407 {
408 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
409 //return "";
410 }
411 }
412
413 resp["Zipped"] = ZCompressOSD(respArr, false);
414 string response = OSDParser.SerializeLLSDXmlString(resp);
415
416 //m_log.Debug("[Materials]: cap request: " + request);
417 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
418 //m_log.Debug("[Materials]: cap response: " + response);
419 return response;
420 }
421
422 public string RenderMaterialsPutCap(string request, UUID agentID)
423 {
424 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
425 OSDMap resp = new OSDMap();
426
427 OSDMap materialsFromViewer = null;
428
429 OSDArray respArr = new OSDArray();
430
431 HashSet<SceneObjectPart> parts = new HashSet<SceneObjectPart>();
432 if (req.ContainsKey("Zipped"))
433 {
434 OSD osd = null;
435
436 byte[] inBytes = req["Zipped"].AsBinary();
341 437
342 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace")) 438 try
439 {
440 osd = ZDecompressBytesToOsd(inBytes);
441
442 if (osd != null && osd is OSDMap)
443 {
444 materialsFromViewer = osd as OSDMap;
445
446 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
447 {
448 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
449 if (matsOsd is OSDArray)
343 { 450 {
344 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"]; 451 OSDArray matsArr = matsOsd as OSDArray;
345 if (matsOsd is OSDArray)
346 {
347 OSDArray matsArr = matsOsd as OSDArray;
348 452
349 try 453 try
454 {
455 foreach (OSDMap matsMap in matsArr)
350 { 456 {
351 foreach (OSDMap matsMap in matsArr) 457 uint primLocalID = 0;
352 { 458 try {
353 uint primLocalID = 0; 459 primLocalID = matsMap["ID"].AsUInteger();
354 try { 460 }
355 primLocalID = matsMap["ID"].AsUInteger(); 461 catch (Exception e) {
356 } 462 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
357 catch (Exception e) { 463 continue;
358 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message); 464 }
359 continue;
360 }
361 465
362 OSDMap mat = null; 466 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
363 try 467 if (sop == null)
364 { 468 {
365 mat = matsMap["Material"] as OSDMap; 469 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
366 } 470 continue;
367 catch (Exception e) 471 }
368 {
369 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
370 continue;
371 }
372 472
373 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID); 473 if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
374 if (sop == null) 474 {
375 { 475 m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID);
376 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString()); 476 continue;
377 continue; 477 }
378 }
379 478
380 if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID)) 479 OSDMap mat = null;
381 { 480 try
382 m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID); 481 {
383 continue; 482 mat = matsMap["Material"] as OSDMap;
384 } 483 }
484 catch (Exception e)
485 {
486 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
487 continue;
488 }
385 489
386 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length); 490 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
387 if (te == null) 491 if (te == null)
388 { 492 {
389 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID); 493 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
390 continue; 494 continue;
391 } 495 }
392 496
497 UUID id;
498 if (mat == null)
499 {
500 // This happens then the user removes a material from a prim
501 id = UUID.Zero;
502 }
503 else
504 {
505 id = getNewID(mat);
506 }
393 507
394 UUID id; 508 int face = -1;
395 if (mat == null) 509 UUID oldid = UUID.Zero;
396 { 510 if (matsMap.ContainsKey("Face"))
397 // This happens then the user removes a material from a prim 511 {
398 id = UUID.Zero; 512 face = matsMap["Face"].AsInteger();
399 } 513 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
514 oldid = faceEntry.MaterialID;
515 faceEntry.MaterialID = id;
516 }
517 else
518 {
519 if (te.DefaultTexture == null)
520 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
400 else 521 else
401 { 522 {
402 id = StoreMaterialAsAsset(agentID, mat, sop); 523 oldid = te.DefaultTexture.MaterialID;
524 te.DefaultTexture.MaterialID = id;
403 } 525 }
526 }
404 527
528 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
405 529
406 int face = -1; 530 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
531 sop.Shape.TextureEntry = te.GetBytes();
407 532
408 if (matsMap.ContainsKey("Face")) 533 lock(m_Materials)
409 { 534 {
410 face = matsMap["Face"].AsInteger(); 535 if(oldid != UUID.Zero && m_MaterialsRefCount.ContainsKey(oldid))
411 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
412 faceEntry.MaterialID = id;
413 }
414 else
415 { 536 {
416 if (te.DefaultTexture == null) 537 m_MaterialsRefCount[oldid]--;
417 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID); 538 if(m_MaterialsRefCount[oldid] <= 0)
418 else 539 {
419 te.DefaultTexture.MaterialID = id; 540 m_Materials.Remove(oldid);
541 m_MaterialsRefCount.Remove(oldid);
542 m_cache.Expire(oldid.ToString());
543 }
420 } 544 }
421 545
422 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); 546 if(id != UUID.Zero)
423
424 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
425 sop.Shape.TextureEntry = te.GetBytes();
426
427 if (sop.ParentGroup != null)
428 { 547 {
429 sop.TriggerScriptChangedEvent(Changed.TEXTURE); 548 AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop);
430 sop.UpdateFlag = UpdateRequired.FULL; 549 if(asset != null)
431 sop.ParentGroup.HasGroupChanged = true; 550 {
432 sop.ScheduleFullUpdate(); 551 ulong materialHash = (ulong)primLocalID << 32;
552 if(face < 0)
553 materialHash += 0xffffffff;
554 else
555 materialHash +=(ulong)face;
556
557 m_changes[materialHash] = asset;
558 m_changesTime[materialHash] = Util.GetTimeStampMS();
559 }
433 } 560 }
434 } 561 }
562
563 if(!parts.Contains(sop))
564 parts.Add(sop);
435 } 565 }
436 catch (Exception e) 566
567 foreach(SceneObjectPart sop in parts)
437 { 568 {
438 m_log.Warn("[Materials]: exception processing received material ", e); 569 if (sop.ParentGroup != null && !sop.ParentGroup.IsDeleted)
570 {
571 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
572 sop.ScheduleFullUpdate();
573 sop.ParentGroup.HasGroupChanged = true;
574 }
439 } 575 }
440 } 576 }
577 catch (Exception e)
578 {
579 m_log.Warn("[Materials]: exception processing received material ", e);
580 }
441 } 581 }
442 } 582 }
443 } 583 }
444
445 } 584 }
446 catch (Exception e) 585 catch (Exception e)
447 { 586 {
@@ -450,7 +589,6 @@ namespace OpenSim.Region.OptionalModules.Materials
450 } 589 }
451 } 590 }
452 591
453
454 resp["Zipped"] = ZCompressOSD(respArr, false); 592 resp["Zipped"] = ZCompressOSD(respArr, false);
455 string response = OSDParser.SerializeLLSDXmlString(resp); 593 string response = OSDParser.SerializeLLSDXmlString(resp);
456 594
@@ -460,6 +598,40 @@ namespace OpenSim.Region.OptionalModules.Materials
460 return response; 598 return response;
461 } 599 }
462 600
601 private UUID getNewID(OSDMap mat)
602 {
603 // ugly and done twice but keep compatibility for now
604 Byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
605 using (var md5 = MD5.Create())
606 return new UUID(md5.ComputeHash(data), 0);
607 }
608
609 private AssetBase CacheMaterialAsAsset(UUID id, UUID agentID, OSDMap mat, SceneObjectPart sop)
610 {
611 AssetBase asset = null;
612 lock (m_Materials)
613 {
614 if (!m_Materials.ContainsKey(id))
615 {
616 m_Materials[id] = mat;
617 m_MaterialsRefCount[id] = 1;
618
619 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
620
621 // This asset might exist already, but it's ok to try to store it again
622 string name = "Material " + ChooseMaterialName(mat, sop);
623 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
624 asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
625 asset.Data = data;
626 asset.Local = true;
627 m_cache.Cache(asset);
628 }
629 else
630 m_MaterialsRefCount[id]++;
631 }
632 return asset;
633 }
634
463 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop) 635 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
464 { 636 {
465 UUID id; 637 UUID id;
@@ -469,11 +641,12 @@ namespace OpenSim.Region.OptionalModules.Materials
469 using (var md5 = MD5.Create()) 641 using (var md5 = MD5.Create())
470 id = new UUID(md5.ComputeHash(data), 0); 642 id = new UUID(md5.ComputeHash(data), 0);
471 643
472 lock (m_regionMaterials) 644 lock (m_Materials)
473 { 645 {
474 if (!m_regionMaterials.ContainsKey(id)) 646 if (!m_Materials.ContainsKey(id))
475 { 647 {
476 m_regionMaterials[id] = mat; 648 m_Materials[id] = mat;
649 m_MaterialsRefCount[id] = 1;
477 650
478 // This asset might exist already, but it's ok to try to store it again 651 // This asset might exist already, but it's ok to try to store it again
479 string name = "Material " + ChooseMaterialName(mat, sop); 652 string name = "Material " + ChooseMaterialName(mat, sop);
@@ -482,6 +655,8 @@ namespace OpenSim.Region.OptionalModules.Materials
482 asset.Data = data; 655 asset.Data = data;
483 m_scene.AssetService.Store(asset); 656 m_scene.AssetService.Store(asset);
484 } 657 }
658 else
659 m_MaterialsRefCount[id]++;
485 } 660 }
486 return id; 661 return id;
487 } 662 }
@@ -509,7 +684,7 @@ namespace OpenSim.Region.OptionalModules.Materials
509 684
510 if (sop.Name != "Primitive") 685 if (sop.Name != "Primitive")
511 return sop.Name; 686 return sop.Name;
512 687
513 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive")) 688 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
514 return sop.ParentGroup.Name; 689 return sop.ParentGroup.Name;
515 690
@@ -523,9 +698,9 @@ namespace OpenSim.Region.OptionalModules.Materials
523 int matsCount = 0; 698 int matsCount = 0;
524 OSDArray allOsd = new OSDArray(); 699 OSDArray allOsd = new OSDArray();
525 700
526 lock (m_regionMaterials) 701 lock (m_Materials)
527 { 702 {
528 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials) 703 foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials)
529 { 704 {
530 OSDMap matMap = new OSDMap(); 705 OSDMap matMap = new OSDMap();
531 706
@@ -573,7 +748,7 @@ namespace OpenSim.Region.OptionalModules.Materials
573 748
574 using (MemoryStream msSinkCompressed = new MemoryStream()) 749 using (MemoryStream msSinkCompressed = new MemoryStream())
575 { 750 {
576 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed, 751 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
577 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true)) 752 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
578 { 753 {
579 zOut.Write(data, 0, data.Length); 754 zOut.Write(data, 0, data.Length);