Properly dispose of drawing objects to reduce/stop memory leakage on generating map tiles with the MapImageModule and TexturedMapTileRenderer (the current defaults)
							parent
							
								
									099975dec2
								
							
						
					
					
						commit
						04e6c68242
					
				|  | @ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|     public struct DrawStruct | ||||
|     { | ||||
|         public DrawRoutine dr; | ||||
|         public Rectangle rect; | ||||
| //        public Rectangle rect; | ||||
|         public SolidBrush brush; | ||||
|         public face[] trns; | ||||
|     } | ||||
|  | @ -119,6 +119,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|             { | ||||
|                 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); | ||||
|             } | ||||
| 
 | ||||
|             return mapbmp; | ||||
|         } | ||||
| 
 | ||||
|  | @ -280,321 +281,331 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|             tc = Environment.TickCount; | ||||
|             m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); | ||||
|             EntityBase[] objs = whichScene.GetEntities(); | ||||
|             Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>(); | ||||
|             //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>(); | ||||
|             List<float> z_sortheights = new List<float>(); | ||||
|             List<uint> z_localIDs = new List<uint>(); | ||||
|             Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>(); | ||||
| 
 | ||||
|             lock (objs) | ||||
|             try  | ||||
|             { | ||||
|                 foreach (EntityBase obj in objs) | ||||
|                 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>(); | ||||
| 
 | ||||
|                 lock (objs) | ||||
|                 { | ||||
|                     // Only draw the contents of SceneObjectGroup | ||||
|                     if (obj is SceneObjectGroup) | ||||
|                     foreach (EntityBase obj in objs) | ||||
|                     { | ||||
|                         SceneObjectGroup mapdot = (SceneObjectGroup)obj; | ||||
|                         Color mapdotspot = Color.Gray; // Default color when prim color is white | ||||
|                          | ||||
|                         // Loop over prim in group | ||||
|                         foreach (SceneObjectPart part in mapdot.Parts) | ||||
|                         // Only draw the contents of SceneObjectGroup | ||||
|                         if (obj is SceneObjectGroup) | ||||
|                         { | ||||
|                             if (part == null) | ||||
|                                 continue; | ||||
| 
 | ||||
|                             // Draw if the object is at least 1 meter wide in any direction | ||||
|                             if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) | ||||
|                             SceneObjectGroup mapdot = (SceneObjectGroup)obj; | ||||
|                             Color mapdotspot = Color.Gray; // Default color when prim color is white | ||||
|                              | ||||
|                             // Loop over prim in group | ||||
|                             foreach (SceneObjectPart part in mapdot.Parts) | ||||
|                             { | ||||
|                                 // Try to get the RGBA of the default texture entry.. | ||||
|                                 // | ||||
|                                 try | ||||
|                                 { | ||||
|                                     // get the null checks out of the way | ||||
|                                     // skip the ones that break | ||||
|                                     if (part == null) | ||||
|                                         continue; | ||||
| 
 | ||||
|                                     if (part.Shape == null) | ||||
|                                         continue; | ||||
| 
 | ||||
|                                     if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) | ||||
|                                         continue; // eliminates trees from this since we don't really have a good tree representation | ||||
|                                     // if you want tree blocks on the map comment the above line and uncomment the below line | ||||
|                                     //mapdotspot = Color.PaleGreen; | ||||
| 
 | ||||
|                                     Primitive.TextureEntry textureEntry = part.Shape.Textures; | ||||
| 
 | ||||
|                                     if (textureEntry == null || textureEntry.DefaultTexture == null) | ||||
|                                         continue; | ||||
| 
 | ||||
|                                     Color4 texcolor = textureEntry.DefaultTexture.RGBA; | ||||
| 
 | ||||
|                                     // Not sure why some of these are null, oh well. | ||||
| 
 | ||||
|                                     int colorr = 255 - (int)(texcolor.R * 255f); | ||||
|                                     int colorg = 255 - (int)(texcolor.G * 255f); | ||||
|                                     int colorb = 255 - (int)(texcolor.B * 255f); | ||||
| 
 | ||||
|                                     if (!(colorr == 255 && colorg == 255 && colorb == 255)) | ||||
|                                     { | ||||
|                                         //Try to set the map spot color | ||||
|                                         try | ||||
|                                         { | ||||
|                                             // If the color gets goofy somehow, skip it *shakes fist at Color4 | ||||
|                                             mapdotspot = Color.FromArgb(colorr, colorg, colorb); | ||||
|                                         } | ||||
|                                         catch (ArgumentException) | ||||
|                                         { | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                                 catch (IndexOutOfRangeException) | ||||
|                                 { | ||||
|                                     // Windows Array | ||||
|                                 } | ||||
|                                 catch (ArgumentOutOfRangeException) | ||||
|                                 { | ||||
|                                     // Mono Array | ||||
|                                 } | ||||
| 
 | ||||
|                                 Vector3 pos = part.GetWorldPosition(); | ||||
| 
 | ||||
|                                 // skip prim outside of retion | ||||
|                                 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) | ||||
|                                 if (part == null) | ||||
|                                     continue; | ||||
| 
 | ||||
|                                 // skip prim in non-finite position | ||||
|                                 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || | ||||
|                                     Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y)) | ||||
|                                     continue; | ||||
| 
 | ||||
|                                 // Figure out if object is under 256m above the height of the terrain | ||||
|                                 bool isBelow256AboveTerrain = false; | ||||
| 
 | ||||
|                                 try | ||||
|                                 // Draw if the object is at least 1 meter wide in any direction | ||||
|                                 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) | ||||
|                                 { | ||||
|                                     isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f)); | ||||
|                                 } | ||||
|                                 catch (Exception) | ||||
|                                 { | ||||
|                                 } | ||||
| 
 | ||||
