aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs')
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs190
1 files changed, 167 insertions, 23 deletions
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index 6cde92e..006b730 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -63,11 +63,16 @@ namespace OpenSim.Region.OptionalModules.Materials
63 63
64 public Type ReplaceableInterface { get { return null; } } 64 public Type ReplaceableInterface { get { return null; } }
65 65
66 IImprovedAssetCache 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 {
@@ -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)
@@ -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;
203 m_scene.EventManager.OnBackup -= EventManager_OnBackup;
148 } 204 }
149 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<IImprovedAssetCache>();
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 {
@@ -252,16 +318,15 @@ 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 328
261 // get all asset so it gets into cache
262 AssetBase matAsset = m_scene.AssetService.Get(id.ToString()); 329 AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
263
264// byte[] data = m_scene.AssetService.GetData(id.ToString());
265 if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 ) 330 if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
266 { 331 {
267 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);
@@ -280,7 +345,8 @@ namespace OpenSim.Region.OptionalModules.Materials
280 return; 345 return;
281 } 346 }
282 347
283 m_regionMaterials[id] = mat; 348 m_Materials[id] = mat;
349 m_MaterialsRefCount[id] = 1;
284 } 350 }
285 } 351 }
286 352
@@ -309,13 +375,13 @@ namespace OpenSim.Region.OptionalModules.Materials
309 { 375 {
310 UUID id = new UUID(elem.AsBinary(), 0); 376 UUID id = new UUID(elem.AsBinary(), 0);
311 377
312 lock (m_regionMaterials) 378 lock (m_Materials)
313 { 379 {
314 if (m_regionMaterials.ContainsKey(id)) 380 if (m_Materials.ContainsKey(id))
315 { 381 {
316 OSDMap matMap = new OSDMap(); 382 OSDMap matMap = new OSDMap();
317 matMap["ID"] = OSD.FromBinary(id.GetBytes()); 383 matMap["ID"] = OSD.FromBinary(id.GetBytes());
318 matMap["Material"] = m_regionMaterials[id]; 384 matMap["Material"] = m_Materials[id];
319 respArr.Add(matMap); 385 respArr.Add(matMap);
320 } 386 }
321 else 387 else
@@ -362,6 +428,7 @@ namespace OpenSim.Region.OptionalModules.Materials
362 428
363 OSDArray respArr = new OSDArray(); 429 OSDArray respArr = new OSDArray();
364 430
431 HashSet<SceneObjectPart> parts = new HashSet<SceneObjectPart>();
365 if (req.ContainsKey("Zipped")) 432 if (req.ContainsKey("Zipped"))
366 { 433 {
367 OSD osd = null; 434 OSD osd = null;
@@ -426,7 +493,7 @@ namespace OpenSim.Region.OptionalModules.Materials
426 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);
427 continue; 494 continue;
428 } 495 }
429 496
430 UUID id; 497 UUID id;
431 if (mat == null) 498 if (mat == null)
432 { 499 {
@@ -435,15 +502,16 @@ namespace OpenSim.Region.OptionalModules.Materials
435 } 502 }
436 else 503 else
437 { 504 {
438 id = StoreMaterialAsAsset(agentID, mat, sop); 505 id = getNewID(mat);
439 } 506 }
440 507
441 int face = -1; 508 int face = -1;
442 509 UUID oldid = UUID.Zero;
443 if (matsMap.ContainsKey("Face")) 510 if (matsMap.ContainsKey("Face"))
444 { 511 {
445 face = matsMap["Face"].AsInteger(); 512 face = matsMap["Face"].AsInteger();
446 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face); 513 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
514 oldid = faceEntry.MaterialID;
447 faceEntry.MaterialID = id; 515 faceEntry.MaterialID = id;
448 } 516 }
449 else 517 else
@@ -451,7 +519,10 @@ namespace OpenSim.Region.OptionalModules.Materials
451 if (te.DefaultTexture == null) 519 if (te.DefaultTexture == null)
452 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID); 520 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
453 else 521 else
522 {
523 oldid = te.DefaultTexture.MaterialID;
454 te.DefaultTexture.MaterialID = id; 524 te.DefaultTexture.MaterialID = id;
525 }
455 } 526 }
456 527
457 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); 528 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
@@ -459,11 +530,47 @@ namespace OpenSim.Region.OptionalModules.Materials
459 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually 530 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
460 sop.Shape.TextureEntry = te.GetBytes(); 531 sop.Shape.TextureEntry = te.GetBytes();
461 532
462 if (sop.ParentGroup != null) 533 lock(m_Materials)
534 {
535 if(oldid != UUID.Zero)
536 {
537 m_MaterialsRefCount[oldid]--;
538 if(m_MaterialsRefCount[oldid] <= 0)
539 {
540 m_Materials.Remove(oldid);
541 m_MaterialsRefCount.Remove(oldid);
542 m_cache.Expire(oldid.ToString());
543 }
544 }
545
546 if(id != UUID.Zero)
547 {
548 AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop);
549 if(asset != null)
550 {
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 }
560 }
561 }
562
563 if(!parts.Contains(sop))
564 parts.Add(sop);
565 }
566
567 foreach(SceneObjectPart sop in parts)
568 {
569 if (sop.ParentGroup != null && !sop.ParentGroup.IsDeleted)
463 { 570 {
464 sop.TriggerScriptChangedEvent(Changed.TEXTURE); 571 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
465 sop.ParentGroup.HasGroupChanged = true;
466 sop.ScheduleFullUpdate(); 572 sop.ScheduleFullUpdate();
573 sop.ParentGroup.HasGroupChanged = true;
467 } 574 }
468 } 575 }
469 } 576 }
@@ -491,6 +598,40 @@ namespace OpenSim.Region.OptionalModules.Materials
491 return response; 598 return response;
492 } 599 }
493 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
494 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop) 635 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
495 { 636 {
496 UUID id; 637 UUID id;
@@ -500,11 +641,12 @@ namespace OpenSim.Region.OptionalModules.Materials
500 using (var md5 = MD5.Create()) 641 using (var md5 = MD5.Create())
501 id = new UUID(md5.ComputeHash(data), 0); 642 id = new UUID(md5.ComputeHash(data), 0);
502 643
503 lock (m_regionMaterials) 644 lock (m_Materials)
504 { 645 {
505 if (!m_regionMaterials.ContainsKey(id)) 646 if (!m_Materials.ContainsKey(id))
506 { 647 {
507 m_regionMaterials[id] = mat; 648 m_Materials[id] = mat;
649 m_MaterialsRefCount[id] = 1;
508 650
509 // 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
510 string name = "Material " + ChooseMaterialName(mat, sop); 652 string name = "Material " + ChooseMaterialName(mat, sop);
@@ -513,6 +655,8 @@ namespace OpenSim.Region.OptionalModules.Materials
513 asset.Data = data; 655 asset.Data = data;
514 m_scene.AssetService.Store(asset); 656 m_scene.AssetService.Store(asset);
515 } 657 }
658 else
659 m_MaterialsRefCount[id]++;
516 } 660 }
517 return id; 661 return id;
518 } 662 }
@@ -554,9 +698,9 @@ namespace OpenSim.Region.OptionalModules.Materials
554 int matsCount = 0; 698 int matsCount = 0;
555 OSDArray allOsd = new OSDArray(); 699 OSDArray allOsd = new OSDArray();
556 700
557 lock (m_regionMaterials) 701 lock (m_Materials)
558 { 702 {
559 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials) 703 foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials)
560 { 704 {
561 OSDMap matMap = new OSDMap(); 705 OSDMap matMap = new OSDMap();
562 706