aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs219
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs520
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs547
-rw-r--r--opensim/Region/Framework/Interfaces/IMaterialsModule.cs41
4 files changed, 992 insertions, 335 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
index d38ef61..e4b9380 100644
--- a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -26,10 +26,12 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Text;
30using System.Runtime.InteropServices;
31using System.Security.Cryptography; // for computing md5 hash
32using OpenSim.Framework;
30using OpenMetaverse; 33using OpenMetaverse;
31using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
32using OpenSim.Framework;
33 35
34namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
35{ 37{
@@ -93,38 +95,74 @@ namespace OpenSim.Region.Framework.Scenes
93 } 95 }
94 } 96 }
95 97
98 [StructLayout(LayoutKind.Sequential)]
96 public class FaceMaterial 99 public class FaceMaterial
97 { 100 {
98 public UUID ID; 101 // ll material data
99 public UUID NormalMapID = UUID.Zero; 102 public byte DiffuseAlphaMode = 1;
100 public float NormalOffsetX = 0.0f; 103 public byte AlphaMaskCutoff = 0;
101 public float NormalOffsetY = 0.0f; 104 public byte SpecularLightExponent = 51;
102 public float NormalRepeatX = 1.0f; 105 public byte EnvironmentIntensity = 0;
103 public float NormalRepeatY = 1.0f; 106 // need to have 4 bytes here
104 public float NormalRotation = 0.0f; 107 public float NormalOffsetX = 0.0f;
105 108 public float NormalOffsetY = 0.0f;
106 public UUID SpecularMapID = UUID.Zero; 109 public float NormalRepeatX = 1.0f;
107 public float SpecularOffsetX = 0.0f; 110 public float NormalRepeatY = 1.0f;
108 public float SpecularOffsetY = 0.0f; 111 public float NormalRotation = 0.0f;
109 public float SpecularRepeatX = 1.0f; 112
110 public float SpecularRepeatY = 1.0f; 113 public float SpecularOffsetX = 0.0f;
111 public float SpecularRotation = 0.0f; 114 public float SpecularOffsetY = 0.0f;
112 115 public float SpecularRepeatX = 1.0f;
113 public Color4 SpecularLightColor = new Color4(255,255,255,255); 116 public float SpecularRepeatY = 1.0f;
114 public Byte SpecularLightExponent = 51; 117 public float SpecularRotation = 0.0f;
115 public Byte EnvironmentIntensity = 0; 118
116 public Byte DiffuseAlphaMode = 1; 119 public byte SpecularLightColorR = 255;
117 public Byte AlphaMaskCutoff = 0; 120 public byte SpecularLightColorG = 255;
121 public byte SpecularLightColorB = 255;
122 public byte SpecularLightColorA = 255;
123 // data size 12 ints so far
124 public UUID NormalMapID = UUID.Zero;
125 public UUID SpecularMapID = UUID.Zero;
126
127 // other data
128 public UUID ID;
129 private int inthash;
130 private bool validinthash;
118 131
119 public FaceMaterial() 132 public FaceMaterial()
120 { } 133 { }
121 134
122 public FaceMaterial(UUID pID, OSDMap mat) 135 public FaceMaterial(FaceMaterial other)
136 {
137 if(other == null)
138 return;
139
140 DiffuseAlphaMode = other.DiffuseAlphaMode;
141 AlphaMaskCutoff = other.AlphaMaskCutoff;
142 SpecularLightExponent = other.SpecularLightExponent;
143 EnvironmentIntensity = other.EnvironmentIntensity;
144 NormalOffsetX = other.NormalOffsetX;
145 NormalOffsetY = other.NormalOffsetY;
146 NormalRepeatX = other.NormalRepeatX;
147 NormalRepeatY = other.NormalRepeatY;
148 NormalRotation = other.NormalRotation;
149 SpecularOffsetX = other.SpecularOffsetX;
150 SpecularOffsetY = other.SpecularOffsetY;
151 SpecularRepeatX = other.SpecularRepeatX;
152 SpecularRepeatY = other.SpecularRepeatY;
153 SpecularRotation = other.SpecularRotation;
154 SpecularLightColorR = other.SpecularLightColorR;
155 SpecularLightColorG = other.SpecularLightColorG;
156 SpecularLightColorB = other.SpecularLightColorB;
157 NormalMapID = other.NormalMapID;
158 SpecularMapID = other.SpecularMapID;
159 }
160
161 public FaceMaterial(OSDMap mat)
123 { 162 {
124 ID = pID;
125 if(mat == null) 163 if(mat == null)
126 return; 164 return;
127 float scale = 0.0001f; 165 const float scale = 0.0001f;
128 NormalMapID = mat["NormMap"].AsUUID(); 166 NormalMapID = mat["NormMap"].AsUUID();
129 NormalOffsetX = scale * (float)mat["NormOffsetX"].AsReal(); 167 NormalOffsetX = scale * (float)mat["NormOffsetX"].AsReal();
130 NormalOffsetY = scale * (float)mat["NormOffsetY"].AsReal(); 168 NormalOffsetY = scale * (float)mat["NormOffsetY"].AsReal();
@@ -138,14 +176,88 @@ namespace OpenSim.Region.Framework.Scenes
138 SpecularRepeatX = scale * (float)mat["SpecRepeatX"].AsReal(); 176 SpecularRepeatX = scale * (float)mat["SpecRepeatX"].AsReal();
139 SpecularRepeatY = scale * (float)mat["SpecRepeatY"].AsReal(); 177 SpecularRepeatY = scale * (float)mat["SpecRepeatY"].AsReal();
140 SpecularRotation = scale * (float)mat["SpecRotation"].AsReal(); 178 SpecularRotation = scale * (float)mat["SpecRotation"].AsReal();
179
180 Color4 SpecularLightColortmp = mat["SpecColor"].AsColor4(); // we can read as color4
181 SpecularLightColorR = (byte)(SpecularLightColortmp.R);
182 SpecularLightColorG = (byte)(SpecularLightColortmp.G);
183 SpecularLightColorB = (byte)(SpecularLightColortmp.B);
141 184
142 SpecularLightColor = mat["SpecColor"].AsColor4();
143 SpecularLightExponent = (Byte)mat["SpecExp"].AsUInteger(); 185 SpecularLightExponent = (Byte)mat["SpecExp"].AsUInteger();
144 EnvironmentIntensity = (Byte)mat["EnvIntensity"].AsUInteger(); 186 EnvironmentIntensity = (Byte)mat["EnvIntensity"].AsUInteger();
145 DiffuseAlphaMode = (Byte)mat["DiffuseAlphaMode"].AsUInteger(); 187 DiffuseAlphaMode = (Byte)mat["DiffuseAlphaMode"].AsUInteger();
146 AlphaMaskCutoff = (Byte)mat["AlphaMaskCutoff"].AsUInteger(); 188 AlphaMaskCutoff = (Byte)mat["AlphaMaskCutoff"].AsUInteger();
147 } 189 }
148 190
191 public void genID()
192 {
193 string lslx = toLLSDxml();
194 Byte[] data = System.Text.Encoding.ASCII.GetBytes(lslx);
195 using (var md5 = MD5.Create())
196 ID = new UUID(md5.ComputeHash(data), 0);
197 }
198
199 public unsafe override int GetHashCode()
200 {
201 if(!validinthash)
202 {
203 unchecked
204 {
205 // if you don't like this, don't read...
206 int* ptr;
207 fixed(byte* ptrbase = &DiffuseAlphaMode)
208 {
209 ptr = (int*)ptrbase;
210 inthash = *ptr;
211 for(int i = 0; i < 11; i++)
212 inthash ^= *ptr++;
213 }
214 fixed(Guid* ptrbase = &NormalMapID.Guid)
215 {
216 ptr = (int*)ptrbase;
217 for(int i = 0; i < 16; i++)
218 inthash ^= ptr[i];
219 }
220 fixed(Guid* ptrbase = &SpecularMapID.Guid)
221 {
222 ptr = (int*)ptrbase;
223 for(int i = 0; i < 16; i++)
224 inthash ^= ptr[i];
225 }
226 }
227 validinthash = true;
228 }
229 return inthash;
230 }
231
232 public override bool Equals(Object o)
233 {
234 if(o == null || !(o is FaceMaterial))
235 return false;
236
237 FaceMaterial other = (FaceMaterial)o;
238 return (
239 DiffuseAlphaMode == other.DiffuseAlphaMode
240 && AlphaMaskCutoff == other.AlphaMaskCutoff
241 && SpecularLightExponent == other.SpecularLightExponent
242 && EnvironmentIntensity == other.EnvironmentIntensity
243 && NormalMapID == other.NormalMapID
244 && NormalOffsetX == other.NormalOffsetX
245 && NormalOffsetY == other.NormalOffsetY
246 && NormalRepeatX == other.NormalRepeatX
247 && NormalRepeatY == other.NormalRepeatY
248 && NormalRotation == other.NormalRotation
249 && SpecularMapID == other.SpecularMapID
250 && SpecularOffsetX == other.SpecularOffsetX
251 && SpecularOffsetY == other.SpecularOffsetY
252 && SpecularRepeatX == other.SpecularRepeatX
253 && SpecularRepeatY == other.SpecularRepeatY
254 && SpecularRotation == other.SpecularRotation
255 && SpecularLightColorR == other.SpecularLightColorR
256 && SpecularLightColorG == other.SpecularLightColorG
257 && SpecularLightColorB == other.SpecularLightColorB
258 );
259 }
260
149 public OSDMap toOSD() 261 public OSDMap toOSD()
150 { 262 {
151 OSDMap mat = new OSDMap(); 263 OSDMap mat = new OSDMap();
@@ -165,7 +277,12 @@ namespace OpenSim.Region.Framework.Scenes
165 mat["SpecRepeatY"] = (int) (scale * SpecularRepeatY); 277 mat["SpecRepeatY"] = (int) (scale * SpecularRepeatY);
166 mat["SpecRotation"] = (int) (scale * SpecularRotation); 278 mat["SpecRotation"] = (int) (scale * SpecularRotation);
167 279
168 mat["SpecColor"] = SpecularLightColor; 280 OSDArray carray = new OSDArray(4);
281 carray.Add(SpecularLightColorR);
282 carray.Add(SpecularLightColorG);
283 carray.Add(SpecularLightColorB);
284 carray.Add(255); // solid color
285 mat["SpecColor"] = carray;
169 mat["SpecExp"] = SpecularLightExponent; 286 mat["SpecExp"] = SpecularLightExponent;
170 mat["EnvIntensity"] = EnvironmentIntensity; 287 mat["EnvIntensity"] = EnvironmentIntensity;
171 mat["DiffuseAlphaMode"] = DiffuseAlphaMode; 288 mat["DiffuseAlphaMode"] = DiffuseAlphaMode;
@@ -173,5 +290,53 @@ namespace OpenSim.Region.Framework.Scenes
173 290
174 return mat; 291 return mat;
175 } 292 }
293
294 public string toLLSDxml(StringBuilder sb = null)
295 {
296 const float scale = 10000f;
297 bool fullLLSD = false;
298 if(sb == null)
299 {
300
301 sb = LLSDxmlEncode.Start(1024,false);
302 fullLLSD = true;
303 }
304
305 LLSDxmlEncode.AddMap(sb);
306 LLSDxmlEncode.AddElem("NormMap", NormalMapID, sb);
307 LLSDxmlEncode.AddElem("NormOffsetX", (int) (scale * NormalOffsetX + 0.5f), sb);
308 LLSDxmlEncode.AddElem("NormOffsetY", (int) (scale * NormalOffsetY + 0.5f), sb);
309 LLSDxmlEncode.AddElem("NormRepeatX", (int) (scale * NormalRepeatX + 0.5f), sb);
310 LLSDxmlEncode.AddElem("NormRepeatY", (int) (scale * NormalRepeatY + 0.5f), sb);
311 LLSDxmlEncode.AddElem("NormRotation", (int) (scale * NormalRotation + 0.5f), sb);
312
313 LLSDxmlEncode.AddElem("SpecMap", SpecularMapID, sb);
314 LLSDxmlEncode.AddElem("SpecOffsetX", (int) (scale * SpecularOffsetX + 0.5f), sb);
315 LLSDxmlEncode.AddElem("SpecOffsetY", (int) (scale * SpecularOffsetY + 0.5f), sb);
316 LLSDxmlEncode.AddElem("SpecRepeatX", (int) (scale * SpecularRepeatX + 0.5f), sb);
317 LLSDxmlEncode.AddElem("SpecRepeatY", (int) (scale * SpecularRepeatY + 0.5f), sb);
318 LLSDxmlEncode.AddElem("SpecRotation", (int) (scale * SpecularRotation + 0.5f), sb);
319
320 LLSDxmlEncode.AddArray("SpecColor", sb);
321 LLSDxmlEncode.AddElem(SpecularLightColorR, sb);
322 LLSDxmlEncode.AddElem(SpecularLightColorG, sb);
323 LLSDxmlEncode.AddElem(SpecularLightColorB, sb);
324 LLSDxmlEncode.AddElem(255, sb);
325 LLSDxmlEncode.AddEndArray(sb);
326
327 LLSDxmlEncode.AddElem("SpecExp", SpecularLightExponent, sb);
328 LLSDxmlEncode.AddElem("EnvIntensity", EnvironmentIntensity, sb);
329 LLSDxmlEncode.AddElem("DiffuseAlphaMode", DiffuseAlphaMode, sb);
330 LLSDxmlEncode.AddElem("AlphaMaskCutoff", AlphaMaskCutoff, sb);
331
332 LLSDxmlEncode.AddEndMap(sb);
333
334 if(fullLLSD)
335 {
336 return LLSDxmlEncode.End(sb);
337 }
338 else
339 return String.Empty; // ignored if appending
340 }
176 } 341 }
177} \ No newline at end of file 342} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index e8cb052..62e1e5c 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -46,16 +46,10 @@ using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
46 46
47using Ionic.Zlib; 47using Ionic.Zlib;
48 48
49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
51// the available DLLs
52//[assembly: Addin("MaterialsModule", "1.0")]
53//[assembly: AddinDependency("OpenSim", "0.8.1")]
54
55namespace OpenSim.Region.OptionalModules.Materials 49namespace OpenSim.Region.OptionalModules.Materials
56{ 50{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
58 public class MaterialsModule : INonSharedRegionModule 52 public class MaterialsModule : INonSharedRegionModule, IMaterialsModule
59 { 53 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61 55
@@ -67,12 +61,12 @@ namespace OpenSim.Region.OptionalModules.Materials
67 private Scene m_scene = null; 61 private Scene m_scene = null;
68 private bool m_enabled = false; 62 private bool m_enabled = false;
69 private int m_maxMaterialsPerTransaction = 50; 63 private int m_maxMaterialsPerTransaction = 50;
64 private object materialslock = new object();
70 65
71 public Dictionary<UUID, OSDMap> m_Materials = new Dictionary<UUID, OSDMap>(); 66 public Dictionary<UUID, FaceMaterial> m_Materials = new Dictionary<UUID, FaceMaterial>();
72 public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>(); 67 public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>();
73 68
74 private Dictionary<ulong, AssetBase> m_changes = new Dictionary<ulong, AssetBase>(); 69 private Dictionary<FaceMaterial, double> m_changed = new Dictionary<FaceMaterial, double>();
75 private Dictionary<ulong, double> m_changesTime = new Dictionary<ulong, double>();
76 70
77 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
78 { 72 {
@@ -101,54 +95,72 @@ namespace OpenSim.Region.OptionalModules.Materials
101 return; 95 return;
102 96
103 m_scene = scene; 97 m_scene = scene;
98 m_scene.RegisterModuleInterface<IMaterialsModule>(this);
104 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 99 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
105 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; 100 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
101 m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManager_OnObjectDeleteFromScene;
106 m_scene.EventManager.OnBackup += EventManager_OnBackup; 102 m_scene.EventManager.OnBackup += EventManager_OnBackup;
107 } 103 }
108 104
109 private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup) 105 public void RemoveRegion(Scene scene)
110 { 106 {
111 List<AssetBase> toStore; 107 if (!m_enabled)
112 List<ulong> hashlist; 108 return;
113 109
110 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
111 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
112 m_scene.EventManager.OnObjectBeingRemovedFromScene -= EventManager_OnObjectDeleteFromScene;
113 m_scene.EventManager.OnBackup -= EventManager_OnBackup;
114 m_scene.UnregisterModuleInterface<IMaterialsModule>(this);
115 }
114 116
115 lock (m_Materials) 117 public void RegionLoaded(Scene scene)
118 {
119 if (!m_enabled) return;
120
121 m_cache = scene.RequestModuleInterface<IAssetCache>();
122 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
123 if (featuresModule != null)
124 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
125 }
126
127 private void EventManager_OnBackup(ISimulationDataService datastore, bool forcedBackup)
128 {
129 List<FaceMaterial> toStore;
130
131 lock (materialslock)
116 { 132 {
117 if(m_changes.Count == 0) 133 if(m_changed.Count == 0)
118 return; 134 return;
119 135
120 if(forcedBackup) 136 if(forcedBackup)
121 { 137 {
122 toStore = new List<AssetBase>(m_changes.Values); 138 toStore = new List<FaceMaterial>(m_changed.Keys);
123 m_changes.Clear(); 139 m_changed.Clear();
124 m_changesTime.Clear();
125 } 140 }
126 else 141 else
127 { 142 {
128 toStore = new List<AssetBase>(); 143 toStore = new List<FaceMaterial>();
129 hashlist = new List<ulong>(); 144 double storetime = Util.GetTimeStamp() - 60.0;
130 double storetime = Util.GetTimeStampMS() - 60000; 145 foreach(KeyValuePair<FaceMaterial, double> kvp in m_changed)
131 foreach(KeyValuePair<ulong,double> kvp in m_changesTime)
132 { 146 {
133 if(kvp.Value < storetime) 147 if(kvp.Value < storetime)
134 { 148 {
135 toStore.Add(m_changes[kvp.Key]); 149 toStore.Add(kvp.Key);
136 hashlist.Add(kvp.Key);
137 } 150 }
138 } 151 }
139 foreach(ulong u in hashlist) 152 foreach(FaceMaterial fm in toStore)
140 { 153 {
141 m_changesTime.Remove(u); 154 m_changed.Remove(fm);
142 m_changes.Remove(u);
143 } 155 }
144 } 156 }
145 157
146 if(toStore.Count > 0) 158 if(toStore.Count > 0)
147 Util.FireAndForget(delegate 159 Util.FireAndForget(delegate
148 { 160 {
149 foreach(AssetBase a in toStore) 161 foreach(FaceMaterial fm in toStore)
150 { 162 {
151 a.Local = false; 163 AssetBase a = MakeAsset(fm, false);
152 m_scene.AssetService.Store(a); 164 m_scene.AssetService.Store(a);
153 } 165 }
154 }); 166 });
@@ -162,6 +174,13 @@ namespace OpenSim.Region.OptionalModules.Materials
162 GetStoredMaterialsInPart(part); 174 GetStoredMaterialsInPart(part);
163 } 175 }
164 176
177 private void EventManager_OnObjectDeleteFromScene(SceneObjectGroup obj)
178 {
179 foreach (var part in obj.Parts)
180 if (part != null)
181 RemoveMaterialsInPart(part);
182 }
183
165 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps) 184 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
166 { 185 {
167 string capsBase = "/CAPS/" + caps.CapsObjectPath; 186 string capsBase = "/CAPS/" + caps.CapsObjectPath;
@@ -193,26 +212,6 @@ namespace OpenSim.Region.OptionalModules.Materials
193 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler); 212 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
194 } 213 }
195 214
196 public void RemoveRegion(Scene scene)
197 {
198 if (!m_enabled)
199 return;
200
201 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
202 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
203 m_scene.EventManager.OnBackup -= EventManager_OnBackup;
204 }
205
206 public void RegionLoaded(Scene scene)
207 {
208 if (!m_enabled) return;
209
210 m_cache = scene.RequestModuleInterface<IAssetCache>();
211 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
212 if (featuresModule != null)
213 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
214 }
215
216 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features) 215 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
217 { 216 {
218 features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction; 217 features["MaxMaterialsPerTransaction"] = m_maxMaterialsPerTransaction;
@@ -222,14 +221,16 @@ namespace OpenSim.Region.OptionalModules.Materials
222 /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'. 221 /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
223 /// </summary> 222 /// </summary>
224 /// <param name="part"></param> 223 /// <param name="part"></param>
225 private void GetLegacyStoredMaterialsInPart(SceneObjectPart part) 224 private bool GetLegacyStoredMaterialsInPart(SceneObjectPart part)
226 { 225 {
227 if (part.DynAttrs == null) 226 if (part.DynAttrs == null)
228 return; 227 return false;
229 228
230 OSD OSMaterials = null; 229 OSD OSMaterials = null;
231 OSDArray matsArr = null; 230 OSDArray matsArr = null;
232 231
232 bool partchanged = false;
233
233 lock (part.DynAttrs) 234 lock (part.DynAttrs)
234 { 235 {
235 if (part.DynAttrs.ContainsStore("OpenSim", "Materials")) 236 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
@@ -237,20 +238,22 @@ namespace OpenSim.Region.OptionalModules.Materials
237 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials"); 238 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
238 239
239 if (materialsStore == null) 240 if (materialsStore == null)
240 return; 241 return false;
241 242
242 materialsStore.TryGetValue("Materials", out OSMaterials); 243 materialsStore.TryGetValue("Materials", out OSMaterials);
244 part.DynAttrs.RemoveStore("OpenSim", "Materials");
245 partchanged = true;
243 } 246 }
244 247
245 if (OSMaterials != null && OSMaterials is OSDArray) 248 if (OSMaterials != null && OSMaterials is OSDArray)
246 matsArr = OSMaterials as OSDArray; 249 matsArr = OSMaterials as OSDArray;
247 else 250 else
248 return; 251 return partchanged;
249 } 252 }
250 253
251 if (matsArr == null) 254 if (matsArr == null)
252 return; 255 return partchanged;
253 256
254 foreach (OSD elemOsd in matsArr) 257 foreach (OSD elemOsd in matsArr)
255 { 258 {
256 if (elemOsd != null && elemOsd is OSDMap) 259 if (elemOsd != null && elemOsd is OSDMap)
@@ -260,16 +263,24 @@ namespace OpenSim.Region.OptionalModules.Materials
260 { 263 {
261 try 264 try
262 { 265 {
263 lock (m_Materials) 266 lock (materialslock)
264 { 267 {
265 UUID id = matMap["ID"].AsUUID(); 268 UUID id = matMap["ID"].AsUUID();
266 if(m_Materials.ContainsKey(id)) 269 if(m_Materials.ContainsKey(id))
267 m_MaterialsRefCount[id]++; 270 continue;
268 else 271
269 { 272 OSDMap theMatMap = (OSDMap)matMap["Material"];
270 m_Materials[id] = (OSDMap)matMap["Material"]; 273 FaceMaterial fmat = new FaceMaterial(theMatMap);
271 m_MaterialsRefCount[id] = 1; 274
272 } 275 if(fmat == null ||
276 ( fmat.DiffuseAlphaMode == 1
277 && fmat.NormalMapID == UUID.Zero
278 && fmat.SpecularMapID == UUID.Zero))
279 continue;
280
281 fmat.ID = id;
282 m_Materials[id] = fmat;
283 m_MaterialsRefCount[id] = 0;
273 } 284 }
274 } 285 }
275 catch (Exception e) 286 catch (Exception e)
@@ -279,6 +290,7 @@ namespace OpenSim.Region.OptionalModules.Materials
279 } 290 }
280 } 291 }
281 } 292 }
293 return partchanged;
282 } 294 }
283 295
284 /// <summary> 296 /// <summary>
@@ -289,14 +301,16 @@ namespace OpenSim.Region.OptionalModules.Materials
289 if (part.Shape == null) 301 if (part.Shape == null)
290 return; 302 return;
291 303
304 bool partchanged = false;
305 bool facechanged = false;
292 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length); 306 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
293 if (te == null) 307 if (te == null)
294 return; 308 return;
295 309
296 GetLegacyStoredMaterialsInPart(part); 310 partchanged = GetLegacyStoredMaterialsInPart(part);
297 311
298 if (te.DefaultTexture != null) 312 if (te.DefaultTexture != null)
299 GetStoredMaterialInFace(part, te.DefaultTexture); 313 facechanged = GetStoredMaterialInFace(part, te.DefaultTexture);
300 else 314 else
301 m_log.WarnFormat( 315 m_log.WarnFormat(
302 "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.", 316 "[Materials]: Default texture for part {0} (part of object {1}) in {2} unexpectedly null. Ignoring.",
@@ -305,36 +319,47 @@ namespace OpenSim.Region.OptionalModules.Materials
305 foreach (Primitive.TextureEntryFace face in te.FaceTextures) 319 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
306 { 320 {
307 if (face != null) 321 if (face != null)
308 GetStoredMaterialInFace(part, face); 322 facechanged |= GetStoredMaterialInFace(part, face);
323 }
324
325 if(facechanged)
326 part.Shape.TextureEntry = te.GetBytes();
327
328 if(facechanged || partchanged)
329 {
330 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted)
331 part.ParentGroup.HasGroupChanged = true;
309 } 332 }
310 } 333 }
311 334
312 /// <summary> 335 /// <summary>
313 /// Find the materials used in one Face, and add them to 'm_regionMaterials'. 336 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
314 /// </summary> 337 /// </summary>
315 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face) 338 private bool GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
316 { 339 {
317 UUID id = face.MaterialID; 340 UUID id = face.MaterialID;
318 if (id == UUID.Zero) 341 if (id == UUID.Zero)
319 return; 342 return false;
320 343
321 lock (m_Materials) 344 OSDMap mat;
345 lock (materialslock)
322 { 346 {
323 if (m_Materials.ContainsKey(id)) 347 if(m_Materials.ContainsKey(id))
324 { 348 {
325 m_MaterialsRefCount[id]++; 349 m_MaterialsRefCount[id]++;
326 return; 350 return false;
327 } 351 }
328 352
329 AssetBase matAsset = m_scene.AssetService.Get(id.ToString()); 353 AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
330 if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 ) 354 if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
331 { 355 {
332 //m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id); 356 // grid may just be down...
333 return; 357 return false;
334 } 358 }
335 359
336 byte[] data = matAsset.Data; 360 byte[] data = matAsset.Data;
337 OSDMap mat; 361
362 string txt = System.Text.Encoding.ASCII.GetString(data);
338 try 363 try
339 { 364 {
340 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data); 365 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
@@ -342,11 +367,76 @@ namespace OpenSim.Region.OptionalModules.Materials
342 catch (Exception e) 367 catch (Exception e)
343 { 368 {
344 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message); 369 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
345 return; 370 return false;
346 } 371 }
347 372
348 m_Materials[id] = mat; 373 FaceMaterial fmat = new FaceMaterial(mat);
349 m_MaterialsRefCount[id] = 1; 374
375 if(fmat == null ||
376 (fmat.DiffuseAlphaMode == 1
377 && fmat.NormalMapID == UUID.Zero
378 && fmat.SpecularMapID == UUID.Zero))
379 {
380 face.MaterialID = UUID.Zero;
381 return true;
382 }
383
384 fmat.ID = id;
385
386 if (m_Materials.ContainsKey(id))
387 {
388 m_MaterialsRefCount[id]++;
389 }
390 else
391 {
392 m_Materials[id] = fmat;
393 m_MaterialsRefCount[id] = 1;
394 }
395 return false;
396 }
397 }
398
399 private void RemoveMaterialsInPart(SceneObjectPart part)
400 {
401 if (part.Shape == null)
402 return;
403
404 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
405 if (te == null)
406 return;
407
408 if (te.DefaultTexture != null)
409 RemoveMaterialInFace(te.DefaultTexture);
410
411 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
412 {
413 if(face != null)
414 RemoveMaterialInFace(face);
415 }
416 }
417
418 private void RemoveMaterialInFace(Primitive.TextureEntryFace face)
419 {
420 UUID id = face.MaterialID;
421 if (id == UUID.Zero)
422 return;
423
424 lock (materialslock)
425 {
426 if(!m_Materials.ContainsKey(id))
427 return;
428 else
429 {
430 m_MaterialsRefCount[id]--;
431 if(m_MaterialsRefCount[id] <= 0)
432 {
433 FaceMaterial oldFaceMat = m_Materials[id];
434 m_changed.Remove(oldFaceMat);
435 m_Materials.Remove(id);
436 m_MaterialsRefCount.Remove(id);
437 m_cache.Expire(id.ToString());
438 }
439 }
350 } 440 }
351 } 441 }
352 442
@@ -375,13 +465,13 @@ namespace OpenSim.Region.OptionalModules.Materials
375 { 465 {
376 UUID id = new UUID(elem.AsBinary(), 0); 466 UUID id = new UUID(elem.AsBinary(), 0);
377 467
378 lock (m_Materials) 468 lock (materialslock)
379 { 469 {
380 if (m_Materials.ContainsKey(id)) 470 if (m_Materials.ContainsKey(id))
381 { 471 {
382 OSDMap matMap = new OSDMap(); 472 OSDMap matMap = new OSDMap();
383 matMap["ID"] = OSD.FromBinary(id.GetBytes()); 473 matMap["ID"] = OSD.FromBinary(id.GetBytes());
384 matMap["Material"] = m_Materials[id]; 474 matMap["Material"] = m_Materials[id].toOSD();
385 respArr.Add(matMap); 475 respArr.Add(matMap);
386 } 476 }
387 else 477 else
@@ -455,10 +545,12 @@ namespace OpenSim.Region.OptionalModules.Materials
455 foreach (OSDMap matsMap in matsArr) 545 foreach (OSDMap matsMap in matsArr)
456 { 546 {
457 uint primLocalID = 0; 547 uint primLocalID = 0;
458 try { 548 try
549 {
459 primLocalID = matsMap["ID"].AsUInteger(); 550 primLocalID = matsMap["ID"].AsUInteger();
460 } 551 }
461 catch (Exception e) { 552 catch (Exception e)
553 {
462 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message); 554 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
463 continue; 555 continue;
464 } 556 }
@@ -494,68 +586,71 @@ namespace OpenSim.Region.OptionalModules.Materials
494 continue; 586 continue;
495 } 587 }
496 588
497 UUID id;
498 if (mat == null)
499 {
500 // This happens then the user removes a material from a prim
501 id = UUID.Zero;
502 }
503 else
504 {
505 id = getNewID(mat);
506 }
507
508 int face = -1; 589 int face = -1;
509 UUID oldid = UUID.Zero; 590 UUID oldid = UUID.Zero;
591 Primitive.TextureEntryFace faceEntry = null;
510 if (matsMap.ContainsKey("Face")) 592 if (matsMap.ContainsKey("Face"))
511 { 593 {
512 face = matsMap["Face"].AsInteger(); 594 face = matsMap["Face"].AsInteger();
513 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face); 595 faceEntry = te.CreateFace((uint)face);
514 oldid = faceEntry.MaterialID;
515 faceEntry.MaterialID = id;
516 } 596 }
517 else 597 else
598 faceEntry = te.DefaultTexture;
599
600 if (faceEntry == null)
601 continue;
602
603 UUID id;
604 FaceMaterial newFaceMat = null;
605 if (mat == null)
518 { 606 {
519 if (te.DefaultTexture == null) 607 // This happens then the user removes a material from a prim
520 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID); 608 id = UUID.Zero;
609 }
610 else
611 {
612 newFaceMat = new FaceMaterial(mat);
613 if(newFaceMat.DiffuseAlphaMode == 1
614 && newFaceMat.NormalMapID == UUID.Zero
615 && newFaceMat.SpecularMapID == UUID.Zero
616 )
617 id = UUID.Zero;
521 else 618 else
522 { 619 {
523 oldid = te.DefaultTexture.MaterialID; 620 newFaceMat.genID();
524 te.DefaultTexture.MaterialID = id; 621 id = newFaceMat.ID;
525 } 622 }
526 } 623 }
527 624
528 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id); 625 oldid = faceEntry.MaterialID;
529 626
530 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually 627 if(oldid == id)
531 sop.Shape.TextureEntry = te.GetBytes(); 628 continue;
532 629
533 lock(m_Materials) 630 if (faceEntry != null)
534 { 631 {
535 if(oldid != UUID.Zero && m_MaterialsRefCount.ContainsKey(oldid)) 632 faceEntry.MaterialID = id;
536 { 633
537 m_MaterialsRefCount[oldid]--; 634 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
538 if(m_MaterialsRefCount[oldid] <= 0) 635
539 { 636 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
540 m_Materials.Remove(oldid); 637 sop.Shape.TextureEntry = te.GetBytes();
541 m_MaterialsRefCount.Remove(oldid); 638 }
542 m_cache.Expire(oldid.ToString());
543 }
544 }
545 639
640 if(oldid != UUID.Zero)
641 RemoveMaterial(oldid);
642
643 lock(materialslock)
644 {
546 if(id != UUID.Zero) 645 if(id != UUID.Zero)
547 { 646 {
548 AssetBase asset = CacheMaterialAsAsset(id, agentID, mat, sop); 647 if (m_Materials.ContainsKey(id))
549 if(asset != null) 648 m_MaterialsRefCount[id]++;
649 else
550 { 650 {
551 ulong materialHash = (ulong)primLocalID << 32; 651 m_Materials[id] = newFaceMat;
552 if(face < 0) 652 m_MaterialsRefCount[id] = 1;
553 materialHash += 0xffffffff; 653 m_changed[newFaceMat] = Util.GetTimeStamp();
554 else
555 materialHash +=(ulong)face;
556
557 m_changes[materialHash] = asset;
558 m_changesTime[materialHash] = Util.GetTimeStampMS();
559 } 654 }
560 } 655 }
561 } 656 }
@@ -598,119 +693,39 @@ namespace OpenSim.Region.OptionalModules.Materials
598 return response; 693 return response;
599 } 694 }
600 695
601 private UUID getNewID(OSDMap mat) 696 private AssetBase MakeAsset(FaceMaterial fm, bool local)
602 {
603 // ugly and done twice but keep compatibility for now
604 Byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
605 using (var md5 = MD5.Create())
606 return new UUID(md5.ComputeHash(data), 0);
607 }
608
609 private AssetBase CacheMaterialAsAsset(UUID id, UUID agentID, OSDMap mat, SceneObjectPart sop)
610 { 697 {
698 // this are not true assets, should had never been...
611 AssetBase asset = null; 699 AssetBase asset = null;
612 lock (m_Materials) 700 string txt = fm.toLLSDxml();
613 { 701 byte[] data = System.Text.Encoding.ASCII.GetBytes(txt);
614 if (!m_Materials.ContainsKey(id))
615 {
616 m_Materials[id] = mat;
617 m_MaterialsRefCount[id] = 1;
618 702
619 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat)); 703 asset = new AssetBase(fm.ID, "llmaterial", (sbyte)OpenSimAssetType.Material, "00000000-0000-0000-0000-000000000000");
620 704 asset.Data = data;
621 // This asset might exist already, but it's ok to try to store it again 705 asset.Local = local;
622 string name = "Material " + ChooseMaterialName(mat, sop);
623 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
624 asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
625 asset.Data = data;
626 asset.Local = true;
627 m_cache.Cache(asset);
628 }
629 else
630 m_MaterialsRefCount[id]++;
631 }
632 return asset; 706 return asset;
633 } 707 }
634 708
635 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
636 {
637 UUID id;
638 // Material UUID = hash of the material's data.
639 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
640 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
641 using (var md5 = MD5.Create())
642 id = new UUID(md5.ComputeHash(data), 0);
643
644 lock (m_Materials)
645 {
646 if (!m_Materials.ContainsKey(id))
647 {
648 m_Materials[id] = mat;
649 m_MaterialsRefCount[id] = 1;
650
651 // This asset might exist already, but it's ok to try to store it again
652 string name = "Material " + ChooseMaterialName(mat, sop);
653 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
654 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
655 asset.Data = data;
656 m_scene.AssetService.Store(asset);
657 }
658 else
659 m_MaterialsRefCount[id]++;
660 }
661 return id;
662 }
663
664 /// <summary>
665 /// Use heuristics to choose a good name for the material.
666 /// </summary>
667 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
668 {
669 UUID normMap = mat["NormMap"].AsUUID();
670 if (normMap != UUID.Zero)
671 {
672 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
673 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
674 return asset.Name;
675 }
676
677 UUID specMap = mat["SpecMap"].AsUUID();
678 if (specMap != UUID.Zero)
679 {
680 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
681 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
682 return asset.Name;
683 }
684
685 if (sop.Name != "Primitive")
686 return sop.Name;
687
688 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
689 return sop.ParentGroup.Name;
690
691 return "";
692 }
693
694
695 public string RenderMaterialsGetCap(string request) 709 public string RenderMaterialsGetCap(string request)
696 { 710 {
697 OSDMap resp = new OSDMap(); 711 OSDMap resp = new OSDMap();
698 int matsCount = 0;
699 OSDArray allOsd = new OSDArray(); 712 OSDArray allOsd = new OSDArray();
713/*
714 // this violates all idea of caching and geting things only if needed, so disabled
700 715
716 int matsCount = 0;
701 lock (m_Materials) 717 lock (m_Materials)
702 { 718 {
703 foreach (KeyValuePair<UUID, OSDMap> kvp in m_Materials) 719 foreach (KeyValuePair<UUID, FaceMaterial> kvp in m_Materials)
704 { 720 {
705 OSDMap matMap = new OSDMap(); 721 OSDMap matMap = new OSDMap();
706
707 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes()); 722 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
708 matMap["Material"] = kvp.Value; 723 matMap["Material"] = kvp.Value.toOSD();
709 allOsd.Add(matMap); 724 allOsd.Add(matMap);
710 matsCount++; 725 matsCount++;
711 } 726 }
712 } 727 }
713 728*/
714 resp["Zipped"] = ZCompressOSD(allOsd, false); 729 resp["Zipped"] = ZCompressOSD(allOsd, false);
715 730
716 return OSDParser.SerializeLLSDXmlString(resp); 731 return OSDParser.SerializeLLSDXmlString(resp);
@@ -728,18 +743,6 @@ namespace OpenSim.Region.OptionalModules.Materials
728 } 743 }
729 } 744 }
730 745
731 /// <summary>
732 /// computes a UUID by hashing a OSD object
733 /// </summary>
734 /// <param name="osd"></param>
735 /// <returns></returns>
736 private static UUID HashOsd(OSD osd)
737 {
738 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
739 using (var md5 = MD5.Create())
740 return new UUID(md5.ComputeHash(data), 0);
741 }
742
743 public static OSD ZCompressOSD(OSD inOsd, bool useHeader) 746 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
744 { 747 {
745 OSD osd = null; 748 OSD osd = null;
@@ -761,7 +764,6 @@ namespace OpenSim.Region.OptionalModules.Materials
761 return osd; 764 return osd;
762 } 765 }
763 766
764
765 public static OSD ZDecompressBytesToOsd(byte[] input) 767 public static OSD ZDecompressBytesToOsd(byte[] input)
766 { 768 {
767 OSD osd = null; 769 OSD osd = null;
@@ -779,5 +781,67 @@ namespace OpenSim.Region.OptionalModules.Materials
779 781
780 return osd; 782 return osd;
781 } 783 }
784
785 public FaceMaterial GetMaterial(UUID ID)
786 {
787 FaceMaterial fm = null;
788 if(m_Materials.TryGetValue(ID, out fm))
789 return fm;
790 return null;
791 }
792
793 public FaceMaterial GetMaterialCopy(UUID ID)
794 {
795 FaceMaterial fm = null;
796 if(m_Materials.TryGetValue(ID, out fm))
797 return new FaceMaterial(fm);
798 return null;
799 }
800
801 public UUID AddNewMaterial(FaceMaterial fm)
802 {
803 if(fm.DiffuseAlphaMode == 1 && fm.NormalMapID == UUID.Zero && fm.SpecularMapID == UUID.Zero)
804 {
805 fm.ID = UUID.Zero;
806 return UUID.Zero;
807 }
808
809 fm.genID();
810 UUID id = fm.ID;
811 lock(materialslock)
812 {
813 if(m_Materials.ContainsKey(id))
814 m_MaterialsRefCount[id]++;
815 else
816 {
817 m_Materials[id] = fm;
818 m_MaterialsRefCount[id] = 1;
819 m_changed[fm] = Util.GetTimeStamp();
820 }
821 }
822 return id;
823 }
824
825 public void RemoveMaterial(UUID id)
826 {
827 if(id == UUID.Zero)
828 return;
829
830 lock(materialslock)
831 {
832 if(m_Materials.ContainsKey(id))
833 {
834 m_MaterialsRefCount[id]--;
835 if(m_MaterialsRefCount[id] <= 0)
836 {
837 FaceMaterial fm = m_Materials[id];
838 m_changed.Remove(fm);
839 m_Materials.Remove(id);
840 m_MaterialsRefCount.Remove(id);
841 m_cache.Expire(id.ToString());
842 }
843 }
844 }
845 }
782 } 846 }
783} 847}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 0124e32..014de69 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -124,6 +124,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
124 protected bool m_debuggerSafe = false; 124 protected bool m_debuggerSafe = false;
125 protected IUrlModule m_UrlModule = null; 125 protected IUrlModule m_UrlModule = null;
126 126
127 protected IMaterialsModule m_materialsModule = null;
128
127 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 129 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
128 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 130 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
129 protected int m_sleepMsOnSetTexture = 200; 131 protected int m_sleepMsOnSetTexture = 200;
@@ -306,6 +308,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
306 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 308 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
307 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 309 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
308 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); 310 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
311 m_materialsModule = m_ScriptEngine.World.RequestModuleInterface<IMaterialsModule>();
309 312
310 AsyncCommands = new AsyncCommandManager(m_ScriptEngine); 313 AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
311 } 314 }
@@ -2458,7 +2461,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2458 return; 2461 return;
2459 } 2462 }
2460 2463
2461
2462 Primitive.TextureEntry tex = part.Shape.Textures; 2464 Primitive.TextureEntry tex = part.Shape.Textures;
2463 int nsides = GetNumberOfSides(part); 2465 int nsides = GetNumberOfSides(part);
2464 2466
@@ -8910,6 +8912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8910 SceneObjectGroup parentgrp = part.ParentGroup; 8912 SceneObjectGroup parentgrp = part.ParentGroup;
8911 8913
8912 bool positionChanged = false; 8914 bool positionChanged = false;
8915 bool materialChanged = false;
8913 LSL_Vector currentPosition = GetPartLocalPos(part); 8916 LSL_Vector currentPosition = GetPartLocalPos(part);
8914 8917
8915 try 8918 try
@@ -10206,6 +10209,231 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10206 10209
10207 break; 10210 break;
10208 10211
10212 case ScriptBaseClass.PRIM_ALPHA_MODE:
10213 if (remain < 3)
10214 return new LSL_List();
10215
10216 try
10217 {
10218 face = rules.GetLSLIntegerItem(idx++);
10219 }
10220 catch(InvalidCastException)
10221 {
10222 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10223 return new LSL_List();
10224 }
10225
10226 int materialAlphaMode;
10227 try
10228 {
10229 materialAlphaMode = rules.GetLSLIntegerItem(idx++);
10230 }
10231 catch(InvalidCastException)
10232 {
10233 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10234 return new LSL_List();
10235 }
10236
10237 if(materialAlphaMode < 0 || materialAlphaMode > 3)
10238 {
10239 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be 0 to 3", rulesParsed, idx - idxStart - 1));
10240 return new LSL_List();
10241 }
10242
10243 int materialMaskCutoff;
10244 try
10245 {
10246 materialMaskCutoff = rules.GetLSLIntegerItem(idx++);
10247 }
10248 catch(InvalidCastException)
10249 {
10250 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10251 return new LSL_List();
10252 }
10253
10254 if(materialMaskCutoff < 0 || materialMaskCutoff > 255)
10255 {
10256 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ALPHA_MODE: arg #{1} - must be 0 to 255", rulesParsed, idx - idxStart - 1));
10257 return new LSL_List();
10258 }
10259
10260 materialChanged |= SetMaterialAlphaMode(part, face, materialAlphaMode, materialMaskCutoff);
10261 break;
10262
10263 case ScriptBaseClass.PRIM_NORMAL:
10264 if (remain < 5)
10265 return new LSL_List();
10266
10267 try
10268 {
10269 face = rules.GetLSLIntegerItem(idx++);
10270 }
10271 catch(InvalidCastException)
10272 {
10273 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10274 return new LSL_List();
10275 }
10276
10277 string mapname = rules.Data[idx++].ToString();
10278
10279 UUID mapID = ScriptUtils.GetAssetIdFromItemName(m_host, mapname, (int)AssetType.Texture);
10280 if (mapID == UUID.Zero)
10281 {
10282 if (!UUID.TryParse(mapname, out mapID))
10283 {
10284 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1));
10285 return new LSL_List();
10286 }
10287 }
10288
10289 LSL_Vector mnrepeat;
10290 try
10291 {
10292 mnrepeat = rules.GetVector3Item(idx++);
10293 }
10294 catch(InvalidCastException)
10295 {
10296 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
10297 return new LSL_List();
10298 }
10299
10300 LSL_Vector mnoffset;
10301 try
10302 {
10303 mnoffset = rules.GetVector3Item(idx++);
10304 }
10305 catch(InvalidCastException)
10306 {
10307 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
10308 return new LSL_List();
10309 }
10310
10311 LSL_Float mnrot;
10312 try
10313 {
10314 mnrot = rules.GetLSLFloatItem(idx++);
10315 }
10316 catch(InvalidCastException)
10317 {
10318 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NORMAL: arg #{1} - must be float", rulesParsed, idx - idxStart - 1));
10319 return new LSL_List();
10320 }
10321
10322 float repeatX = (float)Util.Clamp(mnrepeat.x,-100.0, 100.0);
10323 float repeatY = (float)Util.Clamp(mnrepeat.y,-100.0, 100.0);
10324 float offsetX = (float)Util.Clamp(mnoffset.x, 0, 1.0);
10325 float offsetY = (float)Util.Clamp(mnoffset.y, 0, 1.0);
10326
10327 materialChanged |= SetMaterialNormalMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, (float)mnrot);
10328 break;
10329
10330 case ScriptBaseClass.PRIM_SPECULAR:
10331 if (remain < 8)
10332 return new LSL_List();
10333
10334 try
10335 {
10336 face = rules.GetLSLIntegerItem(idx++);
10337 }
10338 catch(InvalidCastException)
10339 {
10340 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10341 return new LSL_List();
10342 }
10343
10344 string smapname = rules.Data[idx++].ToString();
10345
10346 UUID smapID = ScriptUtils.GetAssetIdFromItemName(m_host, smapname, (int)AssetType.Texture);
10347 if (smapID == UUID.Zero)
10348 {
10349 if (!UUID.TryParse(smapname, out smapID))
10350 {
10351 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be a UUID or a texture name on object inventory", rulesParsed, idx - idxStart - 1));
10352 return new LSL_List();
10353 }
10354 }
10355
10356 LSL_Vector msrepeat;
10357 try
10358 {
10359 msrepeat = rules.GetVector3Item(idx++);
10360 }
10361 catch(InvalidCastException)
10362 {
10363 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
10364 return new LSL_List();
10365 }
10366
10367 LSL_Vector msoffset;
10368 try
10369 {
10370 msoffset = rules.GetVector3Item(idx++);
10371 }
10372 catch(InvalidCastException)
10373 {
10374 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
10375 return new LSL_List();
10376 }
10377
10378 LSL_Float msrot;
10379 try
10380 {
10381 msrot = rules.GetLSLFloatItem(idx++);
10382 }
10383 catch(InvalidCastException)
10384 {
10385 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be float", rulesParsed, idx - idxStart - 1));
10386 return new LSL_List();
10387 }
10388
10389 LSL_Vector mscolor;
10390 try
10391 {
10392 mscolor = rules.GetVector3Item(idx++);
10393 }
10394 catch(InvalidCastException)
10395 {
10396 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be vector", rulesParsed, idx - idxStart - 1));
10397 return new LSL_List();
10398 }
10399
10400 LSL_Integer msgloss;
10401 try
10402 {
10403 msgloss = rules.GetLSLIntegerItem(idx++);
10404 }
10405 catch(InvalidCastException)
10406 {
10407 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10408 return new LSL_List();
10409 }
10410
10411 LSL_Integer msenv;
10412 try
10413 {
10414 msenv = rules.GetLSLIntegerItem(idx++);
10415 }
10416 catch(InvalidCastException)
10417 {
10418 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SPECULAR: arg #{1} - must be integer", rulesParsed, idx - idxStart - 1));
10419 return new LSL_List();
10420 }
10421
10422 float srepeatX = (float)Util.Clamp(msrepeat.x, -100.0, 100.0);
10423 float srepeatY = (float)Util.Clamp(msrepeat.y, -100.0, 100.0);
10424 float soffsetX = (float)Util.Clamp(msoffset.x, -1.0, 1.0);
10425 float soffsetY = (float)Util.Clamp(msoffset.y, -1.0, 1.0);
10426 byte colorR = (byte)(255.0 * Util.Clamp(mscolor.x, 0, 1.0) + 0.5);
10427 byte colorG = (byte)(255.0 * Util.Clamp(mscolor.y, 0, 1.0) + 0.5);
10428 byte colorB = (byte)(255.0 * Util.Clamp(mscolor.z, 0, 1.0) + 0.5);
10429 byte gloss = (byte)Util.Clamp((int)msgloss, 0, 255);
10430 byte env = (byte)Util.Clamp((int)msenv, 0, 255);
10431
10432 materialChanged |= SetMaterialSpecMap(part, face, smapID, srepeatX, srepeatY, soffsetX, soffsetY,
10433 (float)msrot, colorR, colorG, colorB, gloss, env);
10434
10435 break;
10436
10209 case ScriptBaseClass.PRIM_LINK_TARGET: 10437 case ScriptBaseClass.PRIM_LINK_TARGET:
10210 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 10438 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
10211 return new LSL_List(); 10439 return new LSL_List();
@@ -10242,11 +10470,194 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10242 part.ScheduleTerseUpdate(); 10470 part.ScheduleTerseUpdate();
10243 } 10471 }
10244 } 10472 }
10473 if(materialChanged)
10474 {
10475 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted)
10476 {
10477 part.TriggerScriptChangedEvent(Changed.TEXTURE);
10478 part.ScheduleFullUpdate();
10479 part.ParentGroup.HasGroupChanged = true;
10480 }
10481 }
10245 } 10482 }
10246 10483
10247 return new LSL_List(); 10484 return new LSL_List();
10248 } 10485 }
10249 10486
10487 protected bool SetMaterialAlphaMode(SceneObjectPart part, int face, int materialAlphaMode, int materialMaskCutoff)
10488 {
10489 if(m_materialsModule == null)
10490 return false;
10491
10492 int nsides = part.GetNumberOfSides();
10493
10494 if(face == ScriptBaseClass.ALL_SIDES)
10495 {
10496 bool changed = false;
10497 for(int i = 0; i < nsides; i++)
10498 changed |= SetFaceMaterialAlphaMode(part, i, materialAlphaMode, materialMaskCutoff);
10499 return changed;
10500 }
10501
10502 if( face >= 0 && face < nsides)
10503 return SetFaceMaterialAlphaMode(part, face, materialAlphaMode, materialMaskCutoff);
10504
10505 return false;
10506 }
10507
10508 protected bool SetFaceMaterialAlphaMode(SceneObjectPart part, int face, int materialAlphaMode, int materialMaskCutoff)
10509 {
10510 Primitive.TextureEntry tex = part.Shape.Textures;
10511 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
10512 if(texface == null)
10513 return false;
10514
10515 FaceMaterial mat = null;
10516 UUID oldid = texface.MaterialID;
10517
10518 if(oldid != UUID.Zero)
10519 mat = m_materialsModule.GetMaterialCopy(oldid);
10520
10521 if(mat == null)
10522 mat = new FaceMaterial();
10523
10524 mat.DiffuseAlphaMode = (byte)materialAlphaMode;
10525 mat.AlphaMaskCutoff = (byte)materialMaskCutoff;
10526
10527 UUID id = m_materialsModule.AddNewMaterial(mat);
10528 if(oldid == id)
10529 return false;
10530
10531 texface.MaterialID = id;
10532 part.Shape.TextureEntry = tex.GetBytes();
10533 m_materialsModule.RemoveMaterial(oldid);
10534 return true;
10535 }
10536
10537 protected bool SetMaterialNormalMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
10538 float offsetX, float offsetY, float rot)
10539 {
10540 if(m_materialsModule == null)
10541 return false;
10542
10543 int nsides = part.GetNumberOfSides();
10544
10545 if(face == ScriptBaseClass.ALL_SIDES)
10546 {
10547 bool changed = false;
10548 for(int i = 0; i < nsides; i++)
10549 changed |= SetFaceMaterialNormalMap(part, i, mapID, repeatX, repeatY, offsetX, offsetY, rot);
10550 return changed;
10551 }
10552
10553 if( face >= 0 && face < nsides)
10554 return SetFaceMaterialNormalMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, rot);
10555
10556 return false;
10557 }
10558
10559 protected bool SetFaceMaterialNormalMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
10560 float offsetX, float offsetY, float rot)
10561
10562 {
10563 Primitive.TextureEntry tex = part.Shape.Textures;
10564 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
10565 if(texface == null)
10566 return false;
10567
10568 FaceMaterial mat = null;
10569 UUID oldid = texface.MaterialID;
10570
10571 if(oldid != UUID.Zero)
10572 mat = m_materialsModule.GetMaterialCopy(oldid);
10573
10574 if(mat == null)
10575 mat = new FaceMaterial();
10576
10577 mat.NormalMapID = mapID;
10578 mat.NormalOffsetX = offsetX;
10579 mat.NormalOffsetY = offsetY;
10580 mat.NormalRepeatX = repeatX;
10581 mat.NormalRepeatY = repeatY;
10582 mat.NormalRotation = rot;
10583
10584 UUID id = m_materialsModule.AddNewMaterial(mat);
10585 if(oldid == id)
10586 return false;
10587
10588 texface.MaterialID = id;
10589 part.Shape.TextureEntry = tex.GetBytes();
10590 m_materialsModule.RemoveMaterial(oldid);
10591 return true;
10592 }
10593
10594 protected bool SetMaterialSpecMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
10595 float offsetX, float offsetY, float rot,
10596 byte colorR, byte colorG, byte colorB,
10597 byte gloss, byte env)
10598 {
10599 if(m_materialsModule == null)
10600 return false;
10601
10602 int nsides = part.GetNumberOfSides();
10603
10604 if(face == ScriptBaseClass.ALL_SIDES)
10605 {
10606 bool changed = false;
10607 for(int i = 0; i < nsides; i++)
10608 changed |= SetFaceMaterialSpecMap(part, i, mapID, repeatX, repeatY, offsetX, offsetY, rot,
10609 colorR, colorG, colorB, gloss, env);
10610 return changed;
10611 }
10612
10613 if( face >= 0 && face < nsides)
10614 return SetFaceMaterialSpecMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, rot,
10615 colorR, colorG, colorB, gloss, env);
10616
10617 return false;
10618 }
10619
10620 protected bool SetFaceMaterialSpecMap(SceneObjectPart part, int face, UUID mapID, float repeatX, float repeatY,
10621 float offsetX, float offsetY, float rot,
10622 byte colorR, byte colorG, byte colorB,
10623 byte gloss, byte env)
10624 {
10625 Primitive.TextureEntry tex = part.Shape.Textures;
10626 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
10627 if(texface == null)
10628 return false;
10629
10630 FaceMaterial mat = null;
10631 UUID oldid = texface.MaterialID;
10632
10633 if(oldid != UUID.Zero)
10634 mat = m_materialsModule.GetMaterialCopy(oldid);
10635
10636 if(mat == null)
10637 mat = new FaceMaterial();
10638
10639 mat.SpecularMapID = mapID;
10640 mat.SpecularOffsetX = offsetX;
10641 mat.SpecularOffsetY = offsetY;
10642 mat.SpecularRepeatX = repeatX;
10643 mat.SpecularRepeatY = repeatY;
10644 mat.SpecularRotation = rot;
10645 mat.SpecularLightColorR = colorR;
10646 mat.SpecularLightColorG = colorG;
10647 mat.SpecularLightColorB = colorB;
10648 mat.SpecularLightExponent = gloss;
10649 mat.EnvironmentIntensity = env;
10650
10651 UUID id = m_materialsModule.AddNewMaterial(mat);
10652 if(oldid == id)
10653 return false;
10654
10655 texface.MaterialID = id;
10656 part.Shape.TextureEntry = tex.GetBytes();
10657 m_materialsModule.RemoveMaterial(oldid);
10658 return true;
10659 }
10660
10250 protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed) 10661 protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed)
10251 { 10662 {
10252 int idx = 0; 10663 int idx = 0;
@@ -11363,107 +11774,83 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11363 return new LSL_List(); 11774 return new LSL_List();
11364 } 11775 }
11365 11776
11366/* 11777 private string GetMaterialTextureUUIDbyRights(UUID origID, SceneObjectPart part)
11367 private string filterTextureUUIDbyRights(UUID origID, SceneObjectPart part, bool checkTaskInventory, bool returnInvName)
11368 { 11778 {
11369 if(checkTaskInventory) 11779 if(World.Permissions.CanEditObject(m_host.ParentGroup.UUID, m_host.ParentGroup.RootPart.OwnerID))
11780 return origID.ToString();
11781
11782 lock(part.TaskInventory)
11370 { 11783 {
11371 lock (part.TaskInventory) 11784 foreach(KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
11372 { 11785 {
11373 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory) 11786 if(inv.Value.InvType == (int)InventoryType.Texture && inv.Value.AssetID == origID)
11374 { 11787 return origID.ToString();
11375 if (inv.Value.AssetID == origID)
11376 {
11377 if(inv.Value.InvType == (int)InventoryType.Texture)
11378 {
11379 if(returnInvName)
11380 return inv.Value.Name;
11381 else
11382 return origID.ToString();
11383 }
11384 else
11385 return UUID.Zero.ToString();
11386 }
11387 }
11388 } 11788 }
11389 } 11789 }
11390 11790
11391 if(World.Permissions.CanEditObject(m_host.ParentGroup.UUID, m_host.ParentGroup.RootPart.OwnerID))
11392 return origID.ToString();
11393
11394 return UUID.Zero.ToString(); 11791 return UUID.Zero.ToString();
11395 } 11792 }
11396*/ 11793
11397 private void getLSLFaceMaterial(ref LSL_List res, int code, SceneObjectPart part, Primitive.TextureEntryFace texface) 11794 private void getLSLFaceMaterial(ref LSL_List res, int code, SceneObjectPart part, Primitive.TextureEntryFace texface)
11398 { 11795 {
11399 UUID matID = texface.MaterialID; 11796 UUID matID = UUID.Zero;
11797 if(m_materialsModule != null)
11798 matID = texface.MaterialID;
11799
11400 if(matID != UUID.Zero) 11800 if(matID != UUID.Zero)
11401 { 11801 {
11402 AssetBase MatAsset = World.AssetService.Get(matID.ToString()); 11802 FaceMaterial mat = m_materialsModule.GetMaterial(matID);
11403 if(MatAsset != null) 11803 if(mat != null)
11404 { 11804 {
11405 Byte[] data = MatAsset.Data; 11805 if(code == ScriptBaseClass.PRIM_NORMAL)
11406 OSDMap osdmat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
11407 if(osdmat != null && osdmat.ContainsKey("NormMap"))
11408 { 11806 {
11409 string mapIDstr; 11807 res.Add(new LSL_String(GetMaterialTextureUUIDbyRights(mat.NormalMapID, part)));
11410 FaceMaterial mat = new FaceMaterial(matID, osdmat); 11808 res.Add(new LSL_Vector(mat.NormalRepeatX, mat.NormalRepeatY, 0));
11411 if(code == ScriptBaseClass.PRIM_NORMAL) 11809 res.Add(new LSL_Vector(mat.NormalOffsetX, mat.NormalOffsetY, 0));
11412 { 11810 res.Add(new LSL_Float(mat.NormalRotation));
11413// mapIDstr = filterTextureUUIDbyRights(mat.NormalMapID, part, true, false);
11414 mapIDstr = mat.NormalMapID.ToString();
11415 res.Add(new LSL_String(mapIDstr));
11416 res.Add(new LSL_Vector(mat.NormalRepeatX, mat.NormalRepeatY, 0));
11417 res.Add(new LSL_Vector(mat.NormalOffsetX, mat.NormalOffsetY, 0));
11418 res.Add(new LSL_Float(mat.NormalRotation));
11419 }
11420 else if(code == ScriptBaseClass.PRIM_SPECULAR )
11421 {
11422// mapIDstr = filterTextureUUIDbyRights(mat.SpecularMapID, part, true, false);
11423 const float colorScale = 1.0f/255f;
11424 mapIDstr = mat.SpecularMapID.ToString();
11425 res.Add(new LSL_String(mapIDstr));
11426 res.Add(new LSL_Vector(mat.SpecularRepeatX, mat.SpecularRepeatY, 0));
11427 res.Add(new LSL_Vector(mat.SpecularOffsetX, mat.SpecularOffsetY, 0));
11428 res.Add(new LSL_Float(mat.SpecularRotation));
11429 res.Add(new LSL_Vector(mat.SpecularLightColor.R * colorScale,
11430 mat.SpecularLightColor.G * colorScale,
11431 mat.SpecularLightColor.B * colorScale));
11432 res.Add(new LSL_Integer(mat.SpecularLightExponent));
11433 res.Add(new LSL_Integer(mat.EnvironmentIntensity));
11434 }
11435 else if(code == ScriptBaseClass.PRIM_ALPHA_MODE)
11436 {
11437 res.Add(new LSL_Integer(mat.DiffuseAlphaMode));
11438 res.Add(new LSL_Integer(mat.AlphaMaskCutoff));
11439 }
11440 return;
11441 } 11811 }
11442 } 11812 else if(code == ScriptBaseClass.PRIM_SPECULAR)
11443 matID = UUID.Zero;
11444 }
11445 if(matID == UUID.Zero)
11446 {
11447 if(code == (int)ScriptBaseClass.PRIM_NORMAL || code == (int)ScriptBaseClass.PRIM_SPECULAR )
11448 {
11449 res.Add(new LSL_String(UUID.Zero.ToString()));
11450 res.Add(new LSL_Vector(1.0, 1.0, 0));
11451 res.Add(new LSL_Vector(0, 0, 0));
11452 res.Add(new LSL_Float(0));
11453
11454 if(code == (int)ScriptBaseClass.PRIM_SPECULAR)
11455 { 11813 {
11456 res.Add(new LSL_Vector(1.0, 1.0, 1.0)); 11814 const float colorScale = 1.0f / 255f;
11457 res.Add(new LSL_Integer(51)); 11815 res.Add(new LSL_String(GetMaterialTextureUUIDbyRights(mat.SpecularMapID, part)));
11458 res.Add(new LSL_Integer(0)); 11816 res.Add(new LSL_Vector(mat.SpecularRepeatX, mat.SpecularRepeatY, 0));
11817 res.Add(new LSL_Vector(mat.SpecularOffsetX, mat.SpecularOffsetY, 0));
11818 res.Add(new LSL_Float(mat.SpecularRotation));
11819 res.Add(new LSL_Vector(mat.SpecularLightColorR * colorScale,
11820 mat.SpecularLightColorG * colorScale,
11821 mat.SpecularLightColorB * colorScale));
11822 res.Add(new LSL_Integer(mat.SpecularLightExponent));
11823 res.Add(new LSL_Integer(mat.EnvironmentIntensity));
11824 }
11825 else if(code == ScriptBaseClass.PRIM_ALPHA_MODE)
11826 {
11827 res.Add(new LSL_Integer(mat.DiffuseAlphaMode));
11828 res.Add(new LSL_Integer(mat.AlphaMaskCutoff));
11459 } 11829 }
11830 return;
11460 } 11831 }
11461 else if(code == (int)ScriptBaseClass.PRIM_ALPHA_MODE) 11832 }
11833
11834 // material not found
11835 if(code == (int)ScriptBaseClass.PRIM_NORMAL || code == (int)ScriptBaseClass.PRIM_SPECULAR)
11836 {
11837 res.Add(new LSL_String(UUID.Zero.ToString()));
11838 res.Add(new LSL_Vector(1.0, 1.0, 0));
11839 res.Add(new LSL_Vector(0, 0, 0));
11840 res.Add(new LSL_Float(0));
11841
11842 if(code == (int)ScriptBaseClass.PRIM_SPECULAR)
11462 { 11843 {
11463 res.Add(new LSL_Integer(1)); 11844 res.Add(new LSL_Vector(1.0, 1.0, 1.0));
11845 res.Add(new LSL_Integer(51));
11464 res.Add(new LSL_Integer(0)); 11846 res.Add(new LSL_Integer(0));
11465 } 11847 }
11466 } 11848 }
11849 else if(code == (int)ScriptBaseClass.PRIM_ALPHA_MODE)
11850 {
11851 res.Add(new LSL_Integer(1));
11852 res.Add(new LSL_Integer(0));
11853 }
11467 } 11854 }
11468 11855
11469 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 11856 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
diff --git a/opensim/Region/Framework/Interfaces/IMaterialsModule.cs b/opensim/Region/Framework/Interfaces/IMaterialsModule.cs
new file mode 100644
index 0000000..3f25874
--- /dev/null
+++ b/opensim/Region/Framework/Interfaces/IMaterialsModule.cs
@@ -0,0 +1,41 @@
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
28using System;
29using OpenSim.Region.Framework.Scenes;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 public interface IMaterialsModule
35 {
36 FaceMaterial GetMaterial(UUID ID);
37 FaceMaterial GetMaterialCopy(UUID ID);
38 UUID AddNewMaterial(FaceMaterial fm);
39 void RemoveMaterial(UUID id);
40 }
41}