|                                 if (isBelow256AboveTerrain) | ||||
|                                 { | ||||
|                                     // Translate scale by rotation so scale is represented properly when object is rotated | ||||
|                                     Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); | ||||
|                                     Vector3 scale = new Vector3(); | ||||
|                                     Vector3 tScale = new Vector3(); | ||||
|                                     Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z); | ||||
| 
 | ||||
|                                     Quaternion llrot = part.GetWorldRotation(); | ||||
|                                     Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z); | ||||
|                                     scale = lscale * rot; | ||||
| 
 | ||||
|                                     // negative scales don't work in this situation | ||||
|                                     scale.X = Math.Abs(scale.X); | ||||
|                                     scale.Y = Math.Abs(scale.Y); | ||||
|                                     scale.Z = Math.Abs(scale.Z); | ||||
| 
 | ||||
|                                     // This scaling isn't very accurate and doesn't take into account the face rotation :P | ||||
|                                     int mapdrawstartX = (int)(pos.X - scale.X); | ||||
|                                     int mapdrawstartY = (int)(pos.Y - scale.Y); | ||||
|                                     int mapdrawendX = (int)(pos.X + scale.X); | ||||
|                                     int mapdrawendY = (int)(pos.Y + scale.Y); | ||||
| 
 | ||||
|                                     // If object is beyond the edge of the map, don't draw it to avoid errors | ||||
|                                     if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1) | ||||
|                                                           || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0 | ||||
|                                                           || mapdrawendY > ((int)Constants.RegionSize - 1)) | ||||
|                                         continue; | ||||
| 
 | ||||
| #region obb face reconstruction part duex | ||||
|                                     Vector3[] vertexes = new Vector3[8]; | ||||
| 
 | ||||
|                                     // float[] distance = new float[6]; | ||||
|                                     Vector3[] FaceA = new Vector3[6]; // vertex A for Facei | ||||
|                                     Vector3[] FaceB = new Vector3[6]; // vertex B for Facei | ||||
|                                     Vector3[] FaceC = new Vector3[6]; // vertex C for Facei | ||||
|                                     Vector3[] FaceD = new Vector3[6]; // vertex D for Facei | ||||
| 
 | ||||
|                                     tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
|                                     // vertexes[0].x = pos.X + vertexes[0].x; | ||||
|                                     //vertexes[0].y = pos.Y + vertexes[0].y; | ||||
|                                     //vertexes[0].z = pos.Z + vertexes[0].z; | ||||
| 
 | ||||
|                                     FaceA[0] = vertexes[0]; | ||||
|                                     FaceB[3] = vertexes[0]; | ||||
|                                     FaceA[4] = vertexes[0]; | ||||
| 
 | ||||
|                                     tScale = lscale; | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     // vertexes[1].x = pos.X + vertexes[1].x; | ||||
|                                     // vertexes[1].y = pos.Y + vertexes[1].y; | ||||
|                                     //vertexes[1].z = pos.Z + vertexes[1].z; | ||||
| 
 | ||||
|                                     FaceB[0] = vertexes[1]; | ||||
|                                     FaceA[1] = vertexes[1]; | ||||
|                                     FaceC[4] = vertexes[1]; | ||||
| 
 | ||||
|                                     tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
| 
 | ||||
