opensim – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | eva | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ |
||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * * Redistributions of source code must retain the above copyright |
||
8 | * notice, this list of conditions and the following disclaimer. |
||
9 | * * Redistributions in binary form must reproduce the above copyright |
||
10 | * notice, this list of conditions and the following disclaimer in the |
||
11 | * documentation and/or other materials provided with the distribution. |
||
12 | * * Neither the name of the OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections.Generic; |
||
30 | using System.IO; |
||
31 | using System.Reflection; |
||
32 | using System.Text.RegularExpressions; |
||
33 | using System.Threading; |
||
34 | using log4net; |
||
35 | using OpenMetaverse; |
||
36 | using OpenMetaverse.Assets; |
||
37 | using OpenMetaverse.StructuredData; |
||
38 | using OpenSim.Framework; |
||
39 | using OpenSim.Region.Framework.Scenes.Serialization; |
||
40 | using OpenSim.Services.Interfaces; |
||
41 | using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType; |
||
42 | |||
43 | namespace OpenSim.Region.Framework.Scenes |
||
44 | { |
||
45 | /// <summary> |
||
46 | /// Gather uuids for a given entity. |
||
47 | /// </summary> |
||
48 | /// <remarks> |
||
49 | /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts |
||
50 | /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets |
||
51 | /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be |
||
52 | /// retrieved to work out which assets it references). |
||
53 | /// </remarks> |
||
54 | public class UuidGatherer |
||
55 | { |
||
56 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
57 | |||
58 | protected IAssetService m_assetService; |
||
59 | |||
60 | // /// <summary> |
||
61 | // /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate |
||
62 | // /// asset was found by the asset service. |
||
63 | // /// </summary> |
||
64 | // private AssetBase m_requestedObjectAsset; |
||
65 | // |
||
66 | // /// <summary> |
||
67 | // /// Signal whether we are currently waiting for the asset service to deliver an asset. |
||
68 | // /// </summary> |
||
69 | // private bool m_waitingForObjectAsset; |
||
70 | |||
71 | public UuidGatherer(IAssetService assetService) |
||
72 | { |
||
73 | m_assetService = assetService; |
||
74 | } |
||
75 | |||
76 | /// <summary> |
||
77 | /// Gather all the asset uuids associated with the asset referenced by a given uuid |
||
78 | /// </summary> |
||
79 | /// <remarks> |
||
80 | /// This includes both those directly associated with |
||
81 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained |
||
82 | /// within this object). |
||
83 | /// </remarks> |
||
84 | /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> |
||
85 | /// <param name="assetType">The type of the asset for the uuid given</param> |
||
86 | /// <param name="assetUuids">The assets gathered</param> |
||
87 | public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids) |
||
88 | { |
||
89 | // avoid infinite loops |
||
90 | if (assetUuids.ContainsKey(assetUuid)) |
||
91 | return; |
||
92 | |||
93 | try |
||
94 | { |
||
95 | assetUuids[assetUuid] = assetType; |
||
96 | |||
97 | if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) |
||
98 | { |
||
99 | GetWearableAssetUuids(assetUuid, assetUuids); |
||
100 | } |
||
101 | else if ((sbyte)AssetType.Gesture == assetType) |
||
102 | { |
||
103 | GetGestureAssetUuids(assetUuid, assetUuids); |
||
104 | } |
||
105 | else if ((sbyte)AssetType.Notecard == assetType) |
||
106 | { |
||
107 | GetTextEmbeddedAssetUuids(assetUuid, assetUuids); |
||
108 | } |
||
109 | else if ((sbyte)AssetType.LSLText == assetType) |
||
110 | { |
||
111 | GetTextEmbeddedAssetUuids(assetUuid, assetUuids); |
||
112 | } |
||
113 | else if ((sbyte)OpenSimAssetType.Material == assetType) |
||
114 | { |
||
115 | GetMaterialAssetUuids(assetUuid, assetUuids); |
||
116 | } |
||
117 | else if ((sbyte)AssetType.Object == assetType) |
||
118 | { |
||
119 | GetSceneObjectAssetUuids(assetUuid, assetUuids); |
||
120 | } |
||
121 | } |
||
122 | catch (Exception) |
||
123 | { |
||
124 | m_log.ErrorFormat( |
||
125 | "[UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}", |
||
126 | assetUuid, assetType); |
||
127 | throw; |
||
128 | } |
||
129 | } |
||
130 | |||
131 | /// <summary> |
||
132 | /// Gather all the asset uuids associated with a given object. |
||
133 | /// </summary> |
||
134 | /// <remarks> |
||
135 | /// This includes both those directly associated with |
||
136 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained |
||
137 | /// within this object). |
||
138 | /// </remarks> |
||
139 | /// <param name="sceneObject">The scene object for which to gather assets</param> |
||
140 | /// <param name="assetUuids"> |
||
141 | /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. |
||
142 | /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. |
||
143 | /// </param> |
||
144 | public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids) |
||
145 | { |
||
146 | // m_log.DebugFormat( |
||
147 | // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); |
||
148 | |||
149 | SceneObjectPart[] parts = sceneObject.Parts; |
||
150 | for (int i = 0; i < parts.Length; i++) |
||
151 | { |
||
152 | SceneObjectPart part = parts[i]; |
||
153 | |||
154 | // m_log.DebugFormat( |
||
155 | // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); |
||
156 | |||
157 | try |
||
158 | { |
||
159 | Primitive.TextureEntry textureEntry = part.Shape.Textures; |
||
160 | if (textureEntry != null) |
||
161 | { |
||
162 | // Get the prim's default texture. This will be used for faces which don't have their own texture |
||
163 | if (textureEntry.DefaultTexture != null) |
||
164 | GatherTextureEntryAssets(textureEntry.DefaultTexture, assetUuids); |
||
165 | |||
166 | if (textureEntry.FaceTextures != null) |
||
167 | { |
||
168 | // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture) |
||
169 | foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) |
||
170 | { |
||
171 | if (texture != null) |
||
172 | GatherTextureEntryAssets(texture, assetUuids); |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | |||
177 | // If the prim is a sculpt then preserve this information too |
||
178 | if (part.Shape.SculptTexture != UUID.Zero) |
||
179 | assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; |
||
180 | |||
181 | if (part.Shape.ProjectionTextureUUID != UUID.Zero) |
||
182 | assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; |
||
183 | |||
184 | if (part.CollisionSound != UUID.Zero) |
||
185 | assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound; |
||
186 | |||
187 | if (part.ParticleSystem.Length > 0) |
||
188 | { |
||
189 | try |
||
190 | { |
||
191 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); |
||
192 | if (ps.Texture != UUID.Zero) |
||
193 | assetUuids[ps.Texture] = (sbyte)AssetType.Texture; |
||
194 | } |
||
195 | catch (Exception e) |
||
196 | { |
||
197 | m_log.WarnFormat( |
||
198 | "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", |
||
199 | part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); |
||
200 | } |
||
201 | } |
||
202 | |||
203 | TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); |
||
204 | |||
205 | // Now analyze this prim's inventory items to preserve all the uuids that they reference |
||
206 | foreach (TaskInventoryItem tii in taskDictionary.Values) |
||
207 | { |
||
208 | // m_log.DebugFormat( |
||
209 | // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", |
||
210 | // tii.Name, tii.Type, part.Name, part.UUID); |
||
211 | |||
212 | if (!assetUuids.ContainsKey(tii.AssetID)) |
||
213 | GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids); |
||
214 | } |
||
215 | |||
216 | // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed |
||
217 | // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and |
||
218 | // inventory transfer. There needs to be a way for a module to register a method without assuming a |
||
219 | // Scene.EventManager is present. |
||
220 | // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); |
||
221 | |||
222 | |||
223 | // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs |
||
224 | GatherMaterialsUuids(part, assetUuids); |
||
225 | } |
||
226 | catch (Exception e) |
||
227 | { |
||
228 | m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); |
||
229 | m_log.DebugFormat( |
||
230 | "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)", |
||
231 | part.Shape.TextureEntry.Length); |
||
232 | } |
||
233 | } |
||
234 | } |
||
235 | |||
236 | /// <summary> |
||
237 | /// Gather all the asset uuids found in one face of a Texture Entry. |
||
238 | /// </summary> |
||
239 | private void GatherTextureEntryAssets(Primitive.TextureEntryFace texture, IDictionary<UUID, sbyte> assetUuids) |
||
240 | { |
||
241 | assetUuids[texture.TextureID] = (sbyte)AssetType.Texture; |
||
242 | |||
243 | if (texture.MaterialID != UUID.Zero) |
||
244 | { |
||
245 | GatherAssetUuids(texture.MaterialID, (sbyte)OpenSimAssetType.Material, assetUuids); |
||
246 | } |
||
247 | } |
||
248 | |||
249 | // /// <summary> |
||
250 | // /// The callback made when we request the asset for an object from the asset service. |
||
251 | // /// </summary> |
||
252 | // private void AssetReceived(string id, Object sender, AssetBase asset) |
||
253 | // { |
||
254 | // lock (this) |
||
255 | // { |
||
256 | // m_requestedObjectAsset = asset; |
||
257 | // m_waitingForObjectAsset = false; |
||
258 | // Monitor.Pulse(this); |
||
259 | // } |
||
260 | // } |
||
261 | |||
262 | /// <summary> |
||
263 | /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps |
||
264 | /// stored in legacy format in part.DynAttrs |
||
265 | /// </summary> |
||
266 | /// <param name="part"></param> |
||
267 | /// <param name="assetUuids"></param> |
||
268 | //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids) |
||
269 | public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids) |
||
270 | { |
||
271 | // scan thru the dynAttrs map of this part for any textures used as materials |
||
272 | OSD osdMaterials = null; |
||
273 | |||
274 | lock (part.DynAttrs) |
||
275 | { |
||
276 | if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) |
||
277 | { |
||
278 | OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); |
||
279 | |||
280 | if (materialsStore == null) |
||
281 | return; |
||
282 | |||
283 | materialsStore.TryGetValue("Materials", out osdMaterials); |
||
284 | } |
||
285 | |||
286 | if (osdMaterials != null) |
||
287 | { |
||
288 | //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd)); |
||
289 | |||
290 | if (osdMaterials is OSDArray) |
||
291 | { |
||
292 | OSDArray matsArr = osdMaterials as OSDArray; |
||
293 | foreach (OSDMap matMap in matsArr) |
||
294 | { |
||
295 | try |
||
296 | { |
||
297 | if (matMap.ContainsKey("Material")) |
||
298 | { |
||
299 | OSDMap mat = matMap["Material"] as OSDMap; |
||
300 | if (mat.ContainsKey("NormMap")) |
||
301 | { |
||
302 | UUID normalMapId = mat["NormMap"].AsUUID(); |
||
303 | if (normalMapId != UUID.Zero) |
||
304 | { |
||
305 | assetUuids[normalMapId] = (sbyte)AssetType.Texture; |
||
306 | //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString()); |
||
307 | } |
||
308 | } |
||
309 | if (mat.ContainsKey("SpecMap")) |
||
310 | { |
||
311 | UUID specularMapId = mat["SpecMap"].AsUUID(); |
||
312 | if (specularMapId != UUID.Zero) |
||
313 | { |
||
314 | assetUuids[specularMapId] = (sbyte)AssetType.Texture; |
||
315 | //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString()); |
||
316 | } |
||
317 | } |
||
318 | } |
||
319 | |||
320 | } |
||
321 | catch (Exception e) |
||
322 | { |
||
323 | m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message); |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | } |
||
328 | } |
||
329 | } |
||
330 | |||
331 | /// <summary> |
||
332 | /// Get an asset synchronously, potentially using an asynchronous callback. If the |
||
333 | /// asynchronous callback is used, we will wait for it to complete. |
||
334 | /// </summary> |
||
335 | /// <param name="uuid"></param> |
||
336 | /// <returns></returns> |
||
337 | protected virtual AssetBase GetAsset(UUID uuid) |
||
338 | { |
||
339 | return m_assetService.Get(uuid.ToString()); |
||
340 | |||
341 | // XXX: Switching to do this synchronously where the call was async before but we always waited for it |
||
342 | // to complete anyway! |
||
343 | // m_waitingForObjectAsset = true; |
||
344 | // m_assetCache.Get(uuid.ToString(), this, AssetReceived); |
||
345 | // |
||
346 | // // The asset cache callback can either |
||
347 | // // |
||
348 | // // 1. Complete on the same thread (if the asset is already in the cache) or |
||
349 | // // 2. Come in via a different thread (if we need to go fetch it). |
||
350 | // // |
||
351 | // // The code below handles both these alternatives. |
||
352 | // lock (this) |
||
353 | // { |
||
354 | // if (m_waitingForObjectAsset) |
||
355 | // { |
||
356 | // Monitor.Wait(this); |
||
357 | // m_waitingForObjectAsset = false; |
||
358 | // } |
||
359 | // } |
||
360 | // |
||
361 | // return m_requestedObjectAsset; |
||
362 | } |
||
363 | |||
364 | /// <summary> |
||
365 | /// Record the asset uuids embedded within the given script. |
||
366 | /// </summary> |
||
367 | /// <param name="scriptUuid"></param> |
||
368 | /// <param name="assetUuids">Dictionary in which to record the references</param> |
||
369 | private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids) |
||
370 | { |
||
371 | // m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); |
||
372 | |||
373 | AssetBase embeddingAsset = GetAsset(embeddingAssetId); |
||
374 | |||
375 | if (null != embeddingAsset) |
||
376 | { |
||
377 | string script = Utils.BytesToString(embeddingAsset.Data); |
||
378 | // m_log.DebugFormat("[ARCHIVER]: Script {0}", script); |
||
379 | MatchCollection uuidMatches = Util.PermissiveUUIDPattern.Matches(script); |
||
380 | // m_log.DebugFormat("[ARCHIVER]: Found {0} matches in text", uuidMatches.Count); |
||
381 | |||
382 | foreach (Match uuidMatch in uuidMatches) |
||
383 | { |
||
384 | UUID uuid = new UUID(uuidMatch.Value); |
||
385 | // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); |
||
386 | |||
387 | // Embedded asset references (if not false positives) could be for many types of asset, so we will |
||
388 | // label these as unknown. |
||
389 | assetUuids[uuid] = (sbyte)AssetType.Unknown; |
||
390 | } |
||
391 | } |
||
392 | } |
||
393 | |||
394 | /// <summary> |
||
395 | /// Record the uuids referenced by the given wearable asset |
||
396 | /// </summary> |
||
397 | /// <param name="wearableAssetUuid"></param> |
||
398 | /// <param name="assetUuids">Dictionary in which to record the references</param> |
||
399 | private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids) |
||
400 | { |
||
401 | AssetBase assetBase = GetAsset(wearableAssetUuid); |
||
402 | |||
403 | if (null != assetBase) |
||
404 | { |
||
405 | //m_log.Debug(new System.Text.ASCIIEncoding().GetString(bodypartAsset.Data)); |
||
406 | AssetWearable wearableAsset = new AssetBodypart(wearableAssetUuid, assetBase.Data); |
||
407 | wearableAsset.Decode(); |
||
408 | |||
409 | //m_log.DebugFormat( |
||
410 | // "[ARCHIVER]: Wearable asset {0} references {1} assets", wearableAssetUuid, wearableAsset.Textures.Count); |
||
411 | |||
412 | foreach (UUID uuid in wearableAsset.Textures.Values) |
||
413 | { |
||
414 | assetUuids[uuid] = (sbyte)AssetType.Texture; |
||
415 | } |
||
416 | } |
||
417 | } |
||
418 | |||
419 | /// <summary> |
||
420 | /// Get all the asset uuids associated with a given object. This includes both those directly associated with |
||
421 | /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained |
||
422 | /// within this object). |
||
423 | /// </summary> |
||
424 | /// <param name="sceneObject"></param> |
||
425 | /// <param name="assetUuids"></param> |
||
426 | private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids) |
||
427 | { |
||
428 | AssetBase objectAsset = GetAsset(sceneObjectUuid); |
||
429 | |||
430 | if (null != objectAsset) |
||
431 | { |
||
432 | string xml = Utils.BytesToString(objectAsset.Data); |
||
433 | |||
434 | CoalescedSceneObjects coa; |
||
435 | if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) |
||
436 | { |
||
437 | foreach (SceneObjectGroup sog in coa.Objects) |
||
438 | GatherAssetUuids(sog, assetUuids); |
||
439 | } |
||
440 | else |
||
441 | { |
||
442 | SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); |
||
443 | |||
444 | if (null != sog) |
||
445 | GatherAssetUuids(sog, assetUuids); |
||
446 | } |
||
447 | } |
||
448 | } |
||
449 | |||
450 | /// <summary> |
||
451 | /// Get the asset uuid associated with a gesture |
||
452 | /// </summary> |
||
453 | /// <param name="gestureUuid"></param> |
||
454 | /// <param name="assetUuids"></param> |
||
455 | private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids) |
||
456 | { |
||
457 | AssetBase assetBase = GetAsset(gestureUuid); |
||
458 | if (null == assetBase) |
||
459 | return; |
||
460 | |||
461 | MemoryStream ms = new MemoryStream(assetBase.Data); |
||
462 | StreamReader sr = new StreamReader(ms); |
||
463 | |||
464 | sr.ReadLine(); // Unknown (Version?) |
||
465 | sr.ReadLine(); // Unknown |
||
466 | sr.ReadLine(); // Unknown |
||
467 | sr.ReadLine(); // Name |
||
468 | sr.ReadLine(); // Comment ? |
||
469 | int count = Convert.ToInt32(sr.ReadLine()); // Item count |
||
470 | |||
471 | for (int i = 0 ; i < count ; i++) |
||
472 | { |
||
473 | string type = sr.ReadLine(); |
||
474 | if (type == null) |
||
475 | break; |
||
476 | string name = sr.ReadLine(); |
||
477 | if (name == null) |
||
478 | break; |
||
479 | string id = sr.ReadLine(); |
||
480 | if (id == null) |
||
481 | break; |
||
482 | string unknown = sr.ReadLine(); |
||
483 | if (unknown == null) |
||
484 | break; |
||
485 | |||
486 | // If it can be parsed as a UUID, it is an asset ID |
||
487 | UUID uuid; |
||
488 | if (UUID.TryParse(id, out uuid)) |
||
489 | assetUuids[uuid] = (sbyte)AssetType.Animation; |
||
490 | } |
||
491 | } |
||
492 | |||
493 | /// <summary> |
||
494 | /// Get the asset uuid's referenced in a material. |
||
495 | /// </summary> |
||
496 | private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids) |
||
497 | { |
||
498 | AssetBase assetBase = GetAsset(materialUuid); |
||
499 | if (null == assetBase) |
||
500 | return; |
||
501 | |||
502 | OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data); |
||
503 | |||
504 | UUID normMap = mat["NormMap"].AsUUID(); |
||
505 | if (normMap != UUID.Zero) |
||
506 | assetUuids[normMap] = (sbyte)AssetType.Texture; |
||
507 | |||
508 | UUID specMap = mat["SpecMap"].AsUUID(); |
||
509 | if (specMap != UUID.Zero) |
||
510 | assetUuids[specMap] = (sbyte)AssetType.Texture; |
||
511 | } |
||
512 | } |
||
513 | |||
514 | public class HGUuidGatherer : UuidGatherer |
||
515 | { |
||
516 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
517 | |||
518 | protected string m_assetServerURL; |
||
519 | |||
520 | public HGUuidGatherer(IAssetService assetService, string assetServerURL) |
||
521 | : base(assetService) |
||
522 | { |
||
523 | m_assetServerURL = assetServerURL; |
||
524 | if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) |
||
525 | m_assetServerURL = m_assetServerURL + "/"; |
||
526 | } |
||
527 | |||
528 | protected override AssetBase GetAsset(UUID uuid) |
||
529 | { |
||
530 | if (string.Empty == m_assetServerURL) |
||
531 | return base.GetAsset(uuid); |
||
532 | else |
||
533 | return FetchAsset(uuid); |
||
534 | } |
||
535 | |||
536 | public AssetBase FetchAsset(UUID assetID) |
||
537 | { |
||
538 | |||
539 | // Test if it's already here |
||
540 | AssetBase asset = m_assetService.Get(assetID.ToString()); |
||
541 | if (asset == null) |
||
542 | { |
||
543 | // It's not, so fetch it from abroad |
||
544 | asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); |
||
545 | if (asset != null) |
||
546 | m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); |
||
547 | else |
||
548 | m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); |
||
549 | } |
||
550 | //else |
||
551 | // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); |
||
552 | |||
553 | return asset; |
||
554 | } |
||
555 | } |
||
556 | } |