diff options
Diffstat (limited to '')
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Text; |
30 | using System.Runtime.InteropServices; | ||
31 | using System.Security.Cryptography; // for computing md5 hash | ||
32 | using OpenSim.Framework; | ||
30 | using OpenMetaverse; | 33 | using OpenMetaverse; |
31 | using OpenMetaverse.StructuredData; | 34 | using OpenMetaverse.StructuredData; |
32 | using OpenSim.Framework; | ||
33 | 35 | ||
34 | namespace OpenSim.Region.Framework.Scenes | 36 | namespace 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 | ||
47 | using Ionic.Zlib; | 47 | using 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 | |||
55 | namespace OpenSim.Region.OptionalModules.Materials | 49 | namespace 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 | |||
28 | using System; | ||
29 | using OpenSim.Region.Framework.Scenes; | ||
30 | using OpenMetaverse; | ||
31 | |||
32 | namespace 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 | } | ||