|                                     vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     //vertexes[2].x = pos.X + vertexes[2].x; | ||||
|                                     //vertexes[2].y = pos.Y + vertexes[2].y; | ||||
|                                     //vertexes[2].z = pos.Z + vertexes[2].z; | ||||
| 
 | ||||
|                                     FaceC[0] = vertexes[2]; | ||||
|                                     FaceD[3] = vertexes[2]; | ||||
|                                     FaceC[5] = vertexes[2]; | ||||
| 
 | ||||
|                                     tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     //vertexes[3].x = pos.X + vertexes[3].x; | ||||
|                                     // vertexes[3].y = pos.Y + vertexes[3].y; | ||||
|                                     // vertexes[3].z = pos.Z + vertexes[3].z; | ||||
| 
 | ||||
|                                     FaceD[0] = vertexes[3]; | ||||
|                                     FaceC[1] = vertexes[3]; | ||||
|                                     FaceA[5] = vertexes[3]; | ||||
| 
 | ||||
|                                     tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     // vertexes[4].x = pos.X + vertexes[4].x; | ||||
|                                     // vertexes[4].y = pos.Y + vertexes[4].y; | ||||
|                                     // vertexes[4].z = pos.Z + vertexes[4].z; | ||||
| 
 | ||||
|                                     FaceB[1] = vertexes[4]; | ||||
|                                     FaceA[2] = vertexes[4]; | ||||
|                                     FaceD[4] = vertexes[4]; | ||||
| 
 | ||||
|                                     tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     // vertexes[5].x = pos.X + vertexes[5].x; | ||||
|                                     // vertexes[5].y = pos.Y + vertexes[5].y; | ||||
|                                     // vertexes[5].z = pos.Z + vertexes[5].z; | ||||
| 
 | ||||
|                                     FaceD[1] = vertexes[5]; | ||||
|                                     FaceC[2] = vertexes[5]; | ||||
|                                     FaceB[5] = vertexes[5]; | ||||
| 
 | ||||
|                                     tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     // vertexes[6].x = pos.X + vertexes[6].x; | ||||
|                                     // vertexes[6].y = pos.Y + vertexes[6].y; | ||||
|                                     // vertexes[6].z = pos.Z + vertexes[6].z; | ||||
| 
 | ||||
|                                     FaceB[2] = vertexes[6]; | ||||
|                                     FaceA[3] = vertexes[6]; | ||||
|                                     FaceB[4] = vertexes[6]; | ||||
| 
 | ||||
|                                     tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); | ||||
|                                     scale = ((tScale * rot)); | ||||
|                                     vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                     // vertexes[7].x = pos.X + vertexes[7].x; | ||||
|                                     // vertexes[7].y = pos.Y + vertexes[7].y; | ||||
|                                     // vertexes[7].z = pos.Z + vertexes[7].z; | ||||
| 
 | ||||
|                                     FaceD[2] = vertexes[7]; | ||||
|                                     FaceC[3] = vertexes[7]; | ||||
|                                     FaceD[5] = vertexes[7]; | ||||
| #endregion | ||||
| 
 | ||||
|                                     //int wy = 0; | ||||
| 
 | ||||
|                                     //bool breakYN = false; // If we run into an error drawing, break out of the | ||||
|                                     // loop so we don't lag to death on error handling | ||||
|                                     DrawStruct ds = new DrawStruct(); | ||||
|                                     ds.brush = new SolidBrush(mapdotspot); | ||||
|                                     //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); | ||||
| 
 | ||||
|                                     ds.trns = new face[FaceA.Length]; | ||||
| 
 | ||||
|                                     for (int i = 0; i < FaceA.Length; i++) | ||||
|                                     // Try to get the RGBA of the default texture entry.. | ||||
|                                     // | ||||
|                                     try | ||||
|                                     { | ||||
|                                         Point[] working = new Point[5]; | ||||
|                                         working[0] = project(FaceA[i], axPos); | ||||
|                                         working[1] = project(FaceB[i], axPos); | ||||
|                                         working[2] = project(FaceD[i], axPos); | ||||
|                                         working[3] = project(FaceC[i], axPos); | ||||
|                                         working[4] = project(FaceA[i], axPos); | ||||
|                                         // get the null checks out of the way | ||||
|                                         // skip the ones that break | ||||
|                                         if (part == null) | ||||
|                                             continue; | ||||
| 
 | ||||
|                                         face workingface = new face(); | ||||
|                                         workingface.pts = working; | ||||
|                                         if (part.Shape == null) | ||||
|                                             continue; | ||||
| 
 | ||||
|                                         ds.trns[i] = workingface; | ||||
|                                         if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) | ||||
|                                             continue; // eliminates trees from this since we don't really have a good tree representation | ||||
|                                         // if you want tree blocks on the map comment the above line and uncomment the below line | ||||
|                                         //mapdotspot = Color.PaleGreen; | ||||
| 
 | ||||
