diff options
Add code to convert legacy materials stored in DynAttrs to new asset format and store them as assets
Diffstat (limited to 'OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs')
-rw-r--r-- | OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs | 122 |
1 files changed, 102 insertions, 20 deletions
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs index 4b635d8..1b5a7a3 100644 --- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs +++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs | |||
@@ -149,12 +149,87 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
149 | } | 149 | } |
150 | 150 | ||
151 | /// <summary> | 151 | /// <summary> |
152 | /// Searches the part for any legacy materials stored in DynAttrs and converts them to assets, replacing | ||
153 | /// the MaterialIDs in the TextureEntries for the part. | ||
154 | /// Deletes the legacy materials from the part as they are no longer needed. | ||
155 | /// </summary> | ||
156 | /// <param name="part"></param> | ||
157 | private void ConvertLegacyMaterialsInPart(SceneObjectPart part) | ||
158 | { | ||
159 | if (part.DynAttrs == null) | ||
160 | return; | ||
161 | |||
162 | var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); | ||
163 | if (te == null) | ||
164 | return; | ||
165 | |||
166 | OSD OSMaterials = null; | ||
167 | OSDArray matsArr = null; | ||
168 | |||
169 | lock (part.DynAttrs) | ||
170 | { | ||
171 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) | ||
172 | { | ||
173 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); | ||
174 | |||
175 | if (materialsStore == null) | ||
176 | return; | ||
177 | |||
178 | materialsStore.TryGetValue("Materials", out OSMaterials); | ||
179 | } | ||
180 | |||
181 | if (OSMaterials != null && OSMaterials is OSDArray) | ||
182 | matsArr = OSMaterials as OSDArray; | ||
183 | else | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | if (matsArr == null) | ||
188 | return; | ||
189 | |||
190 | foreach (OSD elemOsd in matsArr) | ||
191 | { | ||
192 | if (elemOsd != null && elemOsd is OSDMap) | ||
193 | { | ||
194 | OSDMap matMap = elemOsd as OSDMap; | ||
195 | if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material")) | ||
196 | { | ||
197 | UUID id = matMap["ID"].AsUUID(); | ||
198 | OSDMap material = (OSDMap)matMap["Material"]; | ||
199 | bool used = false; | ||
200 | |||
201 | foreach (var face in te.FaceTextures) | ||
202 | if (face.MaterialID == id) | ||
203 | used = true; | ||
204 | |||
205 | if (used) | ||
206 | { // store legacy material in new asset format, and update the part texture entry with the new hashed UUID | ||
207 | |||
208 | var newId = StoreMaterialAsAsset(part.CreatorID, material, part); | ||
209 | foreach (var face in te.FaceTextures) | ||
210 | if (face.MaterialID == id) | ||
211 | face.MaterialID = newId; | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | part.Shape.TextureEntry = te.GetBytes(); | ||
218 | |||
219 | lock (part.DynAttrs) | ||
220 | part.DynAttrs.RemoveStore("OpenSim", "Materials"); | ||
221 | } | ||
222 | |||
223 | /// <summary> | ||
152 | /// Find the materials used in the SOP, and add them to 'm_regionMaterials'. | 224 | /// Find the materials used in the SOP, and add them to 'm_regionMaterials'. |
153 | /// </summary> | 225 | /// </summary> |
154 | private void GetStoredMaterialsInPart(SceneObjectPart part) | 226 | private void GetStoredMaterialsInPart(SceneObjectPart part) |
155 | { | 227 | { |
156 | if (part.Shape == null) | 228 | if (part.Shape == null) |
157 | return; | 229 | return; |
230 | |||
231 | ConvertLegacyMaterialsInPart(part); | ||
232 | |||
158 | var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); | 233 | var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); |
159 | if (te == null) | 234 | if (te == null) |
160 | return; | 235 | return; |
@@ -324,26 +399,7 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
324 | } | 399 | } |
325 | else | 400 | else |
326 | { | 401 | { |
327 | // Material UUID = hash of the material's data. | 402 | id = StoreMaterialAsAsset(agentID, mat, sop); |
328 | // This makes materials deduplicate across the entire grid (but isn't otherwise required). | ||
329 | byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat)); | ||
330 | using (var md5 = MD5.Create()) | ||
331 | id = new UUID(md5.ComputeHash(data), 0); | ||
332 | |||
333 | lock (m_regionMaterials) | ||
334 | { | ||
335 | if (!m_regionMaterials.ContainsKey(id)) | ||
336 | { | ||
337 | m_regionMaterials[id] = mat; | ||
338 | |||
339 | // This asset might exist already, but it's ok to try to store it again | ||
340 | string name = "Material " + ChooseMaterialName(mat, sop); | ||
341 | name = name.Substring(0, Math.Min(64, name.Length)).Trim(); | ||
342 | AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString()); | ||
343 | asset.Data = data; | ||
344 | m_scene.AssetService.Store(asset); | ||
345 | } | ||
346 | } | ||
347 | } | 403 | } |
348 | 404 | ||
349 | 405 | ||
@@ -404,6 +460,32 @@ namespace OpenSim.Region.OptionalModules.Materials | |||
404 | return response; | 460 | return response; |
405 | } | 461 | } |
406 | 462 | ||
463 | private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop) | ||
464 | { | ||
465 | UUID id; | ||
466 | // Material UUID = hash of the material's data. | ||
467 | // This makes materials deduplicate across the entire grid (but isn't otherwise required). | ||
468 | byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat)); | ||
469 | using (var md5 = MD5.Create()) | ||
470 | id = new UUID(md5.ComputeHash(data), 0); | ||
471 | |||
472 | lock (m_regionMaterials) | ||
473 | { | ||
474 | if (!m_regionMaterials.ContainsKey(id)) | ||
475 | { | ||
476 | m_regionMaterials[id] = mat; | ||
477 | |||
478 | // This asset might exist already, but it's ok to try to store it again | ||
479 | string name = "Material " + ChooseMaterialName(mat, sop); | ||
480 | name = name.Substring(0, Math.Min(64, name.Length)).Trim(); | ||
481 | AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString()); | ||
482 | asset.Data = data; | ||
483 | m_scene.AssetService.Store(asset); | ||
484 | } | ||
485 | } | ||
486 | return id; | ||
487 | } | ||
488 | |||
407 | /// <summary> | 489 | /// <summary> |
408 | /// Use heuristics to choose a good name for the material. | 490 | /// Use heuristics to choose a good name for the material. |
409 | /// </summary> | 491 | /// </summary> |