aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Scripting/DynamicTexture
diff options
context:
space:
mode:
authorUbitUmarov2015-09-01 11:43:07 +0100
committerUbitUmarov2015-09-01 11:43:07 +0100
commitfb78b182520fc9bb0f971afd0322029c70278ea6 (patch)
treeb4e30d383938fdeef8c92d1d1c2f44bb61d329bd /OpenSim/Region/CoreModules/Scripting/DynamicTexture
parentlixo (diff)
parentMantis #7713: fixed bug introduced by 1st MOSES patch. (diff)
downloadopensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.zip
opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.gz
opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.bz2
opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.xz
Merge remote-tracking branch 'os/master'
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/DynamicTexture')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs61
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs617
2 files changed, 678 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
new file mode 100644
index 0000000..fce9490
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Drawing;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
33{
34 public class DynamicTexture : IDynamicTexture
35 {
36 public string InputCommands { get; private set; }
37 public Uri InputUri { get; private set; }
38 public string InputParams { get; private set; }
39 public byte[] Data { get; private set; }
40 public Size Size { get; private set; }
41 public bool IsReuseable { get; private set; }
42
43 public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
44 {
45 InputCommands = inputCommands;
46 InputParams = inputParams;
47 Data = data;
48 Size = size;
49 IsReuseable = isReuseable;
50 }
51
52 public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
53 {
54 InputUri = inputUri;
55 InputParams = inputParams;
56 Data = data;
57 Size = size;
58 IsReuseable = isReuseable;
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
new file mode 100644
index 0000000..a686a4d
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -0,0 +1,617 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Drawing;
31using System.Drawing.Imaging;
32using Nini.Config;
33using OpenMetaverse;
34using OpenMetaverse.Imaging;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using log4net;
39using System.Reflection;
40using Mono.Addins;
41
42namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicTextureModule")]
45 public class DynamicTextureModule : ISharedRegionModule, IDynamicTextureManager
46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private const int ALL_SIDES = -1;
50
51 public const int DISP_EXPIRE = 1;
52 public const int DISP_TEMP = 2;
53
54 /// <summary>
55 /// If true then where possible dynamic textures are reused.
56 /// </summary>
57 public bool ReuseTextures { get; set; }
58
59 /// <summary>
60 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
61 /// </summary>
62 /// <remarks>
63 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
64 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
65 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
66 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
67 /// to work around this problem.</remarks>
68 public bool ReuseLowDataTextures { get; set; }
69
70 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
71
72 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
73 new Dictionary<string, IDynamicTextureRender>();
74
75 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
76
77 /// <summary>
78 /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
79 /// regenerate.
80 /// </summary>
81 /// <remarks>
82 /// Key is string.Format("{0}{1}", data
83 /// </remarks>
84 private Cache m_reuseableDynamicTextures;
85
86 /// <summary>
87 /// This constructor is only here because of the Unit Tests...
88 /// Don't use it.
89 /// </summary>
90 public DynamicTextureModule()
91 {
92 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
93 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
94 }
95
96 #region IDynamicTextureManager Members
97
98 public void RegisterRender(string handleType, IDynamicTextureRender render)
99 {
100 if (!RenderPlugins.ContainsKey(handleType))
101 {
102 RenderPlugins.Add(handleType, render);
103 }
104 }
105
106 /// <summary>
107 /// Called by code which actually renders the dynamic texture to supply texture data.
108 /// </summary>
109 /// <param name="updaterId"></param>
110 /// <param name="texture"></param>
111 public void ReturnData(UUID updaterId, IDynamicTexture texture)
112 {
113 DynamicTextureUpdater updater = null;
114
115 lock (Updaters)
116 {
117 if (Updaters.ContainsKey(updaterId))
118 {
119 updater = Updaters[updaterId];
120 }
121 }
122
123 if (updater != null)
124 {
125 if (RegisteredScenes.ContainsKey(updater.SimUUID))
126 {
127 Scene scene = RegisteredScenes[updater.SimUUID];
128 UUID newTextureID = updater.DataReceived(texture.Data, scene);
129
130 if (ReuseTextures
131 && !updater.BlendWithOldTexture
132 && texture.IsReuseable
133 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
134 {
135 m_reuseableDynamicTextures.Store(
136 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
137 }
138 }
139 }
140
141 if (updater.UpdateTimer == 0)
142 {
143 lock (Updaters)
144 {
145 if (!Updaters.ContainsKey(updater.UpdaterID))
146 {
147 Updaters.Remove(updater.UpdaterID);
148 }
149 }
150 }
151 }
152
153 /// <summary>
154 /// Determines whether the texture is reuseable based on its data size.
155 /// </summary>
156 /// <remarks>
157 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
158 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
159 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
160 /// </remarks>
161 /// <returns></returns>
162 private bool IsDataSizeReuseable(IDynamicTexture texture)
163 {
164// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
165 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
166
167// m_log.DebugFormat(
168// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
169// discardLevel2DataThreshold, texture.Data.Length);
170
171 return discardLevel2DataThreshold < texture.Data.Length;
172 }
173
174 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
175 string extraParams, int updateTimer)
176 {
177 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255);
178 }
179
180 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
181 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
182 {
183 return AddDynamicTextureURL(simID, primID, contentType, url,
184 extraParams, updateTimer, SetBlending,
185 (int)(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
186 }
187
188 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
189 string extraParams, int updateTimer, bool SetBlending,
190 int disp, byte AlphaValue, int face)
191 {
192 if (RenderPlugins.ContainsKey(contentType))
193 {
194 DynamicTextureUpdater updater = new DynamicTextureUpdater();
195 updater.SimUUID = simID;
196 updater.PrimID = primID;
197 updater.ContentType = contentType;
198 updater.Url = url;
199 updater.UpdateTimer = updateTimer;
200 updater.UpdaterID = UUID.Random();
201 updater.Params = extraParams;
202 updater.BlendWithOldTexture = SetBlending;
203 updater.FrontAlpha = AlphaValue;
204 updater.Face = face;
205 updater.Disp = disp;
206
207 lock (Updaters)
208 {
209 if (!Updaters.ContainsKey(updater.UpdaterID))
210 {
211 Updaters.Add(updater.UpdaterID, updater);
212 }
213 }
214
215 RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
216 return updater.UpdaterID;
217 }
218 return UUID.Zero;
219 }
220
221 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
222 string extraParams, int updateTimer)
223 {
224 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255);
225 }
226
227 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
228 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
229 {
230 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending,
231 (int) (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES);
232 }
233
234 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
235 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
236 {
237 if (!RenderPlugins.ContainsKey(contentType))
238 return UUID.Zero;
239
240 Scene scene;
241 RegisteredScenes.TryGetValue(simID, out scene);
242
243 if (scene == null)
244 return UUID.Zero;
245
246 SceneObjectPart part = scene.GetSceneObjectPart(primID);
247
248 if (part == null)
249 return UUID.Zero;
250
251 // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
252 // them.
253 if (ReuseTextures)
254 disp = disp & ~DISP_EXPIRE;
255
256 DynamicTextureUpdater updater = new DynamicTextureUpdater();
257 updater.SimUUID = simID;
258 updater.PrimID = primID;
259 updater.ContentType = contentType;
260 updater.BodyData = data;
261 updater.UpdateTimer = updateTimer;
262 updater.UpdaterID = UUID.Random();
263 updater.Params = extraParams;
264 updater.BlendWithOldTexture = SetBlending;
265 updater.FrontAlpha = AlphaValue;
266 updater.Face = face;
267 updater.Url = "Local image";
268 updater.Disp = disp;
269
270 object objReusableTextureUUID = null;
271
272 if (ReuseTextures && !updater.BlendWithOldTexture)
273 {
274 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
275 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
276
277 if (objReusableTextureUUID != null)
278 {
279 // If something else has removed this temporary asset from the cache, detect and invalidate
280 // our cached uuid.
281 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
282 {
283 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
284 objReusableTextureUUID = null;
285 }
286 }
287 }
288
289 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
290 if (objReusableTextureUUID == null)
291 {
292 lock (Updaters)
293 {
294 if (!Updaters.ContainsKey(updater.UpdaterID))
295 {
296 Updaters.Add(updater.UpdaterID, updater);
297 }
298 }
299
300// m_log.DebugFormat(
301// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
302// part.Name, part.ParentGroup.Scene.Name);
303
304 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
305 }
306 else
307 {
308// m_log.DebugFormat(
309// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
310// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
311
312 // No need to add to updaters as the texture is always the same. Not that this functionality
313 // apppears to be implemented anyway.
314 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
315 }
316
317 return updater.UpdaterID;
318 }
319
320 private string GenerateReusableTextureKey(string data, string extraParams)
321 {
322 return string.Format("{0}{1}", data, extraParams);
323 }
324
325 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
326 out double xSize, out double ySize)
327 {
328 xSize = 0;
329 ySize = 0;
330 if (RenderPlugins.ContainsKey(contentType))
331 {
332 RenderPlugins[contentType].GetDrawStringSize(text, fontName, fontSize, out xSize, out ySize);
333 }
334 }
335
336 #endregion
337
338 #region ISharedRegionModule Members
339
340 public void Initialise(IConfigSource config)
341 {
342 IConfig texturesConfig = config.Configs["Textures"];
343 if (texturesConfig != null)
344 {
345 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
346 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
347
348 if (ReuseTextures)
349 {
350 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
351 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
352 }
353 }
354 }
355
356 public void PostInitialise()
357 {
358 }
359
360 public void AddRegion(Scene scene)
361 {
362 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
363 {
364 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
365 scene.RegisterModuleInterface<IDynamicTextureManager>(this);
366 }
367 }
368
369 public void RegionLoaded(Scene scene)
370 {
371 }
372
373 public void RemoveRegion(Scene scene)
374 {
375 if (RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
376 RegisteredScenes.Remove(scene.RegionInfo.RegionID);
377 }
378
379 public void Close()
380 {
381 }
382
383 public string Name
384 {
385 get { return "DynamicTextureModule"; }
386 }
387
388 public Type ReplaceableInterface
389 {
390 get { return null; }
391 }
392
393 #endregion
394
395 #region Nested type: DynamicTextureUpdater
396
397 public class DynamicTextureUpdater
398 {
399 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
400
401 public bool BlendWithOldTexture = false;
402 public string BodyData;
403 public string ContentType;
404 public byte FrontAlpha = 255;
405 public string Params;
406 public UUID PrimID;
407 public bool SetNewFrontAlpha = false;
408 public UUID SimUUID;
409 public UUID UpdaterID;
410 public int UpdateTimer;
411 public int Face;
412 public int Disp;
413 public string Url;
414
415 public DynamicTextureUpdater()
416 {
417 UpdateTimer = 0;
418 BodyData = null;
419 }
420
421 /// <summary>
422 /// Update the given part with the new texture.
423 /// </summary>
424 /// <returns>
425 /// The old texture UUID.
426 /// </returns>
427 public UUID UpdatePart(SceneObjectPart part, UUID textureID)
428 {
429 UUID oldID;
430
431 lock (part)
432 {
433 // mostly keep the values from before
434 Primitive.TextureEntry tmptex = part.Shape.Textures;
435
436 // FIXME: Need to return the appropriate ID if only a single face is replaced.
437 oldID = tmptex.DefaultTexture.TextureID;
438
439 if (Face == ALL_SIDES)
440 {
441 oldID = tmptex.DefaultTexture.TextureID;
442 tmptex.DefaultTexture.TextureID = textureID;
443 }
444 else
445 {
446 try
447 {
448 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
449 texface.TextureID = textureID;
450 tmptex.FaceTextures[Face] = texface;
451 }
452 catch (Exception)
453 {
454 tmptex.DefaultTexture.TextureID = textureID;
455 }
456 }
457
458 // I'm pretty sure we always want to force this to true
459 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
460 // tmptex.DefaultTexture.Fullbright = true;
461
462 part.UpdateTextureEntry(tmptex.GetBytes());
463 }
464
465 return oldID;
466 }
467
468 /// <summary>
469 /// Called once new texture data has been received for this updater.
470 /// </summary>
471 /// <param name="data"></param>
472 /// <param name="scene"></param>
473 /// <param name="isReuseable">True if the data given is reuseable.</param>
474 /// <returns>The asset UUID given to the incoming data.</returns>
475 public UUID DataReceived(byte[] data, Scene scene)
476 {
477 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
478
479 if (part == null || data == null || data.Length <= 1)
480 {
481 string msg =
482 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
483 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
484 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
485
486 return UUID.Zero;
487 }
488
489 byte[] assetData = null;
490 AssetBase oldAsset = null;
491
492 if (BlendWithOldTexture)
493 {
494 Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture;
495 if (defaultFace != null)
496 {
497 oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString());
498
499 if (oldAsset != null)
500 assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha);
501 }
502 }
503
504 if (assetData == null)
505 {
506 assetData = new byte[data.Length];
507 Array.Copy(data, assetData, data.Length);
508 }
509
510 // Create a new asset for user
511 AssetBase asset
512 = new AssetBase(
513 UUID.Random(), "DynamicImage" + Util.RandomClass.Next(1, 10000), (sbyte)AssetType.Texture,
514 scene.RegionInfo.RegionID.ToString());
515 asset.Data = assetData;
516 asset.Description = String.Format("URL image : {0}", Url);
517 if (asset.Description.Length > 128)
518 asset.Description = asset.Description.Substring(0, 128);
519 asset.Local = true; // dynamic images aren't saved in the assets server
520 asset.Temporary = ((Disp & DISP_TEMP) != 0);
521 scene.AssetService.Store(asset); // this will only save the asset in the local asset cache
522
523 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
524 if (cacheLayerDecode != null)
525 {
526 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
527 m_log.WarnFormat(
528 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
529 asset.ID, part.Name, part.ParentGroup.Scene.Name);
530 }
531
532 UUID oldID = UpdatePart(part, asset.FullID);
533
534 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
535 {
536 if (oldAsset == null)
537 oldAsset = scene.AssetService.Get(oldID.ToString());
538
539 if (oldAsset != null)
540 {
541 if (oldAsset.Temporary)
542 {
543 scene.AssetService.Delete(oldID.ToString());
544 }
545 }
546 }
547
548 return asset.FullID;
549 }
550
551 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
552 {
553 ManagedImage managedImage;
554 Image image;
555
556 if (OpenJPEG.DecodeToImage(frontImage, out managedImage, out image))
557 {
558 Bitmap image1 = new Bitmap(image);
559
560 if (OpenJPEG.DecodeToImage(backImage, out managedImage, out image))
561 {
562 Bitmap image2 = new Bitmap(image);
563
564 if (setNewAlpha)
565 SetAlpha(ref image1, newAlpha);
566
567 Bitmap joint = MergeBitMaps(image1, image2);
568
569 byte[] result = new byte[0];
570
571 try
572 {
573 result = OpenJPEG.EncodeFromImage(joint, true);
574 }
575 catch (Exception e)
576 {
577 m_log.ErrorFormat(
578 "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}",
579 e.Message, e.StackTrace);
580 }
581
582 return result;
583 }
584 }
585
586 return null;
587 }
588
589 public Bitmap MergeBitMaps(Bitmap front, Bitmap back)
590 {
591 Bitmap joint;
592 Graphics jG;
593
594 joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb);
595 jG = Graphics.FromImage(joint);
596
597 jG.DrawImage(back, 0, 0, back.Width, back.Height);
598 jG.DrawImage(front, 0, 0, back.Width, back.Height);
599
600 return joint;
601 }
602
603 private void SetAlpha(ref Bitmap b, byte alpha)
604 {
605 for (int w = 0; w < b.Width; w++)
606 {
607 for (int h = 0; h < b.Height; h++)
608 {
609 b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h)));
610 }
611 }
612 }
613 }
614
615 #endregion
616 }
617}