|                                         Primitive.TextureEntry textureEntry = part.Shape.Textures; | ||||
| 
 | ||||
|                                         if (textureEntry == null || textureEntry.DefaultTexture == null) | ||||
|                                             continue; | ||||
| 
 | ||||
|                                         Color4 texcolor = textureEntry.DefaultTexture.RGBA; | ||||
| 
 | ||||
|                                         // Not sure why some of these are null, oh well. | ||||
| 
 | ||||
|                                         int colorr = 255 - (int)(texcolor.R * 255f); | ||||
|                                         int colorg = 255 - (int)(texcolor.G * 255f); | ||||
|                                         int colorb = 255 - (int)(texcolor.B * 255f); | ||||
| 
 | ||||
|                                         if (!(colorr == 255 && colorg == 255 && colorb == 255)) | ||||
|                                         { | ||||
|                                             //Try to set the map spot color | ||||
|                                             try | ||||
|                                             { | ||||
|                                                 // If the color gets goofy somehow, skip it *shakes fist at Color4 | ||||
|                                                 mapdotspot = Color.FromArgb(colorr, colorg, colorb); | ||||
|                                             } | ||||
|                                             catch (ArgumentException) | ||||
|                                             { | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                     catch (IndexOutOfRangeException) | ||||
|                                     { | ||||
|                                         // Windows Array | ||||
|                                     } | ||||
|                                     catch (ArgumentOutOfRangeException) | ||||
|                                     { | ||||
|                                         // Mono Array | ||||
|                                     } | ||||
| 
 | ||||
|                                     z_sort.Add(part.LocalId, ds); | ||||
|                                     z_localIDs.Add(part.LocalId); | ||||
|                                     z_sortheights.Add(pos.Z); | ||||
|                                     Vector3 pos = part.GetWorldPosition(); | ||||
| 
 | ||||
|                                     //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) | ||||
|                                     //{ | ||||
|                                         //for (wy = mapdrawstartY; wy < mapdrawendY; wy++) | ||||
|                                     // skip prim outside of retion | ||||
|                                     if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) | ||||
|                                         continue; | ||||
| 
 | ||||
|                                     // skip prim in non-finite position | ||||
|                                     if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || | ||||
|                                         Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y)) | ||||
|                                         continue; | ||||
| 
 | ||||
|                                     // Figure out if object is under 256m above the height of the terrain | ||||
|                                     bool isBelow256AboveTerrain = false; | ||||
| 
 | ||||
|                                     try | ||||
|                                     { | ||||
|                                         isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f)); | ||||
|                                     } | ||||
|                                     catch (Exception) | ||||
|                                     { | ||||
|                                     } | ||||
| 
 | ||||
|                                     if (isBelow256AboveTerrain) | ||||
|                                     { | ||||
|                                         // Translate scale by rotation so scale is represented properly when object is rotated | ||||
|                                         Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z); | ||||
|                                         Vector3 scale = new Vector3(); | ||||
|                                         Vector3 tScale = new Vector3(); | ||||
|                                         Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z); | ||||
| 
 | ||||
|                                         Quaternion llrot = part.GetWorldRotation(); | ||||
|                                         Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z); | ||||
|                                         scale = lscale * rot; | ||||
| 
 | ||||
|                                         // negative scales don't work in this situation | ||||
|                                         scale.X = Math.Abs(scale.X); | ||||
|                                         scale.Y = Math.Abs(scale.Y); | ||||
|                                         scale.Z = Math.Abs(scale.Z); | ||||
| 
 | ||||
|                                         // This scaling isn't very accurate and doesn't take into account the face rotation :P | ||||
|                                         int mapdrawstartX = (int)(pos.X - scale.X); | ||||
|                                         int mapdrawstartY = (int)(pos.Y - scale.Y); | ||||
|                                         int mapdrawendX = (int)(pos.X + scale.X); | ||||
|                                         int mapdrawendY = (int)(pos.Y + scale.Y); | ||||
| 
 | ||||
