diff options
author | Melanie | 2012-08-29 03:31:13 +0100 |
---|---|---|
committer | Melanie | 2012-08-29 03:31:13 +0100 |
commit | 899337b4a0584ce2371c3bfcc44387d0f090b792 (patch) | |
tree | 3a3e862951a85889c3c5762d6d30b5dd80868864 /OpenSim/Region/CoreModules/Scripting | |
parent | Merge branch 'master' into careminster (diff) | |
parent | implementing rule tracking (diff) | |
download | opensim-SC-899337b4a0584ce2371c3bfcc44387d0f090b792.zip opensim-SC-899337b4a0584ce2371c3bfcc44387d0f090b792.tar.gz opensim-SC-899337b4a0584ce2371c3bfcc44387d0f090b792.tar.bz2 opensim-SC-899337b4a0584ce2371c3bfcc44387d0f090b792.tar.xz |
Merge branch 'master' into careminster
Conflicts:
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting')
4 files changed, 410 insertions, 70 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 18bd018..13b7498 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | |||
@@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
49 | public const int DISP_EXPIRE = 1; | 49 | public const int DISP_EXPIRE = 1; |
50 | public const int DISP_TEMP = 2; | 50 | public const int DISP_TEMP = 2; |
51 | 51 | ||
52 | /// <summary> | ||
53 | /// If true then where possible dynamic textures are reused. | ||
54 | /// </summary> | ||
55 | public bool ReuseTextures { get; set; } | ||
56 | |||
52 | private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); | 57 | private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); |
53 | 58 | ||
54 | private Dictionary<string, IDynamicTextureRender> RenderPlugins = | 59 | private Dictionary<string, IDynamicTextureRender> RenderPlugins = |
@@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
56 | 61 | ||
57 | private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); | 62 | private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); |
58 | 63 | ||
64 | /// <summary> | ||
65 | /// Record dynamic textures that we can reuse for a given data and parameter combination rather than | ||
66 | /// regenerate. | ||
67 | /// </summary> | ||
68 | /// <remarks> | ||
69 | /// Key is string.Format("{0}{1}", data | ||
70 | /// </remarks> | ||
71 | private Cache m_reuseableDynamicTextures; | ||
72 | |||
59 | #region IDynamicTextureManager Members | 73 | #region IDynamicTextureManager Members |
60 | 74 | ||
61 | public void RegisterRender(string handleType, IDynamicTextureRender render) | 75 | public void RegisterRender(string handleType, IDynamicTextureRender render) |
@@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
71 | /// </summary> | 85 | /// </summary> |
72 | /// <param name="id"></param> | 86 | /// <param name="id"></param> |
73 | /// <param name="data"></param> | 87 | /// <param name="data"></param> |
74 | public void ReturnData(UUID id, byte[] data) | 88 | /// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param> |
89 | public void ReturnData(UUID id, byte[] data, bool isReuseable) | ||
75 | { | 90 | { |
76 | DynamicTextureUpdater updater = null; | 91 | DynamicTextureUpdater updater = null; |
77 | 92 | ||
@@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
88 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) | 103 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) |
89 | { | 104 | { |
90 | Scene scene = RegisteredScenes[updater.SimUUID]; | 105 | Scene scene = RegisteredScenes[updater.SimUUID]; |
91 | updater.DataReceived(data, scene); | 106 | UUID newTextureID = updater.DataReceived(data, scene); |
107 | |||
108 | if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture) | ||
109 | m_reuseableDynamicTextures.Store( | ||
110 | GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID); | ||
92 | } | 111 | } |
93 | } | 112 | } |
94 | 113 | ||
@@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
169 | { | 188 | { |
170 | if (RenderPlugins.ContainsKey(contentType)) | 189 | if (RenderPlugins.ContainsKey(contentType)) |
171 | { | 190 | { |
191 | // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire | ||
192 | // them. | ||
193 | if (ReuseTextures) | ||
194 | disp = disp & ~DISP_EXPIRE; | ||
195 | |||
172 | DynamicTextureUpdater updater = new DynamicTextureUpdater(); | 196 | DynamicTextureUpdater updater = new DynamicTextureUpdater(); |
173 | updater.SimUUID = simID; | 197 | updater.SimUUID = simID; |
174 | updater.PrimID = primID; | 198 | updater.PrimID = primID; |
@@ -183,21 +207,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
183 | updater.Url = "Local image"; | 207 | updater.Url = "Local image"; |
184 | updater.Disp = disp; | 208 | updater.Disp = disp; |
185 | 209 | ||
186 | lock (Updaters) | 210 | object reusableTextureUUID = null; |
211 | |||
212 | if (ReuseTextures) | ||
213 | reusableTextureUUID | ||
214 | = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams)); | ||
215 | |||
216 | // We cannot reuse a dynamic texture if the data is going to be blended with something already there. | ||
217 | if (reusableTextureUUID == null || updater.BlendWithOldTexture) | ||
187 | { | 218 | { |
188 | if (!Updaters.ContainsKey(updater.UpdaterID)) | 219 | lock (Updaters) |
189 | { | 220 | { |
190 | Updaters.Add(updater.UpdaterID, updater); | 221 | if (!Updaters.ContainsKey(updater.UpdaterID)) |
222 | { | ||
223 | Updaters.Add(updater.UpdaterID, updater); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | // No need to add to updaters as the texture is always the same. Not that this functionality | ||
232 | // apppears to be implemented anyway. | ||
233 | if (RegisteredScenes.ContainsKey(updater.SimUUID)) | ||
234 | { | ||
235 | SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID); | ||
236 | |||
237 | if (part != null) | ||
238 | updater.UpdatePart(part, (UUID)reusableTextureUUID); | ||
191 | } | 239 | } |
192 | } | 240 | } |
193 | 241 | ||
194 | RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); | ||
195 | return updater.UpdaterID; | 242 | return updater.UpdaterID; |
196 | } | 243 | } |
197 | 244 | ||
198 | return UUID.Zero; | 245 | return UUID.Zero; |
199 | } | 246 | } |
200 | 247 | ||
248 | private string GenerateReusableTextureKey(string data, string extraParams) | ||
249 | { | ||
250 | return string.Format("{0}{1}", data, extraParams); | ||
251 | } | ||
252 | |||
201 | public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, | 253 | public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, |
202 | out double xSize, out double ySize) | 254 | out double xSize, out double ySize) |
203 | { | 255 | { |
@@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
224 | 276 | ||
225 | public void PostInitialise() | 277 | public void PostInitialise() |
226 | { | 278 | { |
279 | // ReuseTextures = true; | ||
280 | if (ReuseTextures) | ||
281 | { | ||
282 | m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); | ||
283 | m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); | ||
284 | } | ||
227 | } | 285 | } |
228 | 286 | ||
229 | public void Close() | 287 | public void Close() |
@@ -269,9 +327,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
269 | } | 327 | } |
270 | 328 | ||
271 | /// <summary> | 329 | /// <summary> |
330 | /// Update the given part with the new texture. | ||
331 | /// </summary> | ||
332 | /// <returns> | ||
333 | /// The old texture UUID. | ||
334 | /// </returns> | ||
335 | public UUID UpdatePart(SceneObjectPart part, UUID textureID) | ||
336 | { | ||
337 | UUID oldID; | ||
338 | |||
339 | lock (part) | ||
340 | { | ||
341 | // mostly keep the values from before | ||
342 | Primitive.TextureEntry tmptex = part.Shape.Textures; | ||
343 | |||
344 | // FIXME: Need to return the appropriate ID if only a single face is replaced. | ||
345 | oldID = tmptex.DefaultTexture.TextureID; | ||
346 | |||
347 | if (Face == ALL_SIDES) | ||
348 | { | ||
349 | oldID = tmptex.DefaultTexture.TextureID; | ||
350 | tmptex.DefaultTexture.TextureID = textureID; | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | try | ||
355 | { | ||
356 | Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); | ||
357 | texface.TextureID = textureID; | ||
358 | tmptex.FaceTextures[Face] = texface; | ||
359 | } | ||
360 | catch (Exception) | ||
361 | { | ||
362 | tmptex.DefaultTexture.TextureID = textureID; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | // I'm pretty sure we always want to force this to true | ||
367 | // I'm pretty sure noone whats to set fullbright true if it wasn't true before. | ||
368 | // tmptex.DefaultTexture.Fullbright = true; | ||
369 | |||
370 | part.UpdateTextureEntry(tmptex.GetBytes()); | ||
371 | } | ||
372 | |||
373 | return oldID; | ||
374 | } | ||
375 | |||
376 | /// <summary> | ||
272 | /// Called once new texture data has been received for this updater. | 377 | /// Called once new texture data has been received for this updater. |
273 | /// </summary> | 378 | /// </summary> |
274 | public void DataReceived(byte[] data, Scene scene) | 379 | /// <param name="data"></param> |
380 | /// <param name="scene"></param> | ||
381 | /// <param name="isReuseable">True if the data given is reuseable.</param> | ||
382 | /// <returns>The asset UUID given to the incoming data.</returns> | ||
383 | public UUID DataReceived(byte[] data, Scene scene) | ||
275 | { | 384 | { |
276 | SceneObjectPart part = scene.GetSceneObjectPart(PrimID); | 385 | SceneObjectPart part = scene.GetSceneObjectPart(PrimID); |
277 | 386 | ||
@@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
281 | String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); | 390 | String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); |
282 | scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, | 391 | scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, |
283 | 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); | 392 | 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); |
284 | return; | 393 | |
394 | return UUID.Zero; | ||
285 | } | 395 | } |
286 | 396 | ||
287 | byte[] assetData = null; | 397 | byte[] assetData = null; |
@@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture | |||
323 | cacheLayerDecode = null; | 433 | cacheLayerDecode = null; |
324 | } | 434 | } |
325 | 435 | ||
326 | UUID oldID = UUID.Zero; | 436 | UUID oldID = UpdatePart(part, asset.FullID); |
327 | |||
328 | lock (part) | ||
329 | { | ||
330 | // mostly keep the values from before | ||
331 | Primitive.TextureEntry tmptex = part.Shape.Textures; | ||
332 | |||
333 | // remove the old asset from the cache | ||
334 | oldID = tmptex.DefaultTexture.TextureID; | ||
335 | |||
336 | if (Face == ALL_SIDES) | ||
337 | { | ||
338 | tmptex.DefaultTexture.TextureID = asset.FullID; | ||
339 | } | ||
340 | else | ||
341 | { | ||
342 | try | ||
343 | { | ||
344 | Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); | ||
345 | texface.TextureID = asset.FullID; | ||
346 | tmptex.FaceTextures[Face] = texface; | ||
347 | } | ||
348 | catch (Exception) | ||
349 | { | ||
350 | tmptex.DefaultTexture.TextureID = asset.FullID; | ||
351 | } | ||
352 | } | ||
353 | |||
354 | // I'm pretty sure we always want to force this to true | ||
355 | // I'm pretty sure noone whats to set fullbright true if it wasn't true before. | ||
356 | // tmptex.DefaultTexture.Fullbright = true; | ||
357 | |||
358 | part.UpdateTextureEntry(tmptex.GetBytes()); | ||
359 | } | ||
360 | 437 | ||
361 | if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) | 438 | if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) |
362 | { | 439 | { |
363 | if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); | 440 | if (oldAsset == null) |
441 | oldAsset = scene.AssetService.Get(oldID.ToString()); | ||
442 | |||
364 | if (oldAsset != null) | 443 | if (oldAsset != null) |
365 | { | 444 | { |
366 | if (oldAsset.Temporary == true) | 445 | if (oldAsset.Temporary) |
367 | { | 446 | { |
368 | scene.AssetService.Delete(oldID.ToString()); | 447 | scene.AssetService.Delete(oldID.ToString()); |
369 | } | 448 | } |
370 | } | 449 | } |
371 | } | 450 | } |
451 | |||
452 | return asset.FullID; | ||
372 | } | 453 | } |
373 | 454 | ||
374 | private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) | 455 | private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) |
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 6f83948..2b3a0f2 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs | |||
@@ -67,12 +67,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
67 | return true; | 67 | return true; |
68 | } | 68 | } |
69 | 69 | ||
70 | // public bool AlwaysIdenticalConversion(string bodyData, string extraParams) | ||
71 | // { | ||
72 | // // We don't support conversion of body data. | ||
73 | // return false; | ||
74 | // } | ||
75 | |||
70 | public byte[] ConvertUrl(string url, string extraParams) | 76 | public byte[] ConvertUrl(string url, string extraParams) |
71 | { | 77 | { |
72 | return null; | 78 | return null; |
73 | } | 79 | } |
74 | 80 | ||
75 | public byte[] ConvertStream(Stream data, string extraParams) | 81 | public byte[] ConvertData(string bodyData, string extraParams) |
76 | { | 82 | { |
77 | return null; | 83 | return null; |
78 | } | 84 | } |
@@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL | |||
236 | stream.Close(); | 242 | stream.Close(); |
237 | } | 243 | } |
238 | } | 244 | } |
245 | |||
239 | m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", | 246 | m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", |
240 | imageJ2000.Length, state.RequestID); | 247 | imageJ2000.Length, state.RequestID); |
241 | m_textureManager.ReturnData(state.RequestID, imageJ2000); | 248 | |
249 | m_textureManager.ReturnData(state.RequestID, imageJ2000, false); | ||
242 | } | 250 | } |
243 | 251 | ||
244 | #region Nested type: RequestState | 252 | #region Nested type: RequestState |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 9787c8c..b50c0bd 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs | |||
@@ -45,31 +45,250 @@ using OpenSim.Tests.Common.Mock; | |||
45 | namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests | 45 | namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests |
46 | { | 46 | { |
47 | [TestFixture] | 47 | [TestFixture] |
48 | public class VectorRenderModuleTests | 48 | public class VectorRenderModuleTests : OpenSimTestCase |
49 | { | 49 | { |
50 | Scene m_scene; | ||
51 | DynamicTextureModule m_dtm; | ||
52 | VectorRenderModule m_vrm; | ||
53 | |||
54 | private void SetupScene(bool reuseTextures) | ||
55 | { | ||
56 | m_scene = new SceneHelpers().SetupScene(); | ||
57 | |||
58 | m_dtm = new DynamicTextureModule(); | ||
59 | m_dtm.ReuseTextures = reuseTextures; | ||
60 | |||
61 | m_vrm = new VectorRenderModule(); | ||
62 | |||
63 | SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); | ||
64 | } | ||
65 | |||
50 | [Test] | 66 | [Test] |
51 | public void TestDraw() | 67 | public void TestDraw() |
52 | { | 68 | { |
53 | TestHelpers.InMethod(); | 69 | TestHelpers.InMethod(); |
54 | 70 | ||
55 | Scene scene = new SceneHelpers().SetupScene(); | 71 | SetupScene(false); |
56 | DynamicTextureModule dtm = new DynamicTextureModule(); | 72 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); |
57 | VectorRenderModule vrm = new VectorRenderModule(); | ||
58 | SceneHelpers.SetupSceneModules(scene, dtm, vrm); | ||
59 | |||
60 | SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); | ||
61 | UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | 73 | UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; |
62 | 74 | ||
63 | dtm.AddDynamicTextureData( | 75 | m_dtm.AddDynamicTextureData( |
64 | scene.RegionInfo.RegionID, | 76 | m_scene.RegionInfo.RegionID, |
65 | so.UUID, | 77 | so.UUID, |
66 | vrm.GetContentType(), | 78 | m_vrm.GetContentType(), |
67 | "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", | 79 | "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", |
68 | "", | 80 | "", |
69 | 0); | 81 | 0); |
70 | 82 | ||
83 | Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
84 | } | ||
85 | |||
86 | [Test] | ||
87 | public void TestRepeatSameDraw() | ||
88 | { | ||
89 | TestHelpers.InMethod(); | ||
90 | |||
91 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
92 | |||
93 | SetupScene(false); | ||
94 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
95 | |||
96 | m_dtm.AddDynamicTextureData( | ||
97 | m_scene.RegionInfo.RegionID, | ||
98 | so.UUID, | ||
99 | m_vrm.GetContentType(), | ||
100 | dtText, | ||
101 | "", | ||
102 | 0); | ||
103 | |||
104 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
105 | |||
106 | m_dtm.AddDynamicTextureData( | ||
107 | m_scene.RegionInfo.RegionID, | ||
108 | so.UUID, | ||
109 | m_vrm.GetContentType(), | ||
110 | dtText, | ||
111 | "", | ||
112 | 0); | ||
113 | |||
114 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
115 | } | ||
116 | |||
117 | [Test] | ||
118 | public void TestRepeatSameDrawDifferentExtraParams() | ||
119 | { | ||
120 | TestHelpers.InMethod(); | ||
121 | |||
122 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
123 | |||
124 | SetupScene(false); | ||
125 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
126 | |||
127 | m_dtm.AddDynamicTextureData( | ||
128 | m_scene.RegionInfo.RegionID, | ||
129 | so.UUID, | ||
130 | m_vrm.GetContentType(), | ||
131 | dtText, | ||
132 | "", | ||
133 | 0); | ||
134 | |||
135 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
136 | |||
137 | m_dtm.AddDynamicTextureData( | ||
138 | m_scene.RegionInfo.RegionID, | ||
139 | so.UUID, | ||
140 | m_vrm.GetContentType(), | ||
141 | dtText, | ||
142 | "alpha:250", | ||
143 | 0); | ||
144 | |||
145 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
146 | } | ||
147 | |||
148 | [Test] | ||
149 | public void TestRepeatSameDrawContainingImage() | ||
150 | { | ||
151 | TestHelpers.InMethod(); | ||
152 | |||
153 | string dtText | ||
154 | = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; | ||
155 | |||
156 | SetupScene(false); | ||
157 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
158 | |||
159 | m_dtm.AddDynamicTextureData( | ||
160 | m_scene.RegionInfo.RegionID, | ||
161 | so.UUID, | ||
162 | m_vrm.GetContentType(), | ||
163 | dtText, | ||
164 | "", | ||
165 | 0); | ||
166 | |||
167 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
168 | |||
169 | m_dtm.AddDynamicTextureData( | ||
170 | m_scene.RegionInfo.RegionID, | ||
171 | so.UUID, | ||
172 | m_vrm.GetContentType(), | ||
173 | dtText, | ||
174 | "", | ||
175 | 0); | ||
176 | |||
177 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
178 | } | ||
179 | |||
180 | [Test] | ||
181 | public void TestDrawReusingTexture() | ||
182 | { | ||
183 | TestHelpers.InMethod(); | ||
184 | |||
185 | SetupScene(true); | ||
186 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
187 | UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
188 | |||
189 | m_dtm.AddDynamicTextureData( | ||
190 | m_scene.RegionInfo.RegionID, | ||
191 | so.UUID, | ||
192 | m_vrm.GetContentType(), | ||
193 | "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", | ||
194 | "", | ||
195 | 0); | ||
71 | 196 | ||
72 | Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | 197 | Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); |
73 | } | 198 | } |
199 | |||
200 | [Test] | ||
201 | public void TestRepeatSameDrawReusingTexture() | ||
202 | { | ||
203 | TestHelpers.InMethod(); | ||
204 | |||
205 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
206 | |||
207 | SetupScene(true); | ||
208 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
209 | |||
210 | m_dtm.AddDynamicTextureData( | ||
211 | m_scene.RegionInfo.RegionID, | ||
212 | so.UUID, | ||
213 | m_vrm.GetContentType(), | ||
214 | dtText, | ||
215 | "", | ||
216 | 0); | ||
217 | |||
218 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
219 | |||
220 | m_dtm.AddDynamicTextureData( | ||
221 | m_scene.RegionInfo.RegionID, | ||
222 | so.UUID, | ||
223 | m_vrm.GetContentType(), | ||
224 | dtText, | ||
225 | "", | ||
226 | 0); | ||
227 | |||
228 | Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
229 | } | ||
230 | |||
231 | [Test] | ||
232 | public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() | ||
233 | { | ||
234 | TestHelpers.InMethod(); | ||
235 | |||
236 | string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; | ||
237 | |||
238 | SetupScene(true); | ||
239 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
240 | |||
241 | m_dtm.AddDynamicTextureData( | ||
242 | m_scene.RegionInfo.RegionID, | ||
243 | so.UUID, | ||
244 | m_vrm.GetContentType(), | ||
245 | dtText, | ||
246 | "", | ||
247 | 0); | ||
248 | |||
249 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
250 | |||
251 | m_dtm.AddDynamicTextureData( | ||
252 | m_scene.RegionInfo.RegionID, | ||
253 | so.UUID, | ||
254 | m_vrm.GetContentType(), | ||
255 | dtText, | ||
256 | "alpha:250", | ||
257 | 0); | ||
258 | |||
259 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
260 | } | ||
261 | |||
262 | [Test] | ||
263 | public void TestRepeatSameDrawContainingImageReusingTexture() | ||
264 | { | ||
265 | TestHelpers.InMethod(); | ||
266 | |||
267 | string dtText | ||
268 | = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; | ||
269 | |||
270 | SetupScene(true); | ||
271 | SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); | ||
272 | |||
273 | m_dtm.AddDynamicTextureData( | ||
274 | m_scene.RegionInfo.RegionID, | ||
275 | so.UUID, | ||
276 | m_vrm.GetContentType(), | ||
277 | dtText, | ||
278 | "", | ||
279 | 0); | ||
280 | |||
281 | UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; | ||
282 | |||
283 | m_dtm.AddDynamicTextureData( | ||
284 | m_scene.RegionInfo.RegionID, | ||
285 | so.UUID, | ||
286 | m_vrm.GetContentType(), | ||
287 | dtText, | ||
288 | "", | ||
289 | 0); | ||
290 | |||
291 | Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); | ||
292 | } | ||
74 | } | 293 | } |
75 | } \ No newline at end of file | 294 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 05eaaec..f687646 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -30,6 +30,7 @@ using System.Drawing; | |||
30 | using System.Drawing.Imaging; | 30 | using System.Drawing.Imaging; |
31 | using System.Globalization; | 31 | using System.Globalization; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Linq; | ||
33 | using System.Net; | 34 | using System.Net; |
34 | using Nini.Config; | 35 | using Nini.Config; |
35 | using OpenMetaverse; | 36 | using OpenMetaverse; |
@@ -47,7 +48,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
47 | { | 48 | { |
48 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 49 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
49 | 50 | ||
50 | private string m_name = "VectorRenderModule"; | ||
51 | private Scene m_scene; | 51 | private Scene m_scene; |
52 | private IDynamicTextureManager m_textureManager; | 52 | private IDynamicTextureManager m_textureManager; |
53 | private Graphics m_graph; | 53 | private Graphics m_graph; |
@@ -61,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
61 | 61 | ||
62 | public string GetContentType() | 62 | public string GetContentType() |
63 | { | 63 | { |
64 | return ("vector"); | 64 | return "vector"; |
65 | } | 65 | } |
66 | 66 | ||
67 | public string GetName() | 67 | public string GetName() |
68 | { | 68 | { |
69 | return m_name; | 69 | return Name; |
70 | } | 70 | } |
71 | 71 | ||
72 | public bool SupportsAsynchronous() | 72 | public bool SupportsAsynchronous() |
@@ -74,14 +74,26 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
74 | return true; | 74 | return true; |
75 | } | 75 | } |
76 | 76 | ||
77 | // public bool AlwaysIdenticalConversion(string bodyData, string extraParams) | ||
78 | // { | ||
79 | // string[] lines = GetLines(bodyData); | ||
80 | // return lines.Any((str, r) => str.StartsWith("Image")); | ||
81 | // } | ||
82 | |||
77 | public byte[] ConvertUrl(string url, string extraParams) | 83 | public byte[] ConvertUrl(string url, string extraParams) |
78 | { | 84 | { |
79 | return null; | 85 | return null; |
80 | } | 86 | } |
81 | 87 | ||
82 | public byte[] ConvertStream(Stream data, string extraParams) | 88 | public byte[] ConvertData(string bodyData, string extraParams) |
83 | { | 89 | { |
84 | return null; | 90 | bool reuseable; |
91 | return Draw(bodyData, extraParams, out reuseable); | ||
92 | } | ||
93 | |||
94 | private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable) | ||
95 | { | ||
96 | return Draw(bodyData, extraParams, out reuseable); | ||
85 | } | 97 | } |
86 | 98 | ||
87 | public bool AsyncConvertUrl(UUID id, string url, string extraParams) | 99 | public bool AsyncConvertUrl(UUID id, string url, string extraParams) |
@@ -91,7 +103,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
91 | 103 | ||
92 | public bool AsyncConvertData(UUID id, string bodyData, string extraParams) | 104 | public bool AsyncConvertData(UUID id, string bodyData, string extraParams) |
93 | { | 105 | { |
94 | Draw(bodyData, id, extraParams); | 106 | // XXX: This isn't actually being done asynchronously! |
107 | bool reuseable; | ||
108 | byte[] data = ConvertData(bodyData, extraParams, out reuseable); | ||
109 | |||
110 | m_textureManager.ReturnData(id, data, reuseable); | ||
111 | |||
95 | return true; | 112 | return true; |
96 | } | 113 | } |
97 | 114 | ||
@@ -152,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
152 | 169 | ||
153 | public string Name | 170 | public string Name |
154 | { | 171 | { |
155 | get { return m_name; } | 172 | get { return "VectorRenderModule"; } |
156 | } | 173 | } |
157 | 174 | ||
158 | public bool IsSharedModule | 175 | public bool IsSharedModule |
@@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
162 | 179 | ||
163 | #endregion | 180 | #endregion |
164 | 181 | ||
165 | private void Draw(string data, UUID id, string extraParams) | 182 | private byte[] Draw(string data, string extraParams, out bool reuseable) |
166 | { | 183 | { |
167 | // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha | 184 | // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha |
168 | // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 | 185 | // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 |
@@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
343 | } | 360 | } |
344 | } | 361 | } |
345 | 362 | ||
346 | GDIDraw(data, graph, altDataDelim); | 363 | GDIDraw(data, graph, altDataDelim, out reuseable); |
347 | } | 364 | } |
348 | 365 | ||
349 | byte[] imageJ2000 = new byte[0]; | 366 | byte[] imageJ2000 = new byte[0]; |
@@ -359,7 +376,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
359 | e.Message, e.StackTrace); | 376 | e.Message, e.StackTrace); |
360 | } | 377 | } |
361 | 378 | ||
362 | m_textureManager.ReturnData(id, imageJ2000); | 379 | return imageJ2000; |
363 | } | 380 | } |
364 | finally | 381 | finally |
365 | { | 382 | { |
@@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
434 | } | 451 | } |
435 | */ | 452 | */ |
436 | 453 | ||
437 | private void GDIDraw(string data, Graphics graph, char dataDelim) | 454 | /// <summary> |
455 | /// Split input data into discrete command lines. | ||
456 | /// </summary> | ||
457 | /// <returns></returns> | ||
458 | /// <param name='data'></param> | ||
459 | /// <param name='dataDelim'></param> | ||
460 | private string[] GetLines(string data, char dataDelim) | ||
438 | { | 461 | { |
462 | char[] lineDelimiter = { dataDelim }; | ||
463 | return data.Split(lineDelimiter); | ||
464 | } | ||
465 | |||
466 | private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable) | ||
467 | { | ||
468 | reuseable = true; | ||
439 | Point startPoint = new Point(0, 0); | 469 | Point startPoint = new Point(0, 0); |
440 | Point endPoint = new Point(0, 0); | 470 | Point endPoint = new Point(0, 0); |
441 | Pen drawPen = null; | 471 | Pen drawPen = null; |
@@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
450 | myFont = new Font(fontName, fontSize); | 480 | myFont = new Font(fontName, fontSize); |
451 | myBrush = new SolidBrush(Color.Black); | 481 | myBrush = new SolidBrush(Color.Black); |
452 | 482 | ||
453 | char[] lineDelimiter = {dataDelim}; | ||
454 | char[] partsDelimiter = {','}; | 483 | char[] partsDelimiter = {','}; |
455 | string[] lines = data.Split(lineDelimiter); | ||
456 | 484 | ||
457 | foreach (string line in lines) | 485 | foreach (string line in GetLines(data, dataDelim)) |
458 | { | 486 | { |
459 | string nextLine = line.Trim(); | 487 | string nextLine = line.Trim(); |
460 | //replace with switch, or even better, do some proper parsing | 488 | //replace with switch, or even better, do some proper parsing |
@@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
485 | } | 513 | } |
486 | else if (nextLine.StartsWith("Image")) | 514 | else if (nextLine.StartsWith("Image")) |
487 | { | 515 | { |
516 | // We cannot reuse any generated texture involving fetching an image via HTTP since that image | ||
517 | // can change. | ||
518 | reuseable = false; | ||
519 | |||
488 | float x = 0; | 520 | float x = 0; |
489 | float y = 0; | 521 | float y = 0; |
490 | GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); | 522 | GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); |