aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOren Hurvitz2013-12-06 16:21:11 +0200
committerdahlia2014-01-20 00:38:42 -0800
commit3018b2c5d7c9de0e8da6d158f0848c840b7864ab (patch)
treef06f5b35360de9010e618b2cf7c6c109c0527631
parentRenamed MaterialsDemoModule to MaterialsModule (diff)
downloadopensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.zip
opensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.tar.gz
opensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.tar.bz2
opensim-SC_OLD-3018b2c5d7c9de0e8da6d158f0848c840b7864ab.tar.xz
Materials module: a) Store materials as assets; b) Finalized it (removed the "Demo" label; removed most of the logging); c) Enabled by default
Changed UuidGatherer to use 'sbyte' to identify assets instead of 'AssetType'. This lets UuidGatherer handle Materials, which are defined in a different enum from 'AssetType'.
-rw-r--r--OpenSim/Framework/SLUtil.cs40
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs3
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs138
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs518
-rw-r--r--bin/OpenSim.ini.example6
12 files changed, 307 insertions, 453 deletions
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index cb73e8f..9249105 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -39,8 +39,32 @@ namespace OpenSim.Framework
39 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
42 /// <summary>
43 /// Asset types used only in OpenSim.
44 /// To avoid clashing with the code numbers used in Second Life, use only negative numbers here.
45 /// </summary>
46 public enum OpenSimAssetType : sbyte
47 {
48 Material = -2
49 }
50
51
42 #region SL / file extension / content-type conversions 52 #region SL / file extension / content-type conversions
43 53
54 /// <summary>
55 /// Returns the Enum entry corresponding to the given code, regardless of whether it belongs
56 /// to the AssetType or OpenSimAssetType enums.
57 /// </summary>
58 public static object AssetTypeFromCode(sbyte assetType)
59 {
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else if (Enum.IsDefined(typeof(OpenSimAssetType), assetType))
63 return (OpenSimAssetType)assetType;
64 else
65 return OpenMetaverse.AssetType.Unknown;
66 }
67
44 private class TypeMapping 68 private class TypeMapping
45 { 69 {
46 private sbyte assetType; 70 private sbyte assetType;
@@ -56,12 +80,7 @@ namespace OpenSim.Framework
56 80
57 public object AssetType 81 public object AssetType
58 { 82 {
59 get { 83 get { return AssetTypeFromCode(assetType); }
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else
63 return OpenMetaverse.AssetType.Unknown;
64 }
65 } 84 }
66 85
67 public InventoryType InventoryType 86 public InventoryType InventoryType
@@ -102,6 +121,11 @@ namespace OpenSim.Framework
102 : this((sbyte)assetType, inventoryType, contentType, null, extension) 121 : this((sbyte)assetType, inventoryType, contentType, null, extension)
103 { 122 {
104 } 123 }
124
125 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
126 : this((sbyte)assetType, inventoryType, contentType, null, extension)
127 {
128 }
105 } 129 }
106 130
107 /// <summary> 131 /// <summary>
@@ -142,7 +166,9 @@ namespace OpenSim.Framework
142 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"), 166 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
143 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"), 167 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
144 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"), 168 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
145 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm") 169 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
170
171 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
146 }; 172 };
147 173
148 private static Dictionary<sbyte, string> asset2Content; 174 private static Dictionary<sbyte, string> asset2Content;
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 0c12787..73ebfae 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
32 33
33namespace OpenSim.Framework.Serialization 34namespace OpenSim.Framework.Serialization
34{ 35{
@@ -128,6 +129,7 @@ namespace OpenSim.Framework.Serialization
128 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; 129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2";
129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; 130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga";
130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this 131 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this
132 ASSET_TYPE_TO_EXTENSION[(sbyte)OpenSimAssetType.Material] = ASSET_EXTENSION_SEPARATOR + "material.xml"; // Not sure if we'll ever see this
131 133
132 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; 134 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation;
133 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart; 135 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart;
@@ -152,6 +154,7 @@ namespace OpenSim.Framework.Serialization
152 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; 154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture;
153 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; 155 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA;
154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; 156 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
157 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "material.xml"] = (sbyte)OpenSimAssetType.Material;
155 } 158 }
156 159
157 public static string CreateOarLandDataPath(LandData ld) 160 public static string CreateOarLandDataPath(LandData ld)
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 6a5f8f3..b270de9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -771,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Asset
771 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 771 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
772 772
773 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 773 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
774 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 774 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
775 775
776 foreach (Scene s in m_Scenes) 776 foreach (Scene s in m_Scenes)
777 { 777 {
@@ -794,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Asset
794 else if (storeUncached) 794 else if (storeUncached)
795 { 795 {
796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
797 if (cachedAsset == null && assets[assetID] != AssetType.Unknown) 797 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
798 m_log.DebugFormat( 798 m_log.DebugFormat(
799 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", 799 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); 800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 4ec8ae7..4292719 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 /// <value> 78 /// <value>
79 /// Used to collect the uuids of the assets that we need to save into the archive 79 /// Used to collect the uuids of the assets that we need to save into the archive
80 /// </value> 80 /// </value>
81 protected Dictionary<UUID, AssetType> m_assetUuids = new Dictionary<UUID, AssetType>(); 81 protected Dictionary<UUID, sbyte> m_assetUuids = new Dictionary<UUID, sbyte>();
82 82
83 /// <value> 83 /// <value>
84 /// Used to collect the uuids of the users that we need to save into the archive 84 /// Used to collect the uuids of the users that we need to save into the archive
@@ -187,7 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
187 187
188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset 188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) 189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); 190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (sbyte)inventoryItem.AssetType, m_assetUuids);
191 } 191 }
192 192
193 /// <summary> 193 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 04a0db6..09b1975 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -182,11 +182,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
182 { 182 {
183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); 184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
185 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 185 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url); 186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
187 uuidGatherer.GatherAssetUuids(so, ids); 187 uuidGatherer.GatherAssetUuids(so, ids);
188 188
189 foreach (KeyValuePair<UUID, AssetType> kvp in ids) 189 foreach (KeyValuePair<UUID, sbyte> kvp in ids)
190 uuidGatherer.FetchAsset(kvp.Key); 190 uuidGatherer.FetchAsset(kvp.Key);
191 } 191 }
192 } 192 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index b7a4d1a..d4fb1ba 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -260,9 +260,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
260 260
261 // The act of gathering UUIDs downloads some assets from the remote server 261 // The act of gathering UUIDs downloads some assets from the remote server
262 // but not all... 262 // but not all...
263 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 263 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); 264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
265 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); 265 uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
266 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); 266 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
267 bool success = true; 267 bool success = true;
268 foreach (UUID uuid in ids.Keys) 268 foreach (UUID uuid in ids.Keys)
@@ -286,9 +286,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
287 if (asset != null) 287 if (asset != null)
288 { 288 {
289 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 289 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
291 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 291 uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
292 bool success = false; 292 bool success = false;
293 foreach (UUID uuid in ids.Keys) 293 foreach (UUID uuid in ids.Keys)
294 { 294 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index a990898..7a844f4 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
178 178
179 // Archive the regions 179 // Archive the regions
180 180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); 181 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
182 182
183 scenesGroup.ForEachScene(delegate(Scene scene) 183 scenesGroup.ForEachScene(delegate(Scene scene)
184 { 184 {
@@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 216 }
217 } 217 }
218 218
219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids)
220 { 220 {
221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
222 222
@@ -276,16 +276,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings; 276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
277 277
278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) 278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
279 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; 279 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
280 280
281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) 281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
282 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; 282 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
283 283
284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) 284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
285 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; 285 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
286 286
287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) 287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
288 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; 288 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
289 289
290 Save(scene, sceneObjects, regionDir); 290 Save(scene, sceneObjects, regionDir);
291 } 291 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 9600023..2d0da61 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
81 /// <value> 81 /// <value>
82 /// uuids to request 82 /// uuids to request
83 /// </value> 83 /// </value>
84 protected IDictionary<UUID, AssetType> m_uuids; 84 protected IDictionary<UUID, sbyte> m_uuids;
85 85
86 /// <value> 86 /// <value>
87 /// Callback used when all the assets requested have been received. 87 /// Callback used when all the assets requested have been received.
@@ -115,7 +115,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
115 protected Dictionary<string, object> m_options; 115 protected Dictionary<string, object> m_options;
116 116
117 protected internal AssetsRequest( 117 protected internal AssetsRequest(
118 AssetsArchiver assetsArchiver, IDictionary<UUID, AssetType> uuids, 118 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
119 IAssetService assetService, IUserAccountService userService, 119 IAssetService assetService, IUserAccountService userService,
120 UUID scope, Dictionary<string, object> options, 120 UUID scope, Dictionary<string, object> options,
121 AssetsRequestCallback assetsRequestCallback) 121 AssetsRequestCallback assetsRequestCallback)
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
154 154
155 m_requestCallbackTimer.Enabled = true; 155 m_requestCallbackTimer.Enabled = true;
156 156
157 foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) 157 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
158 { 158 {
159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
160 160
@@ -235,9 +235,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer 235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) 236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
237 { 237 {
238 AssetType type = (AssetType)assetType; 238 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, type); 239 fetchedAsset.Type = (sbyte)assetType;
240 fetchedAsset.Type = (sbyte)type;
241 } 240 }
242 241
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 242 AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 3e074b9..42a1977 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -38,6 +38,7 @@ using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
41 42
42namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
43{ 44{
@@ -83,7 +84,7 @@ namespace OpenSim.Region.Framework.Scenes
83 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
84 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
85 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
86 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
87 { 88 {
88 // avoid infinite loops 89 // avoid infinite loops
89 if (assetUuids.ContainsKey(assetUuid)) 90 if (assetUuids.ContainsKey(assetUuid))
@@ -93,23 +94,27 @@ namespace OpenSim.Region.Framework.Scenes
93 { 94 {
94 assetUuids[assetUuid] = assetType; 95 assetUuids[assetUuid] = assetType;
95 96
96 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 97 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
97 { 98 {
98 GetWearableAssetUuids(assetUuid, assetUuids); 99 GetWearableAssetUuids(assetUuid, assetUuids);
99 } 100 }
100 else if (AssetType.Gesture == assetType) 101 else if ((sbyte)AssetType.Gesture == assetType)
101 { 102 {
102 GetGestureAssetUuids(assetUuid, assetUuids); 103 GetGestureAssetUuids(assetUuid, assetUuids);
103 } 104 }
104 else if (AssetType.Notecard == assetType) 105 else if ((sbyte)AssetType.Notecard == assetType)
105 { 106 {
106 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
107 } 108 }
108 else if (AssetType.LSLText == assetType) 109 else if ((sbyte)AssetType.LSLText == assetType)
109 { 110 {
110 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 111 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
111 } 112 }
112 else if (AssetType.Object == assetType) 113 else if ((sbyte)OpenSimAssetType.Material == assetType)
114 {
115 GetMaterialAssetUuids(assetUuid, assetUuids);
116 }
117 else if ((sbyte)AssetType.Object == assetType)
113 { 118 {
114 GetSceneObjectAssetUuids(assetUuid, assetUuids); 119 GetSceneObjectAssetUuids(assetUuid, assetUuids);
115 } 120 }
@@ -136,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes
136 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 141 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
137 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. 142 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
138 /// </param> 143 /// </param>
139 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 144 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
140 { 145 {
141// m_log.DebugFormat( 146// m_log.DebugFormat(
142// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 147// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -156,7 +161,7 @@ namespace OpenSim.Region.Framework.Scenes
156 { 161 {
157 // Get the prim's default texture. This will be used for faces which don't have their own texture 162 // Get the prim's default texture. This will be used for faces which don't have their own texture
158 if (textureEntry.DefaultTexture != null) 163 if (textureEntry.DefaultTexture != null)
159 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 164 assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
160 165
161 if (textureEntry.FaceTextures != null) 166 if (textureEntry.FaceTextures != null)
162 { 167 {
@@ -164,20 +169,20 @@ namespace OpenSim.Region.Framework.Scenes
164 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 169 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
165 { 170 {
166 if (texture != null) 171 if (texture != null)
167 assetUuids[texture.TextureID] = AssetType.Texture; 172 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
168 } 173 }
169 } 174 }
170 } 175 }
171 176
172 // If the prim is a sculpt then preserve this information too 177 // If the prim is a sculpt then preserve this information too
173 if (part.Shape.SculptTexture != UUID.Zero) 178 if (part.Shape.SculptTexture != UUID.Zero)
174 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 179 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
175 180
176 if (part.Shape.ProjectionTextureUUID != UUID.Zero) 181 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
177 assetUuids[part.Shape.ProjectionTextureUUID] = AssetType.Texture; 182 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
178 183
179 if (part.CollisionSound != UUID.Zero) 184 if (part.CollisionSound != UUID.Zero)
180 assetUuids[part.CollisionSound] = AssetType.Sound; 185 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
181 186
182 if (part.ParticleSystem.Length > 0) 187 if (part.ParticleSystem.Length > 0)
183 { 188 {
@@ -185,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes
185 { 190 {
186 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); 191 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
187 if (ps.Texture != UUID.Zero) 192 if (ps.Texture != UUID.Zero)
188 assetUuids[ps.Texture] = AssetType.Texture; 193 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
189 } 194 }
190 catch (Exception e) 195 catch (Exception e)
191 { 196 {
@@ -205,7 +210,7 @@ namespace OpenSim.Region.Framework.Scenes
205// tii.Name, tii.Type, part.Name, part.UUID); 210// tii.Name, tii.Type, part.Name, part.UUID);
206 211
207 if (!assetUuids.ContainsKey(tii.AssetID)) 212 if (!assetUuids.ContainsKey(tii.AssetID))
208 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 213 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
209 } 214 }
210 215
211 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed 216 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
@@ -213,8 +218,6 @@ namespace OpenSim.Region.Framework.Scenes
213 // inventory transfer. There needs to be a way for a module to register a method without assuming a 218 // inventory transfer. There needs to be a way for a module to register a method without assuming a
214 // Scene.EventManager is present. 219 // Scene.EventManager is present.
215// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); 220// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
216
217 GatherMaterialsUuids(part, assetUuids);
218 } 221 }
219 catch (Exception e) 222 catch (Exception e)
220 { 223 {
@@ -225,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
225 } 228 }
226 } 229 }
227 } 230 }
228 231
229// /// <summary> 232// /// <summary>
230// /// The callback made when we request the asset for an object from the asset service. 233// /// The callback made when we request the asset for an object from the asset service.
231// /// </summary> 234// /// </summary>
@@ -238,73 +241,6 @@ namespace OpenSim.Region.Framework.Scenes
238// Monitor.Pulse(this); 241// Monitor.Pulse(this);
239// } 242// }
240// } 243// }
241
242 /// <summary>
243 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
244 /// </summary>
245 /// <param name="part"></param>
246 /// <param name="assetUuids"></param>
247 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
248 {
249 // scan thru the dynAttrs map of this part for any textures used as materials
250 OSD osdMaterials = null;
251
252 lock (part.DynAttrs)
253 {
254 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
255 {
256 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
257
258 if (materialsStore == null)
259 return;
260
261 materialsStore.TryGetValue("Materials", out osdMaterials);
262 }
263
264 if (osdMaterials != null)
265 {
266 //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
267
268 if (osdMaterials is OSDArray)
269 {
270 OSDArray matsArr = osdMaterials as OSDArray;
271 foreach (OSDMap matMap in matsArr)
272 {
273 try
274 {
275 if (matMap.ContainsKey("Material"))
276 {
277 OSDMap mat = matMap["Material"] as OSDMap;
278 if (mat.ContainsKey("NormMap"))
279 {
280 UUID normalMapId = mat["NormMap"].AsUUID();
281 if (normalMapId != UUID.Zero)
282 {
283 assetUuids[normalMapId] = AssetType.Texture;
284 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
285 }
286 }
287 if (mat.ContainsKey("SpecMap"))
288 {
289 UUID specularMapId = mat["SpecMap"].AsUUID();
290 if (specularMapId != UUID.Zero)
291 {
292 assetUuids[specularMapId] = AssetType.Texture;
293 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
294 }
295 }
296 }
297
298 }
299 catch (Exception e)
300 {
301 m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message);
302 }
303 }
304 }
305 }
306 }
307 }
308 244
309 /// <summary> 245 /// <summary>
310 /// Get an asset synchronously, potentially using an asynchronous callback. If the 246 /// Get an asset synchronously, potentially using an asynchronous callback. If the
@@ -344,7 +280,7 @@ namespace OpenSim.Region.Framework.Scenes
344 /// </summary> 280 /// </summary>
345 /// <param name="scriptUuid"></param> 281 /// <param name="scriptUuid"></param>
346 /// <param name="assetUuids">Dictionary in which to record the references</param> 282 /// <param name="assetUuids">Dictionary in which to record the references</param>
347 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 283 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
348 { 284 {
349// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 285// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
350 286
@@ -364,7 +300,7 @@ namespace OpenSim.Region.Framework.Scenes
364 300
365 // Embedded asset references (if not false positives) could be for many types of asset, so we will 301 // Embedded asset references (if not false positives) could be for many types of asset, so we will
366 // label these as unknown. 302 // label these as unknown.
367 assetUuids[uuid] = AssetType.Unknown; 303 assetUuids[uuid] = (sbyte)AssetType.Unknown;
368 } 304 }
369 } 305 }
370 } 306 }
@@ -374,7 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
374 /// </summary> 310 /// </summary>
375 /// <param name="wearableAssetUuid"></param> 311 /// <param name="wearableAssetUuid"></param>
376 /// <param name="assetUuids">Dictionary in which to record the references</param> 312 /// <param name="assetUuids">Dictionary in which to record the references</param>
377 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 313 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
378 { 314 {
379 AssetBase assetBase = GetAsset(wearableAssetUuid); 315 AssetBase assetBase = GetAsset(wearableAssetUuid);
380 316
@@ -389,7 +325,7 @@ namespace OpenSim.Region.Framework.Scenes
389 325
390 foreach (UUID uuid in wearableAsset.Textures.Values) 326 foreach (UUID uuid in wearableAsset.Textures.Values)
391 { 327 {
392 assetUuids[uuid] = AssetType.Texture; 328 assetUuids[uuid] = (sbyte)AssetType.Texture;
393 } 329 }
394 } 330 }
395 } 331 }
@@ -401,7 +337,7 @@ namespace OpenSim.Region.Framework.Scenes
401 /// </summary> 337 /// </summary>
402 /// <param name="sceneObject"></param> 338 /// <param name="sceneObject"></param>
403 /// <param name="assetUuids"></param> 339 /// <param name="assetUuids"></param>
404 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 340 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
405 { 341 {
406 AssetBase objectAsset = GetAsset(sceneObjectUuid); 342 AssetBase objectAsset = GetAsset(sceneObjectUuid);
407 343
@@ -430,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes
430 /// </summary> 366 /// </summary>
431 /// <param name="gestureUuid"></param> 367 /// <param name="gestureUuid"></param>
432 /// <param name="assetUuids"></param> 368 /// <param name="assetUuids"></param>
433 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 369 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
434 { 370 {
435 AssetBase assetBase = GetAsset(gestureUuid); 371 AssetBase assetBase = GetAsset(gestureUuid);
436 if (null == assetBase) 372 if (null == assetBase)
@@ -464,9 +400,29 @@ namespace OpenSim.Region.Framework.Scenes
464 // If it can be parsed as a UUID, it is an asset ID 400 // If it can be parsed as a UUID, it is an asset ID
465 UUID uuid; 401 UUID uuid;
466 if (UUID.TryParse(id, out uuid)) 402 if (UUID.TryParse(id, out uuid))
467 assetUuids[uuid] = AssetType.Animation; 403 assetUuids[uuid] = (sbyte)AssetType.Animation;
468 } 404 }
469 } 405 }
406
407 /// <summary>
408 /// Get the asset uuid's referenced in a material.
409 /// </summary>
410 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
411 {
412 AssetBase assetBase = GetAsset(materialUuid);
413 if (null == assetBase)
414 return;
415
416 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
417
418 UUID normMap = mat["NormMap"].AsUUID();
419 if (normMap != UUID.Zero)
420 assetUuids[normMap] = (sbyte)AssetType.Texture;
421
422 UUID specMap = mat["SpecMap"].AsUUID();
423 if (specMap != UUID.Zero)
424 assetUuids[specMap] = (sbyte)AssetType.Texture;
425 }
470 } 426 }
471 427
472 public class HGUuidGatherer : UuidGatherer 428 public class HGUuidGatherer : UuidGatherer
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index e707154..09041e8 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -42,77 +42,49 @@ using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer; 42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
45using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
45 46
46using Ionic.Zlib; 47using Ionic.Zlib;
47 48
48// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already 49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
49// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans 50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
50// the available DLLs 51// the available DLLs
51//[assembly: Addin("MaterialsDemoModule", "1.0")] 52//[assembly: Addin("MaterialsModule", "1.0")]
52//[assembly: AddinDependency("OpenSim", "0.5")] 53//[assembly: AddinDependency("OpenSim", "0.5")]
53 54
54namespace OpenSim.Region.OptionalModules.MaterialsDemoModule 55namespace OpenSim.Region.OptionalModules.Materials
55{ 56{
56 /// <summary> 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
57 /// 58 public class MaterialsModule : INonSharedRegionModule
58 // # # ## ##### # # # # # ####
59 // # # # # # # ## # # ## # # #
60 // # # # # # # # # # # # # # #
61 // # ## # ###### ##### # # # # # # # # ###
62 // ## ## # # # # # ## # # ## # #
63 // # # # # # # # # # # # ####
64 //
65 // THIS MODULE IS FOR EXPERIMENTAL USE ONLY AND MAY CAUSE REGION OR ASSET CORRUPTION!
66 //
67 ////////////// WARNING //////////////////////////////////////////////////////////////////
68 /// This is an *Experimental* module for developing support for materials-capable viewers
69 /// This module should NOT be used in a production environment! It may cause data corruption and
70 /// viewer crashes. It should be only used to evaluate implementations of materials.
71 ///
72 /// Materials are persisted via SceneObjectPart.dynattrs. This is a relatively new feature
73 /// of OpenSimulator and is not field proven at the time this module was written. Persistence
74 /// may fail or become corrupt and this could cause viewer crashes due to erroneous materials
75 /// data being sent to viewers. Materials descriptions might survive IAR, OAR, or other means
76 /// of archiving however the texture resources used by these materials probably will not as they
77 /// may not be adequately referenced to ensure proper archiving.
78 ///
79 ///
80 ///
81 /// To enable this module, add this string at the bottom of OpenSim.ini:
82 /// [MaterialsDemoModule]
83 ///
84 /// </summary>
85 ///
86
87 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsDemoModule")]
88 public class MaterialsDemoModule : INonSharedRegionModule
89 { 59 {
90 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
91 61
92 public string Name { get { return "MaterialsDemoModule"; } } 62 public string Name { get { return "MaterialsModule"; } }
93 63
94 public Type ReplaceableInterface { get { return null; } } 64 public Type ReplaceableInterface { get { return null; } }
95 65
96 private Scene m_scene = null; 66 private Scene m_scene = null;
97 private bool m_enabled = false; 67 private bool m_enabled = false;
98 68
99 public Dictionary<UUID, OSDMap> m_knownMaterials = new Dictionary<UUID, OSDMap>(); 69 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
100 70
101 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
102 { 72 {
103 m_enabled = (source.Configs["MaterialsDemoModule"] != null); 73 IConfig config = source.Configs["Materials"];
74 if (config == null)
75 return;
76
77 m_enabled = config.GetBoolean("enable_materials", true);
104 if (!m_enabled) 78 if (!m_enabled)
105 return; 79 return;
106 80
107 m_log.DebugFormat("[MaterialsDemoModule]: Initialized"); 81 m_log.DebugFormat("[Materials]: Initialized");
108 } 82 }
109 83
110 public void Close() 84 public void Close()
111 { 85 {
112 if (!m_enabled) 86 if (!m_enabled)
113 return; 87 return;
114
115 //m_log.DebugFormat("[MaterialsDemoModule]: CLOSED MODULE");
116 } 88 }
117 89
118 public void AddRegion(Scene scene) 90 public void AddRegion(Scene scene)
@@ -120,22 +92,19 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
120 if (!m_enabled) 92 if (!m_enabled)
121 return; 93 return;
122 94
123 //m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} ADDED", scene.RegionInfo.RegionName);
124
125 m_scene = scene; 95 m_scene = scene;
126 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 96 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
127 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; 97 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
128// m_scene.EventManager.OnGatherUuids += GatherMaterialsUuids;
129 } 98 }
130 99
131 void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) 100 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
132 { 101 {
133 foreach (var part in obj.Parts) 102 foreach (var part in obj.Parts)
134 if (part != null) 103 if (part != null)
135 GetStoredMaterialsForPart(part); 104 GetStoredMaterialsInPart(part);
136 } 105 }
137 106
138 void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps) 107 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
139 { 108 {
140 string capsBase = "/CAPS/" + caps.CapsObjectPath; 109 string capsBase = "/CAPS/" + caps.CapsObjectPath;
141 110
@@ -164,143 +133,65 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
164 133
165 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 134 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
166 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene; 135 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
167// m_scene.EventManager.OnGatherUuids -= GatherMaterialsUuids;
168
169 //m_log.DebugFormat("[MaterialsDemoModule]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
170 } 136 }
171 137
172 public void RegionLoaded(Scene scene) 138 public void RegionLoaded(Scene scene)
173 { 139 {
174 } 140 }
175 141
176 OSDMap GetMaterial(UUID id) 142 /// <summary>
177 { 143 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
178 OSDMap map = null; 144 /// </summary>
179 lock (m_knownMaterials) 145 private void GetStoredMaterialsInPart(SceneObjectPart part)
180 {
181 if (m_knownMaterials.ContainsKey(id))
182 {
183 map = new OSDMap();
184 map["ID"] = OSD.FromBinary(id.GetBytes());
185 map["Material"] = m_knownMaterials[id];
186 }
187 }
188 return map;
189 }
190
191 void GetStoredMaterialsForPart(SceneObjectPart part)
192 { 146 {
193 OSD OSMaterials = null; 147 if (part.Shape == null)
194 OSDArray matsArr = null;
195
196 if (part.DynAttrs == null)
197 {
198 //m_log.Warn("[MaterialsDemoModule]: NULL DYNATTRS :( ");
199 return; 148 return;
200 } 149 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
201 150 if (te == null)
202 lock (part.DynAttrs)
203 {
204 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
205 {
206 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
207
208 if (materialsStore == null)
209 return;
210
211 materialsStore.TryGetValue("Materials", out OSMaterials);
212 }
213
214 if (OSMaterials != null && OSMaterials is OSDArray)
215 matsArr = OSMaterials as OSDArray;
216 else
217 return;
218 }
219
220 //m_log.Info("[MaterialsDemoModule]: OSMaterials: " + OSDParser.SerializeJsonString(OSMaterials));
221
222 if (matsArr == null)
223 {
224 //m_log.Info("[MaterialsDemoModule]: matsArr is null :( ");
225 return; 151 return;
226 }
227 152
228 foreach (OSD elemOsd in matsArr) 153 GetStoredMaterialInFace(part, te.DefaultTexture);
154
155 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
229 { 156 {
230 if (elemOsd != null && elemOsd is OSDMap) 157 if (face != null)
231 { 158 GetStoredMaterialInFace(part, face);
232 OSDMap matMap = elemOsd as OSDMap;
233 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
234 {
235 try
236 {
237 lock (m_knownMaterials)
238 m_knownMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
239 }
240 catch (Exception e)
241 {
242 m_log.Warn("[MaterialsDemoModule]: exception decoding persisted material ", e);
243 }
244 }
245 }
246 } 159 }
247 } 160 }
248 161
249 void StoreMaterialsForPart(SceneObjectPart part) 162 /// <summary>
163 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
164 /// </summary>
165 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
250 { 166 {
251 try 167 UUID id = face.MaterialID;
168 if (id == UUID.Zero)
169 return;
170
171 lock (m_regionMaterials)
252 { 172 {
253 if (part == null || part.Shape == null) 173 if (m_regionMaterials.ContainsKey(id))
254 return; 174 return;
255 175
256 Dictionary<UUID, OSDMap> mats = new Dictionary<UUID, OSDMap>(); 176 byte[] data = m_scene.AssetService.GetData(id.ToString());
257 177 if (data == null)
258 Primitive.TextureEntry te = part.Shape.Textures;
259
260 if (te.DefaultTexture != null)
261 { 178 {
262 lock (m_knownMaterials) 179 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
263 { 180 return;
264 if (m_knownMaterials.ContainsKey(te.DefaultTexture.MaterialID))
265 mats[te.DefaultTexture.MaterialID] = m_knownMaterials[te.DefaultTexture.MaterialID];
266 }
267 } 181 }
268 182
269 if (te.FaceTextures != null) 183 OSDMap mat;
184 try
270 { 185 {
271 foreach (var face in te.FaceTextures) 186 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
272 {
273 if (face != null)
274 {
275 lock (m_knownMaterials)
276 {
277 if (m_knownMaterials.ContainsKey(face.MaterialID))
278 mats[face.MaterialID] = m_knownMaterials[face.MaterialID];
279 }
280 }
281 }
282 } 187 }
283 if (mats.Count == 0) 188 catch (Exception e)
284 return;
285
286 OSDArray matsArr = new OSDArray();
287 foreach (KeyValuePair<UUID, OSDMap> kvp in mats)
288 { 189 {
289 OSDMap matOsd = new OSDMap(); 190 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
290 matOsd["ID"] = OSD.FromUUID(kvp.Key); 191 return;
291 matOsd["Material"] = kvp.Value;
292 matsArr.Add(matOsd);
293 } 192 }
294 193
295 OSDMap OSMaterials = new OSDMap(); 194 m_regionMaterials[id] = mat;
296 OSMaterials["Materials"] = matsArr;
297
298 lock (part.DynAttrs)
299 part.DynAttrs.SetStore("OpenSim", "Materials", OSMaterials);
300 }
301 catch (Exception e)
302 {
303 m_log.Warn("[MaterialsDemoModule]: exception in StoreMaterialsForPart() ", e);
304 } 195 }
305 } 196 }
306 197
@@ -308,8 +199,6 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
308 string param, IOSHttpRequest httpRequest, 199 string param, IOSHttpRequest httpRequest,
309 IOSHttpResponse httpResponse) 200 IOSHttpResponse httpResponse)
310 { 201 {
311 //m_log.Debug("[MaterialsDemoModule]: POST cap handler");
312
313 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); 202 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
314 OSDMap resp = new OSDMap(); 203 OSDMap resp = new OSDMap();
315 204
@@ -333,34 +222,38 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
333 { 222 {
334 foreach (OSD elem in (OSDArray)osd) 223 foreach (OSD elem in (OSDArray)osd)
335 { 224 {
336
337 try 225 try
338 { 226 {
339 UUID id = new UUID(elem.AsBinary(), 0); 227 UUID id = new UUID(elem.AsBinary(), 0);
340 228
341 lock (m_knownMaterials) 229 lock (m_regionMaterials)
342 { 230 {
343 if (m_knownMaterials.ContainsKey(id)) 231 if (m_regionMaterials.ContainsKey(id))
344 { 232 {
345 //m_log.Info("[MaterialsDemoModule]: request for known material ID: " + id.ToString());
346 OSDMap matMap = new OSDMap(); 233 OSDMap matMap = new OSDMap();
347 matMap["ID"] = OSD.FromBinary(id.GetBytes()); 234 matMap["ID"] = OSD.FromBinary(id.GetBytes());
348 235 matMap["Material"] = m_regionMaterials[id];
349 matMap["Material"] = m_knownMaterials[id];
350 respArr.Add(matMap); 236 respArr.Add(matMap);
351 } 237 }
352 else 238 else
353 m_log.Info("[MaterialsDemoModule]: request for UNKNOWN material ID: " + id.ToString()); 239 {
240 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
241
242 // Theoretically we could try to load the material from the assets service,
243 // but that shouldn't be necessary because the viewer should only request
244 // materials that exist in a prim on the region, and all of these materials
245 // are already stored in m_regionMaterials.
246 }
354 } 247 }
355 } 248 }
356 catch (Exception e) 249 catch (Exception e)
357 { 250 {
358 // report something here? 251 m_log.Error("Error getting materials in response to viewer request", e);
359 continue; 252 continue;
360 } 253 }
361 } 254 }
362 } 255 }
363 else if (osd is OSDMap) // reqest to assign a material 256 else if (osd is OSDMap) // request to assign a material
364 { 257 {
365 materialsFromViewer = osd as OSDMap; 258 materialsFromViewer = osd as OSDMap;
366 259
@@ -375,94 +268,118 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
375 { 268 {
376 foreach (OSDMap matsMap in matsArr) 269 foreach (OSDMap matsMap in matsArr)
377 { 270 {
378 //m_log.Debug("[MaterialsDemoModule]: processing matsMap: " + OSDParser.SerializeJsonString(matsMap));
379
380 uint primLocalID = 0; 271 uint primLocalID = 0;
381 try { primLocalID = matsMap["ID"].AsUInteger(); } 272 try {
382 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"ID\" from matsMap: " + e.Message); } 273 primLocalID = matsMap["ID"].AsUInteger();
383 //m_log.Debug("[MaterialsDemoModule]: primLocalID: " + primLocalID.ToString()); 274 }
275 catch (Exception e) {
276 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
277 continue;
278 }
384 279
385 OSDMap mat = null; 280 OSDMap mat = null;
386 try { mat = matsMap["Material"] as OSDMap; } 281 try
387 catch (Exception e) { m_log.Warn("[MaterialsDemoModule]: cannot decode \"Material\" from matsMap: " + e.Message); } 282 {
388 //m_log.Debug("[MaterialsDemoModule]: mat: " + OSDParser.SerializeJsonString(mat)); 283 mat = matsMap["Material"] as OSDMap;
284 }
285 catch (Exception e)
286 {
287 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
288 continue;
289 }
290
291 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
292 if (sop == null)
293 {
294 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
295 continue;
296 }
297
298 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
299 if (te == null)
300 {
301 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
302 continue;
303 }
304
389 305
390 UUID id; 306 UUID id;
391 if (mat == null) 307 if (mat == null)
392 { 308 {
309 // This happens then the user removes a material from a prim
393 id = UUID.Zero; 310 id = UUID.Zero;
394 } 311 }
395 else 312 else
396 { 313 {
397 id = HashOsd(mat); 314 // Material UUID = hash of the material's data.
398 lock (m_knownMaterials) 315 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
399 m_knownMaterials[id] = mat; 316 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
317 using (var md5 = MD5.Create())
318 id = new UUID(md5.ComputeHash(data), 0);
319
320 lock (m_regionMaterials)
321 {
322 if (!m_regionMaterials.ContainsKey(id))
323 {
324 m_regionMaterials[id] = mat;
325
326 // This asset might exist already, but it's ok to try to store it again
327 string name = "Material " + ChooseMaterialName(mat, sop);
328 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
329 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, sop.OwnerID.ToString());
330 asset.Data = data;
331 m_scene.AssetService.Store(asset);
332 }
333 }
400 } 334 }
401 335
402 var sop = m_scene.GetSceneObjectPart(primLocalID);
403 if (sop == null)
404 m_log.Debug("[MaterialsDemoModule]: null SOP for localId: " + primLocalID.ToString());
405 else
406 {
407 var te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
408 336
409 if (te == null) 337 int face = -1;
338
339 if (matsMap.ContainsKey("Face"))
340 {
341 face = matsMap["Face"].AsInteger();
342 if (te.FaceTextures == null) // && face == 0)
410 { 343 {
411 m_log.Debug("[MaterialsDemoModule]: null TextureEntry for localId: " + primLocalID.ToString()); 344 if (te.DefaultTexture == null)
345 m_log.WarnFormat("[Materials]: te.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
346 else
347 te.DefaultTexture.MaterialID = id;
412 } 348 }
413 else 349 else
414 { 350 {
415 int face = -1; 351 if (te.FaceTextures.Length >= face - 1)
416
417 if (matsMap.ContainsKey("Face"))
418 {
419 face = matsMap["Face"].AsInteger();
420 if (te.FaceTextures == null) // && face == 0)
421 {
422 if (te.DefaultTexture == null)
423 m_log.Debug("[MaterialsDemoModule]: te.DefaultTexture is null");
424 else
425 te.DefaultTexture.MaterialID = id;
426 }
427 else
428 {
429 if (te.FaceTextures.Length >= face - 1)
430 {
431 if (te.FaceTextures[face] == null)
432 te.DefaultTexture.MaterialID = id;
433 else
434 te.FaceTextures[face].MaterialID = id;
435 }
436 }
437 }
438 else
439 { 352 {
440 if (te.DefaultTexture != null) 353 if (te.FaceTextures[face] == null)
441 te.DefaultTexture.MaterialID = id; 354 te.DefaultTexture.MaterialID = id;
355 else
356 te.FaceTextures[face].MaterialID = id;
442 } 357 }
358 }
359 }
360 else
361 {
362 if (te.DefaultTexture != null)
363 te.DefaultTexture.MaterialID = id;
364 }
443 365
444 //m_log.DebugFormat("[MaterialsDemoModule]: in \"{0}\", setting material ID for face {1} to {2}", sop.Name, face, id); 366 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
445
446 //we cant use sop.UpdateTextureEntry(te); because it filters so do it manually
447
448 if (sop.ParentGroup != null)
449 {
450 sop.Shape.TextureEntry = te.GetBytes();
451 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
452 sop.UpdateFlag = UpdateRequired.FULL;
453 sop.ParentGroup.HasGroupChanged = true;
454 367
455 sop.ScheduleFullUpdate(); 368 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
369 sop.Shape.TextureEntry = te.GetBytes();
456 370
457 StoreMaterialsForPart(sop); 371 if (sop.ParentGroup != null)
458 } 372 {
459 } 373 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
374 sop.UpdateFlag = UpdateRequired.FULL;
375 sop.ParentGroup.HasGroupChanged = true;
376 sop.ScheduleFullUpdate();
460 } 377 }
461 } 378 }
462 } 379 }
463 catch (Exception e) 380 catch (Exception e)
464 { 381 {
465 m_log.Warn("[MaterialsDemoModule]: exception processing received material ", e); 382 m_log.Warn("[Materials]: exception processing received material ", e);
466 } 383 }
467 } 384 }
468 } 385 }
@@ -472,36 +389,63 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
472 } 389 }
473 catch (Exception e) 390 catch (Exception e)
474 { 391 {
475 m_log.Warn("[MaterialsDemoModule]: exception decoding zipped CAP payload ", e); 392 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
476 //return ""; 393 //return "";
477 } 394 }
478 //m_log.Debug("[MaterialsDemoModule]: knownMaterials.Count: " + m_knownMaterials.Count.ToString());
479 } 395 }
480 396
481 397
482 resp["Zipped"] = ZCompressOSD(respArr, false); 398 resp["Zipped"] = ZCompressOSD(respArr, false);
483 string response = OSDParser.SerializeLLSDXmlString(resp); 399 string response = OSDParser.SerializeLLSDXmlString(resp);
484 400
485 //m_log.Debug("[MaterialsDemoModule]: cap request: " + request); 401 //m_log.Debug("[Materials]: cap request: " + request);
486 //m_log.Debug("[MaterialsDemoModule]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary())); 402 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
487 //m_log.Debug("[MaterialsDemoModule]: cap response: " + response); 403 //m_log.Debug("[Materials]: cap response: " + response);
488 return response; 404 return response;
489 } 405 }
490 406
407 /// <summary>
408 /// Use heuristics to choose a good name for the material.
409 /// </summary>
410 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
411 {
412 UUID normMap = mat["NormMap"].AsUUID();
413 if (normMap != UUID.Zero)
414 {
415 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
416 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
417 return asset.Name;
418 }
419
420 UUID specMap = mat["SpecMap"].AsUUID();
421 if (specMap != UUID.Zero)
422 {
423 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
424 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
425 return asset.Name;
426 }
427
428 if (sop.Name != "Primitive")
429 return sop.Name;
430
431 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
432 return sop.ParentGroup.Name;
433
434 return "";
435 }
436
491 437
492 public string RenderMaterialsGetCap(string request, string path, 438 public string RenderMaterialsGetCap(string request, string path,
493 string param, IOSHttpRequest httpRequest, 439 string param, IOSHttpRequest httpRequest,
494 IOSHttpResponse httpResponse) 440 IOSHttpResponse httpResponse)
495 { 441 {
496 //m_log.Debug("[MaterialsDemoModule]: GET cap handler");
497
498 OSDMap resp = new OSDMap(); 442 OSDMap resp = new OSDMap();
499 int matsCount = 0; 443 int matsCount = 0;
500 OSDArray allOsd = new OSDArray(); 444 OSDArray allOsd = new OSDArray();
501 445
502 lock (m_knownMaterials) 446 lock (m_regionMaterials)
503 { 447 {
504 foreach (KeyValuePair<UUID, OSDMap> kvp in m_knownMaterials) 448 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
505 { 449 {
506 OSDMap matMap = new OSDMap(); 450 OSDMap matMap = new OSDMap();
507 451
@@ -513,12 +457,11 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
513 } 457 }
514 458
515 resp["Zipped"] = ZCompressOSD(allOsd, false); 459 resp["Zipped"] = ZCompressOSD(allOsd, false);
516 //m_log.Debug("[MaterialsDemoModule]: matsCount: " + matsCount.ToString());
517 460
518 return OSDParser.SerializeLLSDXmlString(resp); 461 return OSDParser.SerializeLLSDXmlString(resp);
519 } 462 }
520 463
521 static string ZippedOsdBytesToString(byte[] bytes) 464 private static string ZippedOsdBytesToString(byte[] bytes)
522 { 465 {
523 try 466 try
524 { 467 {
@@ -537,26 +480,27 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
537 /// <returns></returns> 480 /// <returns></returns>
538 private static UUID HashOsd(OSD osd) 481 private static UUID HashOsd(OSD osd)
539 { 482 {
483 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
540 using (var md5 = MD5.Create()) 484 using (var md5 = MD5.Create())
541 using (MemoryStream ms = new MemoryStream(OSDParser.SerializeLLSDBinary(osd, false))) 485 return new UUID(md5.ComputeHash(data), 0);
542 return new UUID(md5.ComputeHash(ms), 0);
543 } 486 }
544 487
545 public static OSD ZCompressOSD(OSD inOsd, bool useHeader) 488 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
546 { 489 {
547 OSD osd = null; 490 OSD osd = null;
548 491
492 byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
493
549 using (MemoryStream msSinkCompressed = new MemoryStream()) 494 using (MemoryStream msSinkCompressed = new MemoryStream())
550 { 495 {
551 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed, 496 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
552 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true)) 497 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
553 { 498 {
554 CopyStream(new MemoryStream(OSDParser.SerializeLLSDBinary(inOsd, useHeader)), zOut); 499 zOut.Write(data, 0, data.Length);
555 zOut.Close();
556 } 500 }
557 501
558 msSinkCompressed.Seek(0L, SeekOrigin.Begin); 502 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
559 osd = OSD.FromBinary( msSinkCompressed.ToArray()); 503 osd = OSD.FromBinary(msSinkCompressed.ToArray());
560 } 504 }
561 505
562 return osd; 506 return osd;
@@ -571,94 +515,14 @@ namespace OpenSim.Region.OptionalModules.MaterialsDemoModule
571 { 515 {
572 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true)) 516 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
573 { 517 {
574 CopyStream(new MemoryStream(input), zOut); 518 zOut.Write(input, 0, input.Length);
575 zOut.Close();
576 } 519 }
520
577 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin); 521 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
578 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray()); 522 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
579 } 523 }
580 524
581 return osd; 525 return osd;
582 } 526 }
583
584 static void CopyStream(System.IO.Stream input, System.IO.Stream output)
585 {
586 byte[] buffer = new byte[2048];
587 int len;
588 while ((len = input.Read(buffer, 0, 2048)) > 0)
589 {
590 output.Write(buffer, 0, len);
591 }
592
593 output.Flush();
594 }
595
596 // FIXME: This code is currently still in UuidGatherer since we cannot use Scene.EventManager as some
597 // calls to the gatherer are done for objects with no scene.
598// /// <summary>
599// /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
600// /// </summary>
601// /// <param name="part"></param>
602// /// <param name="assetUuids"></param>
603// private void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
604// {
605// // scan thru the dynAttrs map of this part for any textures used as materials
606// OSD osdMaterials = null;
607//
608// lock (part.DynAttrs)
609// {
610// if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
611// {
612// OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
613// if (materialsStore == null)
614// return;
615//
616// materialsStore.TryGetValue("Materials", out osdMaterials);
617// }
618//
619// if (osdMaterials != null)
620// {
621// //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
622//
623// if (osdMaterials is OSDArray)
624// {
625// OSDArray matsArr = osdMaterials as OSDArray;
626// foreach (OSDMap matMap in matsArr)
627// {
628// try
629// {
630// if (matMap.ContainsKey("Material"))
631// {
632// OSDMap mat = matMap["Material"] as OSDMap;
633// if (mat.ContainsKey("NormMap"))
634// {
635// UUID normalMapId = mat["NormMap"].AsUUID();
636// if (normalMapId != UUID.Zero)
637// {
638// assetUuids[normalMapId] = AssetType.Texture;
639// //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
640// }
641// }
642// if (mat.ContainsKey("SpecMap"))
643// {
644// UUID specularMapId = mat["SpecMap"].AsUUID();
645// if (specularMapId != UUID.Zero)
646// {
647// assetUuids[specularMapId] = AssetType.Texture;
648// //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
649// }
650// }
651// }
652//
653// }
654// catch (Exception e)
655// {
656// m_log.Warn("[MaterialsDemoModule]: exception getting materials: " + e.Message);
657// }
658// }
659// }
660// }
661// }
662// }
663 } 527 }
664} 528}
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 28c16cf..28369a3 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -691,6 +691,12 @@
691 ; enable_windlight = false 691 ; enable_windlight = false
692 692
693 693
694[Materials]
695 ;# {enable_materials} {} {Enable Materials support?} {true false} true
696 ;; This enables the use of Materials.
697 ; enable_materials = true
698
699
694[DataSnapshot] 700[DataSnapshot]
695 ;# {index_sims} {} {Enable data snapshotting (search)?} {true false} false 701 ;# {index_sims} {} {Enable data snapshotting (search)?} {true false} false
696 ;; The following set of configs pertains to search. 702 ;; The following set of configs pertains to search.