|                                         // If object is beyond the edge of the map, don't draw it to avoid errors | ||||
|                                         if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1) | ||||
|                                                               || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0 | ||||
|                                                               || mapdrawendY > ((int)Constants.RegionSize - 1)) | ||||
|                                             continue; | ||||
| 
 | ||||
|     #region obb face reconstruction part duex | ||||
|                                         Vector3[] vertexes = new Vector3[8]; | ||||
| 
 | ||||
|                                         // float[] distance = new float[6]; | ||||
|                                         Vector3[] FaceA = new Vector3[6]; // vertex A for Facei | ||||
|                                         Vector3[] FaceB = new Vector3[6]; // vertex B for Facei | ||||
|                                         Vector3[] FaceC = new Vector3[6]; // vertex C for Facei | ||||
|                                         Vector3[] FaceD = new Vector3[6]; // vertex D for Facei | ||||
| 
 | ||||
|                                         tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
|                                         // vertexes[0].x = pos.X + vertexes[0].x; | ||||
|                                         //vertexes[0].y = pos.Y + vertexes[0].y; | ||||
|                                         //vertexes[0].z = pos.Z + vertexes[0].z; | ||||
| 
 | ||||
|                                         FaceA[0] = vertexes[0]; | ||||
|                                         FaceB[3] = vertexes[0]; | ||||
|                                         FaceA[4] = vertexes[0]; | ||||
| 
 | ||||
|                                         tScale = lscale; | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         // vertexes[1].x = pos.X + vertexes[1].x; | ||||
|                                         // vertexes[1].y = pos.Y + vertexes[1].y; | ||||
|                                         //vertexes[1].z = pos.Z + vertexes[1].z; | ||||
| 
 | ||||
|                                         FaceB[0] = vertexes[1]; | ||||
|                                         FaceA[1] = vertexes[1]; | ||||
|                                         FaceC[4] = vertexes[1]; | ||||
| 
 | ||||
|                                         tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
| 
 | ||||
|                                         vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         //vertexes[2].x = pos.X + vertexes[2].x; | ||||
|                                         //vertexes[2].y = pos.Y + vertexes[2].y; | ||||
|                                         //vertexes[2].z = pos.Z + vertexes[2].z; | ||||
| 
 | ||||
|                                         FaceC[0] = vertexes[2]; | ||||
|                                         FaceD[3] = vertexes[2]; | ||||
|                                         FaceC[5] = vertexes[2]; | ||||
| 
 | ||||
|                                         tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         //vertexes[3].x = pos.X + vertexes[3].x; | ||||
|                                         // vertexes[3].y = pos.Y + vertexes[3].y; | ||||
|                                         // vertexes[3].z = pos.Z + vertexes[3].z; | ||||
| 
 | ||||
|                                         FaceD[0] = vertexes[3]; | ||||
|                                         FaceC[1] = vertexes[3]; | ||||
|                                         FaceA[5] = vertexes[3]; | ||||
| 
 | ||||
|                                         tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         // vertexes[4].x = pos.X + vertexes[4].x; | ||||
|                                         // vertexes[4].y = pos.Y + vertexes[4].y; | ||||
|                                         // vertexes[4].z = pos.Z + vertexes[4].z; | ||||
| 
 | ||||
|                                         FaceB[1] = vertexes[4]; | ||||
|                                         FaceA[2] = vertexes[4]; | ||||
|                                         FaceD[4] = vertexes[4]; | ||||
| 
 | ||||
|                                         tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         // vertexes[5].x = pos.X + vertexes[5].x; | ||||
|                                         // vertexes[5].y = pos.Y + vertexes[5].y; | ||||
|                                         // vertexes[5].z = pos.Z + vertexes[5].z; | ||||
| 
 | ||||
|                                         FaceD[1] = vertexes[5]; | ||||
|                                         FaceC[2] = vertexes[5]; | ||||
|                                         FaceB[5] = vertexes[5]; | ||||
| 
 | ||||
|                                         tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         // vertexes[6].x = pos.X + vertexes[6].x; | ||||
|                                         // vertexes[6].y = pos.Y + vertexes[6].y; | ||||
|                                         // vertexes[6].z = pos.Z + vertexes[6].z; | ||||
| 
 | ||||
|                                         FaceB[2] = vertexes[6]; | ||||
|                                         FaceA[3] = vertexes[6]; | ||||
|                                         FaceB[4] = vertexes[6]; | ||||
| 
 | ||||
|                                         tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); | ||||
|                                         scale = ((tScale * rot)); | ||||
|                                         vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); | ||||
| 
 | ||||
