From 4e1f2ba1f4c1316a2d9df548cf1f3d0e2a7bf84b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 26 Sep 2014 01:02:19 +0100 Subject: [PATCH] Make "generate map" console command also trigger upload to maptiles as well as asset generation without performing tile generation twice. --- .../MapImage/MapImageServiceModule.cs | 87 ++++++++++--------- .../World/WorldMap/WorldMapModule.cs | 44 +++++++--- .../Interfaces/IMapImageUploadModule.cs | 37 ++++++++ 3 files changed, 118 insertions(+), 50 deletions(-) create mode 100644 OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index cf4175408c..7dfe53a0ce 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -53,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")] - public class MapImageServiceModule : ISharedRegionModule + public class MapImageServiceModule : IMapImageUploadModule, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -152,6 +152,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage m_scenes[scene.RegionInfo.RegionID] = scene; scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); }; + + scene.RegisterModuleInterface(this); } /// @@ -198,14 +200,53 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage m_lastrefresh = Util.EnvironmentTickCount(); } + public void UploadMapTile(IScene scene, Bitmap mapTile) + { + m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.Name); + + // mapTile.Save( // DEBUG DEBUG + // String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY), + // ImageFormat.Jpeg); + // If the region/maptile is legacy sized, just upload the one tile like it has always been done + if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize) + { + ConvertAndUploadMaptile(mapTile, + scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, + scene.RegionInfo.RegionName); + } + else + { + // For larger regions (varregion) we must cut the region image into legacy sized + // pieces since that is how the maptile system works. + // Note the assumption that varregions are always a multiple of legacy size. + for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize) + { + for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize) + { + // Images are addressed from the upper left corner so have to do funny + // math to pick out the sub-tile since regions are numbered from + // the lower left. + Rectangle rect = new Rectangle( + (int)xx, + mapTile.Height - (int)yy - (int)Constants.RegionSize, + (int)Constants.RegionSize, (int)Constants.RegionSize); + using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat)) + { + ConvertAndUploadMaptile(subMapTile, + scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize), + scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize), + scene.Name); + } + } + } + } + } + /// /// /// private void UploadMapTile(IScene scene) { - m_log.DebugFormat("{0} Upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName); - string regionName = scene.RegionInfo.RegionName; - // Create a JPG map tile and upload it to the AddMapTile API IMapImageGenerator tileGenerator = scene.RequestModuleInterface(); if (tileGenerator == null) @@ -213,46 +254,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage m_log.WarnFormat("{0} Cannot upload map tile without an ImageGenerator", LogHeader); return; } + using (Bitmap mapTile = tileGenerator.CreateMapTile()) { if (mapTile != null) { - // mapTile.Save( // DEBUG DEBUG - // String.Format("maptiles/raw-{0}-{1}-{2}.jpg", regionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY), - // ImageFormat.Jpeg); - // If the region/maptile is legacy sized, just upload the one tile like it has always been done - if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize) - { - ConvertAndUploadMaptile(mapTile, - scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, - scene.RegionInfo.RegionName); - } - else - { - // For larger regions (varregion) we must cut the region image into legacy sized - // pieces since that is how the maptile system works. - // Note the assumption that varregions are always a multiple of legacy size. - for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize) - { - for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize) - { - // Images are addressed from the upper left corner so have to do funny - // math to pick out the sub-tile since regions are numbered from - // the lower left. - Rectangle rect = new Rectangle( - (int)xx, - mapTile.Height - (int)yy - (int)Constants.RegionSize, - (int)Constants.RegionSize, (int)Constants.RegionSize); - using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat)) - { - ConvertAndUploadMaptile(subMapTile, - scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize), - scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize), - regionName); - } - } - } - } + UploadMapTile(scene, mapTile); } else { diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 3af8ac468d..78fbefea36 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -68,6 +68,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap private static readonly UUID STOP_UUID = UUID.Random(); private static readonly string m_mapLayerPath = "0001/"; + private IMapImageGenerator m_mapImageGenerator; + private IMapImageUploadModule m_mapImageServiceModule; + private OpenSim.Framework.BlockingQueue requests = new OpenSim.Framework.BlockingQueue(); protected Scene m_scene; @@ -100,7 +103,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap = Util.GetConfigVarFromSections(config, "BlacklistTimeout", configSections, 10 * 60) * 1000; } - public virtual void AddRegion (Scene scene) + public virtual void AddRegion(Scene scene) { if (!m_Enabled) return; @@ -144,8 +147,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap return; m_ServiceThrottle = scene.RequestModuleInterface(); - } + m_mapImageGenerator = m_scene.RequestModuleInterface(); + m_mapImageServiceModule = m_scene.RequestModuleInterface(); + } public virtual void Close() { @@ -1315,7 +1320,17 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (consoleScene != null && consoleScene != m_scene) return; - GenerateMaptile(); + if (m_mapImageGenerator == null) + { + Console.WriteLine("No map image generator available for {0}", m_scene.Name); + return; + } + + using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile()) + { + GenerateMaptile(mapbmp); + m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp); + } } public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) @@ -1444,16 +1459,25 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (m_scene.Heightmap == null) return; - //create a texture asset of the terrain - IMapImageGenerator terrain = m_scene.RequestModuleInterface(); - if (terrain == null) - return; + m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name); - m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.RegionInfo.RegionName); + using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile()) + GenerateMaptile(mapbmp); + } - byte[] data = terrain.WriteJpeg2000Image(); - if (data == null) + private void GenerateMaptile(Bitmap mapbmp) + { + byte[] data; + + try + { + data = OpenJPEG.EncodeFromImage(mapbmp, true); + } + catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke + { + m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e); return; + } byte[] overlay = GenerateOverlay(); diff --git a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs new file mode 100644 index 0000000000..6a7d4a1c2b --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Drawing; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IMapImageUploadModule + { + void UploadMapTile(IScene scene, Bitmap mapTile); + } +} \ No newline at end of file