diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 408474178b..37cfe1d25f 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -700,6 +700,7 @@ namespace OpenSim scene.LoadWorldMap(); scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName); + scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset; scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight); diff --git a/OpenSim/Region/CoreModules/World/Tests/SOGSpamTest.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs similarity index 53% rename from OpenSim/Region/CoreModules/World/Tests/SOGSpamTest.cs rename to OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 53d775ea48..9787c8c173 100644 --- a/OpenSim/Region/CoreModules/World/Tests/SOGSpamTest.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -27,11 +27,49 @@ using System; using System.Collections.Generic; -using System.Text; +using System.IO; +using System.Reflection; +using System.Threading; +using log4net.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Scripting.DynamicTexture; +using OpenSim.Region.CoreModules.Scripting.VectorRender; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; -namespace OpenSim.Region.CoreModules.World.Tests +namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests { - class SOGSpamTest + [TestFixture] + public class VectorRenderModuleTests { + [Test] + public void TestDraw() + { + TestHelpers.InMethod(); + + Scene scene = new SceneHelpers().SetupScene(); + DynamicTextureModule dtm = new DynamicTextureModule(); + VectorRenderModule vrm = new VectorRenderModule(); + SceneHelpers.SetupSceneModules(scene, dtm, vrm); + + SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); + UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; + + dtm.AddDynamicTextureData( + scene.RegionInfo.RegionID, + so.UUID, + vrm.GetContentType(), + "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", + "", + 0); + + + Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); + } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index c061868ed6..d03911101d 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -98,16 +98,18 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize) { - Font myFont = new Font(fontName, fontSize); - SizeF stringSize = new SizeF(); - lock (m_graph) { - stringSize = m_graph.MeasureString(text, myFont); - xSize = stringSize.Width; - ySize = stringSize.Height; + using (Font myFont = new Font(fontName, fontSize)) + { + SizeF stringSize = new SizeF(); + lock (m_graph) + { + stringSize = m_graph.MeasureString(text, myFont); + xSize = stringSize.Width; + ySize = stringSize.Height; + } } } - #endregion #region IRegionModule Members @@ -121,6 +123,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender if (m_graph == null) { + // We won't dispose of these explicitly since this module is only removed when the entire simulator + // is shut down. Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb); m_graph = Graphics.FromImage(bitmap); } @@ -299,53 +303,64 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } - Bitmap bitmap; - - if (alpha == 256) - { - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - } - else - { - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - } - - Graphics graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background color in their scripts, only do when fully opaque - if (alpha >= 255) - { - graph.FillRectangle(new SolidBrush(bgColor), 0, 0, width, height); - } - - for (int w = 0; w < bitmap.Width; w++) - { - if (alpha <= 255) - { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } - } - } - - GDIDraw(data, graph, altDataDelim); - - byte[] imageJ2000 = new byte[0]; + Bitmap bitmap = null; + Graphics graph = null; try { - imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Exception {0}{1}", - e.Message, e.StackTrace); - } + if (alpha == 256) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + else + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - m_textureManager.ReturnData(id, imageJ2000); + graph = Graphics.FromImage(bitmap); + + // this is really just to save people filling the + // background color in their scripts, only do when fully opaque + if (alpha >= 255) + { + using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) + { + graph.FillRectangle(bgFillBrush, 0, 0, width, height); + } + } + + for (int w = 0; w < bitmap.Width; w++) + { + if (alpha <= 255) + { + for (int h = 0; h < bitmap.Height; h++) + { + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + } + } + } + + GDIDraw(data, graph, altDataDelim); + + byte[] imageJ2000 = new byte[0]; + + try + { + imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Exception {0}{1}", + e.Message, e.StackTrace); + } + + m_textureManager.ReturnData(id, imageJ2000); + } + finally + { + if (graph != null) + graph.Dispose(); + + if (bitmap != null) + bitmap.Dispose(); + } } private int parseIntParam(string strInt) @@ -407,237 +422,284 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { Point startPoint = new Point(0, 0); Point endPoint = new Point(0, 0); - Pen drawPen = new Pen(Color.Black, 7); - string fontName = m_fontName; - float fontSize = 14; - Font myFont = new Font(fontName, fontSize); - SolidBrush myBrush = new SolidBrush(Color.Black); - - char[] lineDelimiter = {dataDelim}; - char[] partsDelimiter = {','}; - string[] lines = data.Split(lineDelimiter); + Pen drawPen = null; + Font myFont = null; + SolidBrush myBrush = null; - foreach (string line in lines) + try { - string nextLine = line.Trim(); - //replace with switch, or even better, do some proper parsing - if (nextLine.StartsWith("MoveTo")) + drawPen = new Pen(Color.Black, 7); + string fontName = m_fontName; + float fontSize = 14; + myFont = new Font(fontName, fontSize); + myBrush = new SolidBrush(Color.Black); + + char[] lineDelimiter = {dataDelim}; + char[] partsDelimiter = {','}; + string[] lines = data.Split(lineDelimiter); + + foreach (string line in lines) { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); - startPoint.X = (int) x; - startPoint.Y = (int) y; - } - else if (nextLine.StartsWith("LineTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawLine(drawPen, startPoint, endPoint); - startPoint.X = endPoint.X; - startPoint.Y = endPoint.Y; - } - else if (nextLine.StartsWith("Text")) - { - nextLine = nextLine.Remove(0, 4); - nextLine = nextLine.Trim(); - graph.DrawString(nextLine, myFont, myBrush, startPoint); - } - else if (nextLine.StartsWith("Image")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - Image image = ImageHttpRequest(nextLine); - if (image != null) + string nextLine = line.Trim(); + //replace with switch, or even better, do some proper parsing + if (nextLine.StartsWith("MoveTo")) { - graph.DrawImage(image, (float)startPoint.X, (float)startPoint.Y, x, y); + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); + startPoint.X = (int) x; + startPoint.Y = (int) y; } - else + else if (nextLine.StartsWith("LineTo")) { - graph.DrawString("URL couldn't be resolved or is", new Font(m_fontName,6), - myBrush, startPoint); - graph.DrawString("not an image. Please check URL.", new Font(m_fontName, 6), - myBrush, new Point(startPoint.X, 12 + startPoint.Y)); + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawLine(drawPen, startPoint, endPoint); + startPoint.X = endPoint.X; + startPoint.Y = endPoint.Y; + } + else if (nextLine.StartsWith("Text")) + { + nextLine = nextLine.Remove(0, 4); + nextLine = nextLine.Trim(); + graph.DrawString(nextLine, myFont, myBrush, startPoint); + } + else if (nextLine.StartsWith("Image")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + + using (Image image = ImageHttpRequest(nextLine)) + { + if (image != null) + { + graph.DrawImage(image, (float)startPoint.X, (float)startPoint.Y, x, y); + } + else + { + using (Font errorFont = new Font(m_fontName,6)) + { + graph.DrawString("URL couldn't be resolved or is", errorFont, + myBrush, startPoint); + graph.DrawString("not an image. Please check URL.", errorFont, + myBrush, new Point(startPoint.X, 12 + startPoint.Y)); + } + + graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + } + } + + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("Rectangle")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; } - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("Rectangle")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FillRectangle")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FillPolygon")) - { - PointF[] points = null; - GetParams(partsDelimiter, ref nextLine, 11, ref points); - graph.FillPolygon(myBrush, points); - } - else if (nextLine.StartsWith("Polygon")) - { - PointF[] points = null; - GetParams(partsDelimiter, ref nextLine, 7, ref points); - graph.DrawPolygon(drawPen, points); - } - else if (nextLine.StartsWith("Ellipse")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); - endPoint.X = (int)x; - endPoint.Y = (int)y; - graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FontSize")) - { - nextLine = nextLine.Remove(0, 8); - nextLine = nextLine.Trim(); - fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - myFont = new Font(fontName, fontSize); - } - else if (nextLine.StartsWith("FontProp")) - { - nextLine = nextLine.Remove(0, 8); - nextLine = nextLine.Trim(); - - string[] fprops = nextLine.Split(partsDelimiter); - foreach (string prop in fprops) + else if (nextLine.StartsWith("FillRectangle")) { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("FillPolygon")) + { + PointF[] points = null; + GetParams(partsDelimiter, ref nextLine, 11, ref points); + graph.FillPolygon(myBrush, points); + } + else if (nextLine.StartsWith("Polygon")) + { + PointF[] points = null; + GetParams(partsDelimiter, ref nextLine, 7, ref points); + graph.DrawPolygon(drawPen, points); + } + else if (nextLine.StartsWith("Ellipse")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); + endPoint.X = (int)x; + endPoint.Y = (int)y; + graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("FontSize")) + { + nextLine = nextLine.Remove(0, 8); + nextLine = nextLine.Trim(); + fontSize = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - switch (prop) + myFont.Dispose(); + myFont = new Font(fontName, fontSize); + } + else if (nextLine.StartsWith("FontProp")) + { + nextLine = nextLine.Remove(0, 8); + nextLine = nextLine.Trim(); + + string[] fprops = nextLine.Split(partsDelimiter); + foreach (string prop in fprops) { - case "B": - if (!(myFont.Bold)) - myFont = new Font(myFont, myFont.Style | FontStyle.Bold); - break; - case "I": - if (!(myFont.Italic)) - myFont = new Font(myFont, myFont.Style | FontStyle.Italic); - break; - case "U": - if (!(myFont.Underline)) - myFont = new Font(myFont, myFont.Style | FontStyle.Underline); - break; - case "S": - if (!(myFont.Strikeout)) - myFont = new Font(myFont, myFont.Style | FontStyle.Strikeout); - break; - case "R": - myFont = new Font(myFont, FontStyle.Regular); - break; + + switch (prop) + { + case "B": + if (!(myFont.Bold)) + { + Font newFont = new Font(myFont, myFont.Style | FontStyle.Bold); + myFont.Dispose(); + myFont = newFont; + } + break; + case "I": + if (!(myFont.Italic)) + { + Font newFont = new Font(myFont, myFont.Style | FontStyle.Italic); + myFont.Dispose(); + myFont = newFont; + } + break; + case "U": + if (!(myFont.Underline)) + { + Font newFont = new Font(myFont, myFont.Style | FontStyle.Underline); + myFont.Dispose(); + myFont = newFont; + } + break; + case "S": + if (!(myFont.Strikeout)) + { + Font newFont = new Font(myFont, myFont.Style | FontStyle.Strikeout); + myFont.Dispose(); + myFont = newFont; + } + break; + case "R": + Font newFont = new Font(myFont, FontStyle.Regular); + myFont.Dispose(); + myFont = newFont; + break; + } } } - } - else if (nextLine.StartsWith("FontName")) - { - nextLine = nextLine.Remove(0, 8); - fontName = nextLine.Trim(); - myFont = new Font(fontName, fontSize); - } - else if (nextLine.StartsWith("PenSize")) - { - nextLine = nextLine.Remove(0, 7); - nextLine = nextLine.Trim(); - float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - drawPen.Width = size; - } - else if (nextLine.StartsWith("PenCap")) - { - bool start = true, end = true; - nextLine = nextLine.Remove(0, 6); - nextLine = nextLine.Trim(); - string[] cap = nextLine.Split(partsDelimiter); - if (cap[0].ToLower() == "start") - end = false; - else if (cap[0].ToLower() == "end") - start = false; - else if (cap[0].ToLower() != "both") - return; - string type = cap[1].ToLower(); - - if (end) + else if (nextLine.StartsWith("FontName")) { - switch (type) + nextLine = nextLine.Remove(0, 8); + fontName = nextLine.Trim(); + myFont.Dispose(); + myFont = new Font(fontName, fontSize); + } + else if (nextLine.StartsWith("PenSize")) + { + nextLine = nextLine.Remove(0, 7); + nextLine = nextLine.Trim(); + float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); + drawPen.Width = size; + } + else if (nextLine.StartsWith("PenCap")) + { + bool start = true, end = true; + nextLine = nextLine.Remove(0, 6); + nextLine = nextLine.Trim(); + string[] cap = nextLine.Split(partsDelimiter); + if (cap[0].ToLower() == "start") + end = false; + else if (cap[0].ToLower() == "end") + start = false; + else if (cap[0].ToLower() != "both") + return; + string type = cap[1].ToLower(); + + if (end) { - case "arrow": - drawPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; - break; - case "round": - drawPen.EndCap = System.Drawing.Drawing2D.LineCap.RoundAnchor; - break; - case "diamond": - drawPen.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; - break; - case "flat": - drawPen.EndCap = System.Drawing.Drawing2D.LineCap.Flat; - break; + switch (type) + { + case "arrow": + drawPen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; + break; + case "round": + drawPen.EndCap = System.Drawing.Drawing2D.LineCap.RoundAnchor; + break; + case "diamond": + drawPen.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; + break; + case "flat": + drawPen.EndCap = System.Drawing.Drawing2D.LineCap.Flat; + break; + } + } + if (start) + { + switch (type) + { + case "arrow": + drawPen.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; + break; + case "round": + drawPen.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor; + break; + case "diamond": + drawPen.StartCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; + break; + case "flat": + drawPen.StartCap = System.Drawing.Drawing2D.LineCap.Flat; + break; + } } } - if (start) + else if (nextLine.StartsWith("PenColour") || nextLine.StartsWith("PenColor")) { - switch (type) + nextLine = nextLine.Remove(0, 9); + nextLine = nextLine.Trim(); + int hex = 0; + + Color newColor; + if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) { - case "arrow": - drawPen.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor; - break; - case "round": - drawPen.StartCap = System.Drawing.Drawing2D.LineCap.RoundAnchor; - break; - case "diamond": - drawPen.StartCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; - break; - case "flat": - drawPen.StartCap = System.Drawing.Drawing2D.LineCap.Flat; - break; + newColor = Color.FromArgb(hex); } + else + { + // this doesn't fail, it just returns black if nothing is found + newColor = Color.FromName(nextLine); + } + + myBrush.Color = newColor; + drawPen.Color = newColor; } } - else if (nextLine.StartsWith("PenColour") || nextLine.StartsWith("PenColor")) - { - nextLine = nextLine.Remove(0, 9); - nextLine = nextLine.Trim(); - int hex = 0; + } + finally + { + if (drawPen != null) + drawPen.Dispose(); - Color newColor; - if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) - { - newColor = Color.FromArgb(hex); - } - else - { - // this doesn't fail, it just returns black if nothing is found - newColor = Color.FromName(nextLine); - } + if (myFont != null) + myFont.Dispose(); - myBrush.Color = newColor; - drawPen.Color = newColor; - } + if (myBrush != null) + myBrush.Dispose(); } } @@ -691,7 +753,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { try { - WebRequest request = HttpWebRequest.Create(url); + WebRequest request = HttpWebRequest.Create(url); //Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. //Ckrinke Stream str = null; HttpWebResponse response = (HttpWebResponse)(request).GetResponse(); @@ -702,7 +764,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } catch { } + return null; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 55110dcc86..a073cb9fb8 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -154,6 +154,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) { + bool close = true; + try { lock (this) @@ -161,7 +163,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Take care of the possibilty that this thread started but was paused just outside the lock before // the final request came in (assuming that such a thing is possible) if (m_requestState == RequestState.Completed) + { + close = false; return; + } m_requestState = RequestState.Aborted; } @@ -208,7 +213,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver } finally { - m_assetsArchiver.ForceClose(); + if (close) + m_assetsArchiver.ForceClose(); } } @@ -242,11 +248,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_requestCallbackTimer.Stop(); - if (m_requestState == RequestState.Aborted) + if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed)) { m_log.WarnFormat( - "[ARCHIVER]: Received information about asset {0} after archive save abortion. Ignoring.", - id); + "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.", + id, m_requestState); return; } @@ -268,7 +274,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_notFoundAssetUuids.Add(new UUID(id)); } - if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count == m_repliesRequired) + if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired) { m_requestState = RequestState.Completed; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index d18fffde04..7e31d60650 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2131,7 +2131,8 @@ namespace OpenSim.Region.Framework.Scenes if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) sourcePart.Inventory.RemoveInventoryItem(item.ItemID); } - + + group.FromPartID = sourcePart.UUID; AddNewSceneObject(group, true, pos, rot, vel); // We can only call this after adding the scene object, since the scene object references the scene diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index eb4ba41d7b..c77457c764 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5421,5 +5421,21 @@ namespace OpenSim.Region.Framework.Scenes m_SpawnPoint = 1; return m_SpawnPoint - 1; } + + // Wrappers to get physics modules retrieve assets. Has to be done this way + // because we can't assign the asset service to physics directly - at the + // time physics are instantiated it's not registered but it will be by + // the time the first prim exists. + public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) + { + AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); + } + + private void PhysicsAssetReceived(string id, Object sender, AssetBase asset) + { + AssetReceivedDelegate callback = (AssetReceivedDelegate)sender; + + callback(asset); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 52469a2302..7b284aefaf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -26,6 +26,7 @@ */ using System; +using System.ComponentModel; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -610,6 +611,14 @@ namespace OpenSim.Region.Framework.Scenes /// public UUID FromItemID { get; set; } + /// + /// Refers to the SceneObjectPart.UUID property of the object that this object was rezzed from, if applicable. + /// + /// + /// If not applicable will be UUID.Zero + /// + public UUID FromPartID { get; set; } + /// /// The folder ID that this object was rezzed from, if applicable. /// @@ -640,6 +649,7 @@ namespace OpenSim.Region.Framework.Scenes /// The original SceneObjectPart will be used rather than a copy, preserving /// its existing localID and UUID. /// + /// Root part for this scene object. public SceneObjectGroup(SceneObjectPart part) { SetRootPart(part); @@ -649,8 +659,8 @@ namespace OpenSim.Region.Framework.Scenes /// Constructor. This object is added to the scene later via AttachToScene() /// public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) + :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) { - SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4b2fedead8..4c87639f94 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2467,7 +2467,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Schedule a terse update for this prim. Terse updates only send position, - /// rotation, velocity, rotational velocity and shape information. + /// rotation, velocity and rotational velocity information. /// public void ScheduleTerseUpdate() { diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 61aaf04bd2..d412cd1082 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -54,12 +54,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_debugEnabled = false; - public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | - GroupPowers.Accountable | - GroupPowers.JoinChat | - GroupPowers.AllowVoiceChat | - GroupPowers.ReceiveNotices | - GroupPowers.StartProposal | + public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | GroupPowers.VoteOnProposal; private bool m_connectorEnabled = false; @@ -201,8 +201,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. /// - public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, - int membershipFee, bool openEnrollment, bool allowPublish, + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, + int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { UUID GroupID = UUID.Random(); @@ -214,7 +214,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Charter"] = charter; param["ShowInList"] = showInList == true ? 1 : 0; param["InsigniaID"] = insigniaID.ToString(); - param["MembershipFee"] = 0; + param["MembershipFee"] = membershipFee; param["OpenEnrollment"] = openEnrollment == true ? 1 : 0; param["AllowPublish"] = allowPublish == true ? 1 : 0; param["MaturePublish"] = maturePublish == true ? 1 : 0; @@ -285,8 +285,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return UUID.Parse((string)respData["GroupID"]); } - public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, - UUID insigniaID, int membershipFee, bool openEnrollment, + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, + UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { Hashtable param = new Hashtable(); @@ -302,7 +302,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups XmlRpcCall(requestingAgentID, "groups.updateGroup", param); } - public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -325,7 +325,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups XmlRpcCall(requestingAgentID, "groups.removeRoleFromGroup", param); } - public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -580,7 +580,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups memberships.Add(HashTableToGroupMembershipData((Hashtable)membership)); } } - + return memberships; } @@ -800,9 +800,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) { - // If we're tracking drops for this group, + // If we're tracking drops for this group, // and we find them, well... then they've dropped - return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) + return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); } @@ -888,7 +888,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return group; } - + private static GroupMembershipData HashTableToGroupMembershipData(Hashtable respData) { GroupMembershipData data = new GroupMembershipData(); @@ -921,7 +921,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.MembershipFee = int.Parse((string)respData["MembershipFee"]); data.OpenEnrollment = ((string)respData["OpenEnrollment"] == "1"); data.ShowInList = ((string)respData["ShowInList"] == "1"); - + return data; } @@ -958,7 +958,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_memoryCache.TryGetValue(CacheKey, out resp); } } - + if (resp == null) { if (m_debugEnabled) @@ -967,7 +967,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string UserService; UUID SessionID; GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); - + param.Add("RequestingAgentID", requestingAgentID.ToString()); param.Add("RequestingAgentUserService", UserService); param.Add("RequestingSessionID", SessionID.ToString()); @@ -992,9 +992,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups catch (Exception e) { m_log.ErrorFormat( - "[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method {0} at {1}", + "[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method {0} at {1}", function, m_groupsServerURI); - + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}{1}", e.Message, e.StackTrace); foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) @@ -1061,9 +1061,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } } - + /// - /// Group Request Tokens are an attempt to allow the groups service to authenticate + /// Group Request Tokens are an attempt to allow the groups service to authenticate /// requests. /// TODO: This broke after the big grid refactor, either find a better way, or discard this /// @@ -1103,7 +1103,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } */ } - + } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a4ab702f60..ebfd85b409 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1331,13 +1331,15 @@ public sealed class BSPrim : PhysicsActor base.RequestPhysicsterseUpdate(); } + /* else { - // For debugging, we can also report the movement of children + // For debugging, we also report the movement of children DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } + */ } // I've collided with something diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 28d5cb5b62..011033cefc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -390,9 +390,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Simulate one timestep public override float Simulate(float timeStep) { - int updatedEntityCount; + int updatedEntityCount = 0; IntPtr updatedEntitiesPtr; - int collidersCount; + int collidersCount = 0; IntPtr collidersPtr; LastSimulatedTimestep = timeStep; @@ -411,8 +411,21 @@ public class BSScene : PhysicsScene, IPhysicsParameters // step the physical world one interval m_simulationStep++; - int numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, - out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); + int numSubSteps = 0; + try + { + numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, + out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); + DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); + } + catch (Exception e) + { + m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); + DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); + // updatedEntityCount = 0; + collidersCount = 0; + } + // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in @@ -711,7 +724,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters return true; } - // The calls to the PhysicsActors can't directly call into the physics engine + // Calls to the PhysicsActors can't directly call into the physics engine // because it might be busy. We delay changes to a known time. // We rely on C#'s closure to save and restore the context for the delegate. public void TaintedObject(TaintCallback callback) @@ -1275,5 +1288,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters #endregion Runtime settable parameters + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + PhysicsLogging.Write(msg, args); + } + } } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index b32cd30bec..6a0558a35e 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -43,6 +43,9 @@ namespace OpenSim.Region.Physics.Manager public delegate void JointDeactivated(PhysicsJoint joint); public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation" + public delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback); + public delegate void AssetReceivedDelegate(AssetBase asset); + /// /// Contact result from a raycast. /// @@ -73,6 +76,8 @@ namespace OpenSim.Region.Physics.Manager get { return new NullPhysicsScene(); } } + public RequestAssetDelegate RequestAssetMethod { private get; set; } + public virtual void TriggerPhysicsBasedRestart() { physicsCrash handler = OnPhysicsCrash; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 44de176609..bcd1a6f676 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3314,5 +3314,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return Math.Max(a, b); } + + public LSL_Key osGetRezzingObject() + { + CheckThreatLevel(ThreatLevel.None, "osGetRezzingObject"); + m_host.AddScriptLPS(1); + + return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); + } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index f73a85e3e7..1f000a3e77 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -299,5 +299,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// LSL_Float osMax(double a, double b); + + /// + /// Get the key of the object that rezzed this object. + /// + /// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown. + LSL_Key osGetRezzingObject(); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 53daa13d49..94405d2b5d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -945,5 +945,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osMax(a, b); } + + public LSL_Key osGetRezzingObject() + { + return m_OSSL_Functions.osGetRezzingObject(); + } } } diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index 137a9b0b18..b1f0f7e84d 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -191,7 +191,8 @@ namespace OpenSim.Services.AssetService public virtual bool Delete(string id) { - m_log.DebugFormat("[ASSET SERVICE]: Deleting asset {0}", id); +// m_log.DebugFormat("[ASSET SERVICE]: Deleting asset {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) return false; diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs index 05eb125ebc..e62bcb556d 100644 --- a/OpenSim/Services/AssetService/XAssetService.cs +++ b/OpenSim/Services/AssetService/XAssetService.cs @@ -188,7 +188,8 @@ namespace OpenSim.Services.AssetService public virtual bool Delete(string id) { - m_log.DebugFormat("[XASSET SERVICE]: Deleting asset {0}", id); +// m_log.DebugFormat("[XASSET SERVICE]: Deleting asset {0}", id); + UUID assetID; if (!UUID.TryParse(id, out assetID)) return false; diff --git a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs index 701881e32f..66a336a0c6 100644 --- a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs +++ b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs @@ -47,6 +47,9 @@ namespace pCampBot { Dictionary objects = Bot.Objects; + if (objects.Count <= 0) + return; + Primitive prim = objects.ElementAt(Bot.Random.Next(0, objects.Count - 1)).Value; // This appears to be a typical message sent when a viewer user clicks a clickable object diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index f92c55524e..ff5bdec32e 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -937,7 +937,7 @@ FixedTimeStep = .01667 MaxCollisionsPerFrame = 2048 - MaxUpdatesPerFrame = 8192 + MaxUpdatesPerFrame = 2048 [RemoteAdmin] enabled = false diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index fd8f39ab7c..03e8f26a9b 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 72847e7c6e..4e119c402f 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 300e4be8eb..6e8d6b4427 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 1acc0dd5ae..9363d1a4eb 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ diff --git a/prebuild.xml b/prebuild.xml index ea4ec250a4..6ed41a0ac7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2995,13 +2995,13 @@ --> - +