try to reduce the amount of assets created editing materials
parent
6526de04cb
commit
b5e7816b77
|
@ -63,11 +63,16 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
|
||||
public Type ReplaceableInterface { get { return null; } }
|
||||
|
||||
IImprovedAssetCache m_cache;
|
||||
private Scene m_scene = null;
|
||||
private bool m_enabled = false;
|
||||
private int m_maxMaterialsPerTransaction = 50;
|
||||
|
||||
public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
|
||||
public Dictionary<UUID, OSDMap> m_Materials = new Dictionary<UUID, OSDMap>();
|
||||
public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>();
|
||||
|
||||
private Dictionary<ulong, AssetBase> m_changes = new Dictionary<ulong, AssetBase>();
|
||||
private Dictionary<ulong, double> m_changesTime = new Dictionary<ulong, double>();
|
||||
|
||||
public void Initialise(IConfigSource source)
|
||||
{
|
||||
|
@ -98,6 +103,56 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
m_scene = scene;
|
||||
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||
m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
|
||||
m_scene.EventManager.OnBackup += EventManager_OnBackup;
|
||||
}
|
||||
|
||||
private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup)
|
||||
{
|
||||
List<AssetBase> toStore;
|
||||
List<ulong> hashlist;
|
||||
|
||||
|
||||
lock (m_Materials)
|
||||
{
|
||||
if(m_changes.Count == 0)
|
||||
return;
|
||||
|
||||
if(forcedBackup)
|
||||
{
|
||||
toStore = new List<AssetBase>(m_changes.Values);
|
||||
m_changes.Clear();
|
||||
m_changesTime.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
toStore = new List<AssetBase>();
|
||||
hashlist = new List<ulong>();
|
||||
double storetime = Util.GetTimeStampMS() - 60000;
|
||||
foreach(KeyValuePair<ulong,double> kvp in m_changesTime)
|
||||
{
|
||||
if(kvp.Value < storetime)
|
||||
{
|
||||
toStore.Add(m_changes[kvp.Key]);
|
||||
hashlist.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
foreach(ulong u in hashlist)
|
||||
{
|
||||
m_changesTime.Remove(u);
|
||||
m_changes.Remove(u);
|
||||
}
|
||||
}
|
||||
|
||||
if(toStore.Count > 0)
|
||||
Util.FireAndForget(delegate
|
||||
{
|
||||
foreach(AssetBase a in toStore)
|
||||
{
|
||||
a.Local = false;
|
||||
m_scene.AssetService.Store(a);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
|
||||
|
@ -145,12 +200,14 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
|
||||
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
|
||||
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
|
||||
m_scene.EventManager.OnBackup -= EventManager_OnBackup;
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!m_enabled) return;
|
||||
|
||||
m_cache = scene.RequestModuleInterface<IImprovedAssetCache>();
|
||||
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
|
||||
if (featuresModule != null)
|
||||
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
|
||||
|
@ -203,8 +260,17 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
{
|
||||
try
|
||||
{
|
||||
lock (m_regionMaterials)
|
||||
m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
|
||||
lock (m_Materials)
|
||||
{
|
||||
UUID id = matMap["ID"].AsUUID();
|
||||
if(m_Materials.ContainsKey(id))
|
||||
m_MaterialsRefCount[id]++;
|
||||
else
|
||||
{
|
||||
m_Materials[id] = (OSDMap)matMap["Material"];
|
||||
m_MaterialsRefCount[id] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -252,16 +318,15 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
if (id == UUID.Zero)
|
||||
return;
|
||||
|
||||
lock (m_regionMaterials)
|
||||
lock (m_Materials)
|
||||
{
|
||||
if (m_regionMaterials.ContainsKey(id))
|
||||
if (m_Materials.ContainsKey(id))
|
||||
{
|
||||
m_MaterialsRefCount[id]++;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// get all asset so it gets into cache
|
||||
AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
|
||||
|
||||
// byte[] data = m_scene.AssetService.GetData(id.ToString());
|
||||
if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
|
||||
{
|
||||
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
|
|||
return;
|
||||
}
|
||||
|
||||
m_regionMaterials[id] = mat;
|
||||
m_Materials[id] = mat;
|
||||
m_MaterialsRefCount[id] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,13 +375,13 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
{
|
||||
UUID id = new UUID(elem.AsBinary(), 0);
|
||||
|
||||
lock (m_regionMaterials)
|
||||
lock (m_Materials)
|
||||
{
|
||||
if (m_regionMaterials.ContainsKey(id))
|
||||
if (m_Materials.ContainsKey(id))
|
||||
{
|
||||
OSDMap matMap = new OSDMap();
|
||||
matMap["ID"] = OSD.FromBinary(id.GetBytes());
|
||||
matMap["Material"] = m_regionMaterials[id];
|
||||
matMap["Material"] = m_Materials[id];
|
||||
respArr.Add(matMap);
|
||||
}
|
||||
else
|
||||
|
@ -362,6 +428,7 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
|
||||
OSDArray respArr = new OSDArray();
|
||||
|
||||
HashSet<SceneObjectPart> parts = new HashSet<SceneObjectPart>();
|
||||
if (req.ContainsKey("Zipped"))
|
||||
{
|
||||
OSD osd = null;
|
||||
|
@ -426,7 +493,7 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
UUID id;
|
||||
if (mat == null)
|
||||
{
|
||||
|
@ -435,15 +502,16 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
}
|
||||
else
|
||||
{
|
||||
id = StoreMaterialAsAsset(agentID, mat, sop);
|
||||
id = getNewID(mat);
|
||||
}
|
||||
|
||||
int face = -1;
|
||||
|
||||
UUID oldid = UUID.Zero;
|
||||
if (matsMap.ContainsKey("Face"))
|
||||
{
|
||||
face = matsMap["Face"].AsInteger();
|
||||
Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
|
||||
oldid = faceEntry.MaterialID;
|
||||
faceEntry.MaterialID = id;
|
||||
}
|
||||
else
|
||||
|
@ -451,7 +519,10 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
if (te.DefaultTexture == null)
|
||||
m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
|
||||
else
|
||||
{
|
||||
oldid = te.DefaultTexture.MaterialID;
|
||||
te.DefaultTexture.MaterialID = id;
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
|||
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
|
||||
sop.Shape.TextureEntry = te.GetBytes();
|
||||
|
||||
if (sop.ParentGroup != null)
|
||||
lock(m_Materials)
|
||||
{
|
||||
if(oldid != UUID.Zero)
|
||||
{
|
||||
m_MaterialsRefCount[oldid]--;
|
||||
if(m_MaterialsRefCount[oldid] <= 0)
|
||||
{
|
||||
m_Materials.Remove(oldid);
|
||||
m_MaterialsRefCount.Remove(oldid);
|
||||
m_cache.Expire(oldid.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if(id != UUID.Zero)
|
||||
{
|
||||
AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop);
|
||||
if(asset != null)
|
||||
{
|
||||
ulong materialHash = (ulong)primLocalID << 32;
|
||||
if(face < 0)
|
||||
materialHash += 0xffffffff;
|
||||
else
|
||||
materialHash +=(ulong)face;
|
||||
|
||||
m_changes[materialHash] = asset;
|
||||
m_changesTime[materialHash] = Util.GetTimeStampMS();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!parts.Contains(sop))
|
||||
parts.Add(sop);
|
||||
}
|
||||
|
||||
foreach(SceneObjectPart sop in parts)
|
||||
{
|
||||
if (sop.ParentGroup != null && !sop.ParentGroup.IsDeleted)
|
||||
{
|
||||
sop.TriggerScriptChangedEvent(Changed.TEXTURE);
|
||||
sop.ParentGroup.HasGroupChanged = true;
|
||||
sop.ScheduleFullUpdate();
|
||||
sop.ParentGroup.HasGroupChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +598,40 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
return response;
|
||||
}
|
||||
|
||||
private UUID getNewID(OSDMap mat)
|
||||
{
|
||||
// ugly and done twice but keep compatibility for now
|
||||
Byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
|
||||
using (var md5 = MD5.Create())
|
||||
return new UUID(md5.ComputeHash(data), 0);
|
||||
}
|
||||
|
||||
private AssetBase CacheMaterialAsAsset(UUID id, UUID agentID, OSDMap mat, SceneObjectPart sop)
|
||||
{
|
||||
AssetBase asset = null;
|
||||
lock (m_Materials)
|
||||
{
|
||||
if (!m_Materials.ContainsKey(id))
|
||||
{
|
||||
m_Materials[id] = mat;
|
||||
m_MaterialsRefCount[id] = 1;
|
||||
|
||||
byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
|
||||
|
||||
// This asset might exist already, but it's ok to try to store it again
|
||||
string name = "Material " + ChooseMaterialName(mat, sop);
|
||||
name = name.Substring(0, Math.Min(64, name.Length)).Trim();
|
||||
asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
|
||||
asset.Data = data;
|
||||
asset.Local = true;
|
||||
m_cache.Cache(asset);
|
||||
}
|
||||
else
|
||||
m_MaterialsRefCount[id]++;
|
||||
}
|
||||
return asset;
|
||||
}
|
||||
|
||||
private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
|
||||
{
|
||||
UUID id;
|
||||
|
@ -500,11 +641,12 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
using (var md5 = MD5.Create())
|
||||
id = new UUID(md5.ComputeHash(data), 0);
|
||||
|
||||
lock (m_regionMaterials)
|
||||
lock (m_Materials)
|
||||
{
|
||||
if (!m_regionMaterials.ContainsKey(id))
|
||||
if (!m_Materials.ContainsKey(id))
|
||||
{
|
||||
m_regionMaterials[id] = mat;
|
||||
m_Materials[id] = mat;
|
||||
m_MaterialsRefCount[id] = 1;
|
||||
|
||||
// This asset might exist already, but it's ok to try to store it again
|
||||
string name = "Material " + ChooseMaterialName(mat, sop);
|
||||
|
@ -513,6 +655,8 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
asset.Data = data;
|
||||
m_scene.AssetService.Store(asset);
|
||||
}
|
||||
else
|
||||
m_MaterialsRefCount[id]++;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
@ -554,9 +698,9 @@ namespace OpenSim.Region.OptionalModules.Materials
|
|||
int matsCount = 0;
|
||||
OSDArray allOsd = new OSDArray();
|
||||
|
||||
lock (m_regionMaterials)
|
||||
lock (m_Materials)
|
||||
{
|
||||
foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
|
||||
foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials)
|
||||
{
|
||||
OSDMap matMap = new OSDMap();
|
||||
|
||||
|
|
Loading…
Reference in New Issue