|                                         // vertexes[7].x = pos.X + vertexes[7].x; | ||||
|                                         // vertexes[7].y = pos.Y + vertexes[7].y; | ||||
|                                         // vertexes[7].z = pos.Z + vertexes[7].z; | ||||
| 
 | ||||
|                                         FaceD[2] = vertexes[7]; | ||||
|                                         FaceC[3] = vertexes[7]; | ||||
|                                         FaceD[5] = vertexes[7]; | ||||
|     #endregion | ||||
| 
 | ||||
|                                         //int wy = 0; | ||||
| 
 | ||||
|                                         //bool breakYN = false; // If we run into an error drawing, break out of the | ||||
|                                         // loop so we don't lag to death on error handling | ||||
|                                         DrawStruct ds = new DrawStruct(); | ||||
|                                         ds.brush = new SolidBrush(mapdotspot); | ||||
|                                         //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); | ||||
| 
 | ||||
|                                         ds.trns = new face[FaceA.Length]; | ||||
| 
 | ||||
|                                         for (int i = 0; i < FaceA.Length; i++) | ||||
|                                         { | ||||
|                                             Point[] working = new Point[5]; | ||||
|                                             working[0] = project(FaceA[i], axPos); | ||||
|                                             working[1] = project(FaceB[i], axPos); | ||||
|                                             working[2] = project(FaceD[i], axPos); | ||||
|                                             working[3] = project(FaceC[i], axPos); | ||||
|                                             working[4] = project(FaceA[i], axPos); | ||||
| 
 | ||||
|                                             face workingface = new face(); | ||||
|                                             workingface.pts = working; | ||||
| 
 | ||||
|                                             ds.trns[i] = workingface; | ||||
|                                         } | ||||
| 
 | ||||
|                                         z_sort.Add(part.LocalId, ds); | ||||
|                                         z_localIDs.Add(part.LocalId); | ||||
|                                         z_sortheights.Add(pos.Z); | ||||
| 
 | ||||
|                                         //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) | ||||
|                                         //{ | ||||
|                                             //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); | ||||
|                                             //try | ||||
|                                             //for (wy = mapdrawstartY; wy < mapdrawendY; wy++) | ||||
|                                             //{ | ||||
|                                                 // Remember, flip the y! | ||||
|                                             //    mapbmp.SetPixel(wx, (255 - wy), mapdotspot); | ||||
|                                             //} | ||||
|                                             //catch (ArgumentException) | ||||
|                                             //{ | ||||
|                                             //    breakYN = true; | ||||
|                                                 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); | ||||
|                                                 //try | ||||
|                                                 //{ | ||||
|                                                     // Remember, flip the y! | ||||
|                                                 //    mapbmp.SetPixel(wx, (255 - wy), mapdotspot); | ||||
|                                                 //} | ||||
|                                                 //catch (ArgumentException) | ||||
|                                                 //{ | ||||
|                                                 //    breakYN = true; | ||||
|                                                 //} | ||||
| 
 | ||||
|                                                 //if (breakYN) | ||||
|                                                 //    break; | ||||
|                                             //} | ||||
| 
 | ||||
|                                             //if (breakYN) | ||||
|                                             //    break; | ||||
|                                         //} | ||||
|                                     } // Object is within 256m Z of terrain | ||||
|                                 } // object is at least a meter wide | ||||
|                             } // loop over group children | ||||
|                         } // entitybase is sceneobject group | ||||
|                     } // foreach loop over entities | ||||
| 
 | ||||
|                                         //if (breakYN) | ||||
|                                         //    break; | ||||
|                                     //} | ||||
|                                 } // Object is within 256m Z of terrain | ||||
|                             } // object is at least a meter wide | ||||
|                         } // loop over group children | ||||
|                     } // entitybase is sceneobject group | ||||
|                 } // foreach loop over entities | ||||
|                     float[] sortedZHeights = z_sortheights.ToArray(); | ||||
|                     uint[] sortedlocalIds = z_localIDs.ToArray(); | ||||
| 
 | ||||
|                 float[] sortedZHeights = z_sortheights.ToArray(); | ||||
|                 uint[] sortedlocalIds = z_localIDs.ToArray(); | ||||
|                     // Sort prim by Z position | ||||
|                     Array.Sort(sortedZHeights, sortedlocalIds); | ||||
| 
 | ||||
|                 // Sort prim by Z position | ||||
|                 Array.Sort(sortedZHeights, sortedlocalIds); | ||||
| 
 | ||||
|                 Graphics g = Graphics.FromImage(mapbmp); | ||||
| 
 | ||||
