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; } }
|
public Type ReplaceableInterface { get { return null; } }
|
||||||
|
|
||||||
|
IImprovedAssetCache m_cache;
|
||||||
private Scene m_scene = null;
|
private Scene m_scene = null;
|
||||||
private bool m_enabled = false;
|
private bool m_enabled = false;
|
||||||
private int m_maxMaterialsPerTransaction = 50;
|
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)
|
public void Initialise(IConfigSource source)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +103,56 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
m_scene = scene;
|
m_scene = scene;
|
||||||
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
|
||||||
m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
|
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)
|
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
|
||||||
|
@ -145,12 +200,14 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
|
|
||||||
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
|
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
|
||||||
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
|
m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
|
||||||
|
m_scene.EventManager.OnBackup -= EventManager_OnBackup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegionLoaded(Scene scene)
|
public void RegionLoaded(Scene scene)
|
||||||
{
|
{
|
||||||
if (!m_enabled) return;
|
if (!m_enabled) return;
|
||||||
|
|
||||||
|
m_cache = scene.RequestModuleInterface<IImprovedAssetCache>();
|
||||||
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
|
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
|
||||||
if (featuresModule != null)
|
if (featuresModule != null)
|
||||||
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
|
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
|
||||||
|
@ -203,8 +260,17 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (m_regionMaterials)
|
lock (m_Materials)
|
||||||
m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
|
{
|
||||||
|
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)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -252,16 +318,15 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
if (id == UUID.Zero)
|
if (id == UUID.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (m_regionMaterials)
|
lock (m_Materials)
|
||||||
{
|
{
|
||||||
if (m_regionMaterials.ContainsKey(id))
|
if (m_Materials.ContainsKey(id))
|
||||||
|
{
|
||||||
|
m_MaterialsRefCount[id]++;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// get all asset so it gets into cache
|
|
||||||
AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
|
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 )
|
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);
|
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;
|
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);
|
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();
|
OSDMap matMap = new OSDMap();
|
||||||
matMap["ID"] = OSD.FromBinary(id.GetBytes());
|
matMap["ID"] = OSD.FromBinary(id.GetBytes());
|
||||||
matMap["Material"] = m_regionMaterials[id];
|
matMap["Material"] = m_Materials[id];
|
||||||
respArr.Add(matMap);
|
respArr.Add(matMap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -362,6 +428,7 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
|
|
||||||
OSDArray respArr = new OSDArray();
|
OSDArray respArr = new OSDArray();
|
||||||
|
|
||||||
|
HashSet<SceneObjectPart> parts = new HashSet<SceneObjectPart>();
|
||||||
if (req.ContainsKey("Zipped"))
|
if (req.ContainsKey("Zipped"))
|
||||||
{
|
{
|
||||||
OSD osd = null;
|
OSD osd = null;
|
||||||
|
@ -435,15 +502,16 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
id = StoreMaterialAsAsset(agentID, mat, sop);
|
id = getNewID(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
int face = -1;
|
int face = -1;
|
||||||
|
UUID oldid = UUID.Zero;
|
||||||
if (matsMap.ContainsKey("Face"))
|
if (matsMap.ContainsKey("Face"))
|
||||||
{
|
{
|
||||||
face = matsMap["Face"].AsInteger();
|
face = matsMap["Face"].AsInteger();
|
||||||
Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
|
Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
|
||||||
|
oldid = faceEntry.MaterialID;
|
||||||
faceEntry.MaterialID = id;
|
faceEntry.MaterialID = id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -451,19 +519,58 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
if (te.DefaultTexture == null)
|
if (te.DefaultTexture == null)
|
||||||
m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
|
m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
oldid = te.DefaultTexture.MaterialID;
|
||||||
te.DefaultTexture.MaterialID = id;
|
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);
|
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
|
||||||
|
|
||||||
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
|
// We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
|
||||||
sop.Shape.TextureEntry = te.GetBytes();
|
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.TriggerScriptChangedEvent(Changed.TEXTURE);
|
||||||
sop.ParentGroup.HasGroupChanged = true;
|
|
||||||
sop.ScheduleFullUpdate();
|
sop.ScheduleFullUpdate();
|
||||||
|
sop.ParentGroup.HasGroupChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,6 +598,40 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
return response;
|
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)
|
private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
|
||||||
{
|
{
|
||||||
UUID id;
|
UUID id;
|
||||||
|
@ -500,11 +641,12 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
using (var md5 = MD5.Create())
|
using (var md5 = MD5.Create())
|
||||||
id = new UUID(md5.ComputeHash(data), 0);
|
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
|
// This asset might exist already, but it's ok to try to store it again
|
||||||
string name = "Material " + ChooseMaterialName(mat, sop);
|
string name = "Material " + ChooseMaterialName(mat, sop);
|
||||||
|
@ -513,6 +655,8 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
asset.Data = data;
|
asset.Data = data;
|
||||||
m_scene.AssetService.Store(asset);
|
m_scene.AssetService.Store(asset);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
m_MaterialsRefCount[id]++;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -554,9 +698,9 @@ namespace OpenSim.Region.OptionalModules.Materials
|
||||||
int matsCount = 0;
|
int matsCount = 0;
|
||||||
OSDArray allOsd = new OSDArray();
|
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();
|
OSDMap matMap = new OSDMap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue