PageRenderTime 29ms CodeModel.GetById 13ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Aurora/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs

https://bitbucket.org/VirtualReality/software-testing
C# | 480 lines | 371 code | 68 blank | 41 comment | 62 complexity | 0f816d5b2c00ecc6b5fe06b83095a307 MD5 | raw file
  1/*
  2 * Copyright (c) Contributors, http://aurora-sim.org/, 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 Aurora-Sim 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 Aurora.Framework;
 29using Aurora.Framework.ClientInterfaces;
 30using Aurora.Framework.ConsoleFramework;
 31using Aurora.Framework.Modules;
 32using Aurora.Framework.SceneInfo;
 33using Aurora.Framework.Services.ClassHelpers.Assets;
 34using Aurora.Framework.Utilities;
 35using Nini.Config;
 36using OpenMetaverse;
 37using OpenMetaverse.Imaging;
 38using System;
 39using System.Collections.Generic;
 40using System.Drawing;
 41using System.Drawing.Imaging;
 42
 43namespace Aurora.Modules.Scripting
 44{
 45    public class DynamicTextureModule : INonSharedRegionModule, IDynamicTextureManager
 46    {
 47        //private static readonly ILog MainConsole.Instance = 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        private readonly Dictionary<UUID, IScene> RegisteredScenes = new Dictionary<UUID, IScene>();
 55
 56        private readonly Dictionary<string, IDynamicTextureRender> RenderPlugins =
 57            new Dictionary<string, IDynamicTextureRender>();
 58
 59        private readonly Dictionary<UUID, DynamicTextureUpdater> Updaters =
 60            new Dictionary<UUID, DynamicTextureUpdater>();
 61
 62        #region IDynamicTextureManager Members
 63
 64        public void RegisterRender(string handleType, IDynamicTextureRender render)
 65        {
 66            if (!RenderPlugins.ContainsKey(handleType))
 67            {
 68                RenderPlugins.Add(handleType, render);
 69            }
 70        }
 71
 72        /// <summary>
 73        ///     Called by code which actually renders the dynamic texture to supply texture data.
 74        /// </summary>
 75        /// <param name="id"></param>
 76        /// <param name="data"></param>
 77        public void ReturnData(UUID id, byte[] data)
 78        {
 79            DynamicTextureUpdater updater = null;
 80
 81            lock (Updaters)
 82            {
 83                if (Updaters.ContainsKey(id))
 84                {
 85                    updater = Updaters[id];
 86                }
 87            }
 88
 89            if (updater != null)
 90            {
 91                if (RegisteredScenes.ContainsKey(updater.SimUUID))
 92                {
 93                    IScene scene = RegisteredScenes[updater.SimUUID];
 94                    updater.DataReceived(data, scene);
 95                }
 96            }
 97
 98            if (updater.UpdateTimer == 0)
 99            {
100                lock (Updaters)
101                {
102                    if (!Updaters.ContainsKey(updater.UpdaterID))
103                    {
104                        Updaters.Remove(updater.UpdaterID);
105                    }
106                }
107            }
108        }
109
110        public UUID AddDynamicTextureURL(UUID simID, UUID primID, UUID oldAssetID, string contentType, string url,
111                                         string extraParams, int updateTimer)
112        {
113            return AddDynamicTextureURL(simID, primID, oldAssetID, contentType, url, extraParams, updateTimer, false,
114                                        255);
115        }
116
117        public UUID AddDynamicTextureURL(UUID simID, UUID primID, UUID oldAssetID, string contentType, string url,
118                                         string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
119        {
120            return AddDynamicTextureURL(simID, primID, oldAssetID, contentType, url,
121                                        extraParams, updateTimer, SetBlending,
122                                        (DISP_TEMP | DISP_EXPIRE), AlphaValue, ALL_SIDES);
123        }
124
125        public UUID AddDynamicTextureURL(UUID simID, UUID primID, UUID oldAssetID, string contentType, string url,
126                                         string extraParams, int updateTimer, bool SetBlending,
127                                         int disp, byte AlphaValue, int face)
128        {
129            if (RenderPlugins.ContainsKey(contentType))
130            {
131                DynamicTextureUpdater updater = new DynamicTextureUpdater
132                                                    {
133                                                        SimUUID = simID,
134                                                        PrimID = primID,
135                                                        ContentType = contentType,
136                                                        Url = url,
137                                                        UpdateTimer = updateTimer,
138                                                        UpdaterID = UUID.Random(),
139                                                        Params = extraParams,
140                                                        BlendWithOldTexture = SetBlending,
141                                                        FrontAlpha = AlphaValue,
142                                                        Face = face,
143                                                        Disp = disp,
144                                                        LastAssetID = oldAssetID
145                                                    };
146
147                lock (Updaters)
148                {
149                    if (!Updaters.ContainsKey(updater.UpdaterID))
150                    {
151                        Updaters.Add(updater.UpdaterID, updater);
152                    }
153                }
154
155                RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
156                return updater.UpdaterID;
157            }
158            return UUID.Zero;
159        }
160
161        public UUID AddDynamicTextureData(UUID simID, UUID primID, UUID oldAssetID, string contentType, string data,
162                                          string extraParams, int updateTimer)
163        {
164            return AddDynamicTextureData(simID, primID, oldAssetID, contentType, data, extraParams, updateTimer, false,
165                                         255);
166        }
167
168        public UUID AddDynamicTextureData(UUID simID, UUID primID, UUID oldAssetID, string contentType, string data,
169                                          string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
170        {
171            return AddDynamicTextureData(simID, primID, oldAssetID, contentType, data, extraParams, updateTimer,
172                                         SetBlending,
173                                         (DISP_TEMP | DISP_EXPIRE), AlphaValue, ALL_SIDES);
174        }
175
176        public UUID AddDynamicTextureData(UUID simID, UUID primID, UUID oldAssetID, string contentType, string data,
177                                          string extraParams, int updateTimer, bool SetBlending, int disp,
178                                          byte AlphaValue, int face)
179        {
180            if (RenderPlugins.ContainsKey(contentType))
181            {
182                DynamicTextureUpdater updater = new DynamicTextureUpdater
183                                                    {
184                                                        SimUUID = simID,
185                                                        PrimID = primID,
186                                                        ContentType = contentType,
187                                                        BodyData = data,
188                                                        UpdateTimer = updateTimer,
189                                                        UpdaterID = UUID.Random(),
190                                                        Params = extraParams,
191                                                        BlendWithOldTexture = SetBlending,
192                                                        FrontAlpha = AlphaValue,
193                                                        Face = face,
194                                                        Url = "Local image",
195                                                        Disp = disp,
196                                                        LastAssetID = oldAssetID
197                                                    };
198
199                lock (Updaters)
200                {
201                    if (!Updaters.ContainsKey(updater.UpdaterID))
202                    {
203                        Updaters.Add(updater.UpdaterID, updater);
204                    }
205                }
206
207                RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
208                return updater.UpdaterID;
209            }
210            return UUID.Zero;
211        }
212
213        public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
214                                      out double xSize, out double ySize)
215        {
216            xSize = 0;
217            ySize = 0;
218            if (RenderPlugins.ContainsKey(contentType))
219            {
220                RenderPlugins[contentType].GetDrawStringSize(text, fontName, fontSize, out xSize, out ySize);
221            }
222        }
223
224        #endregion
225
226        #region INonSharedRegionModule Members
227
228        public void Initialise(IConfigSource config)
229        {
230        }
231
232        public void AddRegion(IScene scene)
233        {
234            if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
235            {
236                RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
237                scene.RegisterModuleInterface<IDynamicTextureManager>(this);
238            }
239        }
240
241        public void RemoveRegion(IScene scene)
242        {
243        }
244
245        public void RegionLoaded(IScene scene)
246        {
247        }
248
249        public Type ReplaceableInterface
250        {
251            get { return null; }
252        }
253
254        public void Close()
255        {
256        }
257
258        public string Name
259        {
260            get { return "DynamicTextureModule"; }
261        }
262
263        #endregion
264
265        #region Nested type: DynamicTextureUpdater
266
267        public class DynamicTextureUpdater
268        {
269            public bool BlendWithOldTexture;
270            public string BodyData;
271            public string ContentType;
272            public int Disp;
273            public int Face;
274            public byte FrontAlpha = 255;
275            public UUID LastAssetID = UUID.Zero;
276            public string Params;
277            public UUID PrimID;
278            public bool SetNewFrontAlpha;
279            public UUID SimUUID;
280            public int UpdateTimer;
281            public UUID UpdaterID;
282            public string Url;
283
284            public DynamicTextureUpdater()
285            {
286                UpdateTimer = 0;
287                BodyData = null;
288            }
289
290            /// <summary>
291            ///     Called once new texture data has been received for this updater.
292            /// </summary>
293            public void DataReceived(byte[] data, IScene scene)
294            {
295                ISceneChildEntity part = scene.GetSceneObjectPart(PrimID);
296
297                if (part == null || data == null || data.Length <= 1)
298                {
299                    string msg =
300                        String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
301                    IChatModule chatModule = scene.RequestModuleInterface<IChatModule>();
302                    if (chatModule != null)
303                        chatModule.SimChat(msg, ChatTypeEnum.Say, 0,
304                                           part.ParentEntity.AbsolutePosition, part.Name, part.UUID, false, scene);
305                    return;
306                }
307
308                byte[] assetData = null;
309                AssetBase oldAsset = null;
310
311                if (BlendWithOldTexture)
312                {
313                    Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture;
314                    if (defaultFace != null)
315                    {
316                        oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString());
317
318                        if (oldAsset != null)
319                            assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha, scene);
320                    }
321                }
322
323                if (assetData == null)
324                {
325                    assetData = new byte[data.Length];
326                    Array.Copy(data, assetData, data.Length);
327                }
328
329                AssetBase asset = null;
330
331                if (LastAssetID != UUID.Zero)
332                {
333                    asset = scene.AssetService.Get(LastAssetID.ToString());
334                    asset.Description = String.Format("URL image : {0}", Url);
335                    asset.Data = assetData;
336                    if ((asset.Flags & AssetFlags.Local) == AssetFlags.Local)
337                    {
338                        asset.Flags = asset.Flags & ~AssetFlags.Local;
339                    }
340                    if (((asset.Flags & AssetFlags.Temporary) == AssetFlags.Temporary) != ((Disp & DISP_TEMP) != 0))
341                    {
342                        if ((Disp & DISP_TEMP) != 0) asset.Flags |= AssetFlags.Temporary;
343                        else asset.Flags = asset.Flags & ~AssetFlags.Temporary;
344                    }
345                    asset.ID = scene.AssetService.Store(asset);
346                }
347                else
348                {
349                    // Create a new asset for user
350                    asset = new AssetBase(UUID.Random(), "DynamicImage" + Util.RandomClass.Next(1, 10000),
351                                          AssetType.Texture,
352                                          scene.RegionInfo.RegionID)
353                                {Data = assetData, Description = String.Format("URL image : {0}", Url)};
354                    if ((Disp & DISP_TEMP) != 0) asset.Flags = AssetFlags.Temporary;
355                    asset.ID = scene.AssetService.Store(asset);
356                }
357
358                IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
359                if (cacheLayerDecode != null)
360                {
361                    cacheLayerDecode.Decode(asset.ID, asset.Data);
362                    cacheLayerDecode = null;
363                    LastAssetID = asset.ID;
364                }
365
366                UUID oldID = UUID.Zero;
367
368                lock (part)
369                {
370                    // mostly keep the values from before
371                    Primitive.TextureEntry tmptex = part.Shape.Textures;
372
373                    // remove the old asset from the cache
374                    oldID = tmptex.DefaultTexture.TextureID;
375
376                    if (Face == ALL_SIDES)
377                    {
378                        tmptex.DefaultTexture.TextureID = asset.ID;
379                    }
380                    else
381                    {
382                        try
383                        {
384                            Primitive.TextureEntryFace texface = tmptex.CreateFace((uint) Face);
385                            texface.TextureID = asset.ID;
386                            tmptex.FaceTextures[Face] = texface;
387                        }
388                        catch (Exception)
389                        {
390                            tmptex.DefaultTexture.TextureID = asset.ID;
391                        }
392                    }
393
394                    // I'm pretty sure we always want to force this to true
395                    // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
396                    // tmptex.DefaultTexture.Fullbright = true;
397
398                    part.UpdateTexture(tmptex, true);
399                }
400
401                if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
402                {
403                    if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
404                    if (oldAsset != null)
405                    {
406                        if ((oldAsset.Flags & AssetFlags.Temporary) == AssetFlags.Temporary)
407                        {
408                            scene.AssetService.Delete(oldID);
409                        }
410                    }
411                }
412            }
413
414            private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha,
415                                         IScene scene)
416            {
417                Image image = scene.RequestModuleInterface<IJ2KDecoder>().DecodeToImage(frontImage);
418
419                if (image != null)
420                {
421                    Bitmap image1 = new Bitmap(image);
422
423                    image = scene.RequestModuleInterface<IJ2KDecoder>().DecodeToImage(backImage);
424                    if (image != null)
425                    {
426                        Bitmap image2 = new Bitmap(image);
427
428                        if (setNewAlpha)
429                            SetAlpha(ref image1, newAlpha);
430
431                        Bitmap joint = MergeBitMaps(image1, image2);
432
433                        byte[] result = new byte[0];
434
435                        try
436                        {
437                            result = OpenJPEG.EncodeFromImage(joint, true);
438                        }
439                        catch (Exception)
440                        {
441                            MainConsole.Instance.Error(
442                                "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed.  Empty byte data returned!");
443                        }
444
445                        return result;
446                    }
447                }
448
449                return null;
450            }
451
452            public Bitmap MergeBitMaps(Bitmap front, Bitmap back)
453            {
454                Bitmap joint;
455                Graphics jG;
456
457                joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb);
458                jG = Graphics.FromImage(joint);
459
460                jG.DrawImage(back, 0, 0, back.Width, back.Height);
461                jG.DrawImage(front, 0, 0, back.Width, back.Height);
462
463                return joint;
464            }
465
466            private void SetAlpha(ref Bitmap b, byte alpha)
467            {
468                for (int w = 0; w < b.Width; w++)
469                {
470                    for (int h = 0; h < b.Height; h++)
471                    {
472                        b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h)));
473                    }
474                }
475            }
476        }
477
478        #endregion
479    }
480}