|                 for (int s = 0; s < sortedZHeights.Length; s++) | ||||
|                 { | ||||
|                     if (z_sort.ContainsKey(sortedlocalIds[s])) | ||||
|                     using (Graphics g = Graphics.FromImage(mapbmp)) | ||||
|                     { | ||||
|                         DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; | ||||
|                         for (int r = 0; r < rectDrawStruct.trns.Length; r++) | ||||
|                         for (int s = 0; s < sortedZHeights.Length; s++) | ||||
|                         { | ||||
|                             g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); | ||||
|                             if (z_sort.ContainsKey(sortedlocalIds[s])) | ||||
|                             { | ||||
|                                 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; | ||||
|                                 for (int r = 0; r < rectDrawStruct.trns.Length; r++) | ||||
|                                 { | ||||
|                                     g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); | ||||
|                                 } | ||||
|                                 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect); | ||||
|                             } | ||||
|                         } | ||||
|                         //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect); | ||||
|                     } | ||||
|                 } | ||||
|                 } // lock entities objs | ||||
| 
 | ||||
|                 g.Dispose(); | ||||
|             } // lock entities objs | ||||
|             } | ||||
|             finally | ||||
|             { | ||||
|                 foreach (DrawStruct ds in z_sort.Values) | ||||
|                     ds.brush.Dispose(); | ||||
|             } | ||||
| 
 | ||||
|             m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); | ||||
| 
 | ||||
|             return mapbmp; | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|         public void TerrainToBitmap(Bitmap mapbmp) | ||||
|         { | ||||
|             int tc = Environment.TickCount; | ||||
|             m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); | ||||
|             m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain"); | ||||
| 
 | ||||
|             double[,] hm = m_scene.Heightmap.GetDoubles(); | ||||
|             bool ShadowDebugContinue = true; | ||||
|  | @ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|                         { | ||||
|                             if (!terraincorruptedwarningsaid) | ||||
|                             { | ||||
|                                 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); | ||||
|                                 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); | ||||
|                                 terraincorruptedwarningsaid = true; | ||||
|                             } | ||||
|                             color = Color.Black; | ||||
|  | @ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|                         { | ||||
|                             if (!terraincorruptedwarningsaid) | ||||
|                             { | ||||
|                                 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); | ||||
|                                 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); | ||||
|                                 terraincorruptedwarningsaid = true; | ||||
|                             } | ||||
|                             Color black = Color.Black; | ||||
|  | @ -238,7 +238,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); | ||||
| 
 | ||||
|             m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|         private Bitmap fetchTexture(UUID id) | ||||
|         { | ||||
|             AssetBase asset = m_scene.AssetService.Get(id.ToString()); | ||||
|             m_log.DebugFormat("[TexturedMapTileRenderer]: Fetched texture {0}, found: {1}", id, asset != null); | ||||
|             m_log.DebugFormat("[TEXTURED MAP TILE RENDERER]: Fetched texture {0}, found: {1}", id, asset != null); | ||||
|             if (asset == null) return null; | ||||
| 
 | ||||
|             ManagedImage managedImage; | ||||
|  | @ -188,17 +188,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|             } | ||||
|             catch (DllNotFoundException) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system.   Asset Data is empty for {0}", id); | ||||
|                 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg is not installed correctly on this system.   Asset Data is empty for {0}", id); | ||||
|                  | ||||
|             } | ||||
|             catch (IndexOutOfRangeException) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this.   Asset Data is empty for {0}", id); | ||||
|                 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this.   Asset Data is empty for {0}", id); | ||||
|                  | ||||
|             } | ||||
|             catch (Exception) | ||||
|             { | ||||
|                 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this.   Asset Data is empty for {0}", id); | ||||
|                 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this.   Asset Data is empty for {0}", id); | ||||
|                  | ||||
|             } | ||||
|             return null; | ||||
|  | @ -233,10 +233,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|             if (textureID == UUID.Zero) return defaultColor; // not set | ||||
|             if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures | ||||
| 
 | ||||
|             Bitmap bmp = fetchTexture(textureID); | ||||
|             Color color = bmp == null ? defaultColor : computeAverageColor(bmp); | ||||
|             // store it for future reference | ||||
|             m_mapping[textureID] = color; | ||||
|             Color color; | ||||
| 
 | ||||
|             using (Bitmap bmp = fetchTexture(textureID)) | ||||
|             { | ||||
|                 color = bmp == null ? defaultColor : computeAverageColor(bmp); | ||||
|                 // store it for future reference | ||||
|                 m_mapping[textureID] = color; | ||||
|             } | ||||
| 
 | ||||
|             return color; | ||||
|         } | ||||
|  | @ -278,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|         public void TerrainToBitmap(Bitmap mapbmp) | ||||
|         { | ||||
|             int tc = Environment.TickCount; | ||||
|             m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); | ||||
|             m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain"); | ||||
| 
 | ||||
|             // These textures should be in the AssetCache anyway, as every client conneting to this | ||||
|             // region needs them. Except on start, when the map is recreated (before anyone connected), | ||||
|  | @ -412,7 +416,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap | |||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); | ||||
| 
 | ||||
|             m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -1501,62 +1501,69 @@ namespace OpenSim.Region.CoreModules.World.WorldMap | |||
| 
 | ||||
|         private Byte[] GenerateOverlay() | ||||
|         { | ||||
|             Bitmap overlay = new Bitmap(256, 256); | ||||
| 
 | ||||
|             bool[,] saleBitmap = new bool[64, 64]; | ||||
|             for (int x = 0 ; x < 64 ; x++) | ||||
|             using (Bitmap overlay = new Bitmap(256, 256)) | ||||
|             { | ||||
|                 for (int y = 0 ; y < 64 ; y++) | ||||
|                     saleBitmap[x, y] = false; | ||||
|             } | ||||
| 
 | ||||
|             bool landForSale = false; | ||||
| 
 | ||||
|             List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); | ||||
| 
 | ||||
|             Color background = Color.FromArgb(0, 0, 0, 0); | ||||
|             SolidBrush transparent = new SolidBrush(background); | ||||
|             Graphics g = Graphics.FromImage(overlay); | ||||
|             g.FillRectangle(transparent, 0, 0, 256, 256); | ||||
| 
 | ||||
|             SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); | ||||
| 
 | ||||
|             foreach (ILandObject land in parcels) | ||||
|             { | ||||
|                 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags); | ||||
|                 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0) | ||||
|                 bool[,] saleBitmap = new bool[64, 64]; | ||||
|                 for (int x = 0 ; x < 64 ; x++) | ||||
|                 { | ||||
|                     landForSale = true; | ||||
|                     for (int y = 0 ; y < 64 ; y++) | ||||
|                         saleBitmap[x, y] = false; | ||||
|                 } | ||||
| 
 | ||||
|                     saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); | ||||
|                 bool landForSale = false; | ||||
| 
 | ||||
|                 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); | ||||
| 
 | ||||
|                 Color background = Color.FromArgb(0, 0, 0, 0); | ||||
| 
 | ||||
|                 using (Graphics g = Graphics.FromImage(overlay)) | ||||
|                 { | ||||
|                     using (SolidBrush transparent = new SolidBrush(background)) | ||||
|                         g.FillRectangle(transparent, 0, 0, 256, 256); | ||||
| 
 | ||||
| 
 | ||||
|                     foreach (ILandObject land in parcels) | ||||
|                     { | ||||
|                         // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags); | ||||
|                         if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0) | ||||
|                         { | ||||
|                             landForSale = true; | ||||
| 
 | ||||
|                             saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     if (!landForSale) | ||||
|                     { | ||||
|                         m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); | ||||
|                         return null; | ||||
|                     } | ||||
| 
 | ||||
|                     m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName); | ||||
| 
 | ||||
|                     using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9))) | ||||
|                     { | ||||
|                         for (int x = 0 ; x < 64 ; x++) | ||||
|                         { | ||||
|                             for (int y = 0 ; y < 64 ; y++) | ||||
|                             { | ||||
|                                 if (saleBitmap[x, y]) | ||||
|                                     g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 try | ||||
|                 { | ||||
|                     return OpenJPEG.EncodeFromImage(overlay, true); | ||||
|                 } | ||||
|                 catch (Exception e) | ||||
|                 { | ||||
|                     m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString()); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!landForSale) | ||||
|             { | ||||
|                 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); | ||||
|                 return null; | ||||
|             } | ||||
| 
 | ||||
|             m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName); | ||||
| 
 | ||||
|             for (int x = 0 ; x < 64 ; x++) | ||||
|             { | ||||
|                 for (int y = 0 ; y < 64 ; y++) | ||||
|                 { | ||||
|                     if (saleBitmap[x, y]) | ||||
|                         g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 return OpenJPEG.EncodeFromImage(overlay, true); | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString()); | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Justin Clark-Casey (justincc)
						Justin Clark-Casey (justincc)