Merge branch 'master' into careminster

Conflicts:
	OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
	OpenSim/Framework/Servers/VersionInfo.cs
avinationmerge
Melanie 2012-09-07 19:49:46 +01:00
commit 924df14c5e
29 changed files with 686 additions and 75 deletions

1
.gitignore vendored
View File

@ -69,6 +69,7 @@ Examples/*.dll
OpenSim.build
OpenSim.sln
OpenSim.suo
OpenSim.userprefs
Prebuild/Prebuild.build
Prebuild/Prebuild.sln
TestResult.xml

View File

@ -92,6 +92,7 @@ what it is today.
* Flyte Xevious
* Garmin Kawaguichi
* Gryc Ueusp
* Hiro Lecker
* Imaze Rhiano
* Intimidated
* Jeremy Bongio (IBM)

View File

@ -163,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
if (texture == null)
{
//m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
// Fetch locally or remotely. Misses return a 404
texture = m_assetService.Get(textureID.ToString());
@ -197,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
}
else // it was on the cache
{
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
WriteTextureData(httpRequest, httpResponse, texture, format);
return true;
}
@ -219,14 +219,30 @@ namespace OpenSim.Capabilities.Handlers
int start, end;
if (TryParseRange(range, out start, out end))
{
// Before clamping start make sure we can satisfy it in order to avoid
// sending back the last byte instead of an error status
if (start >= texture.Data.Length)
{
// m_log.DebugFormat(
// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
// texture.ID, start, texture.Data.Length);
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
// of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
// received a very small texture may attempt to fetch bytes from the server past the
// range of data that it received originally. Whether this happens appears to depend on whether
// the viewer's estimation of how large a request it needs to make for certain discard levels
// (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
// level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
// here will cause the viewer to treat the texture as bad and never display the full resolution
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
// viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
response.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentType = texture.Metadata.ContentType;
}
else
{
@ -234,12 +250,18 @@ namespace OpenSim.Capabilities.Handlers
start = Utils.Clamp(start, 0, end);
int len = end - start + 1;
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
// Always return PartialContent, even if the range covered the entire data length
// We were accidentally sending back 404 before in this situation
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
//
// We also do not want to send back OK even if the whole range was satisfiable since this causes
// HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
// if (end > maxEnd)
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
// else
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
response.ContentLength = len;
@ -368,4 +390,4 @@ namespace OpenSim.Capabilities.Handlers
return null;
}
}
}
}

View File

@ -29,7 +29,7 @@ namespace OpenSim
{
public class VersionInfo
{
private const string VERSION_NUMBER = "0.7.4CM";
private const string VERSION_NUMBER = "0.7.5CM";
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
public enum Flavour

View File

@ -49,12 +49,8 @@ using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
[assembly: Addin("FlotsamAssetCache", "1.1")]
[assembly: AddinDependency("OpenSim", "0.5")]
namespace Flotsam.RegionModules.AssetCache
namespace OpenSim.Region.CoreModules.Asset
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
{
private static readonly ILog m_log =

View File

@ -35,7 +35,7 @@ using Nini.Config;
using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Assets;
using Flotsam.RegionModules.AssetCache;
using OpenSim.Region.CoreModules.Asset;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;

View File

@ -34,6 +34,7 @@
<RegionModule id="LureModule" type="OpenSim.Region.CoreModules.Avatar.Lure.LureModule" />
<RegionModule id="InventoryTransferModule" type="OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.InventoryTransferModule" />
<RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.CoreAssetCache" />
<RegionModule id="FlotsamAssetCache" type="OpenSim.Region.CoreModules.Asset.FlotsamAssetCache" />
<RegionModule id="GlynnTuckerAssetCache" type="OpenSim.Region.CoreModules.Asset.GlynnTuckerAssetCache" />
<RegionModule id="CenomeMemoryAssetCache" type="OpenSim.Region.CoreModules.Asset.CenomeMemoryAssetCache"/>
<RegionModule id="LibraryModule" type="OpenSim.Region.CoreModules.Framework.Library.LibraryModule"/>

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Drawing;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
public class DynamicTexture : IDynamicTexture
{
public string InputCommands { get; private set; }
public Uri InputUri { get; private set; }
public string InputParams { get; private set; }
public byte[] Data { get; private set; }
public Size Size { get; private set; }
public bool IsReuseable { get; private set; }
public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
{
InputCommands = inputCommands;
InputParams = inputParams;
Data = data;
Size = size;
IsReuseable = isReuseable;
}
public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
{
InputUri = inputUri;
InputParams = inputParams;
Data = data;
Size = size;
IsReuseable = isReuseable;
}
}
}

View File

@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
{
//private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int ALL_SIDES = -1;
@ -54,6 +54,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
/// </summary>
public bool ReuseTextures { get; set; }
/// <summary>
/// If false, then textures which have a low data size are not reused when ReuseTextures = true.
/// </summary>
/// <remarks>
/// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
/// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
/// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
/// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
/// to work around this problem.</remarks>
public bool ReuseLowDataTextures { get; set; }
private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@ -83,18 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
/// <summary>
/// Called by code which actually renders the dynamic texture to supply texture data.
/// </summary>
/// <param name="id"></param>
/// <param name="data"></param>
/// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param>
public void ReturnData(UUID id, byte[] data, bool isReuseable)
/// <param name="updaterId"></param>
/// <param name="texture"></param>
public void ReturnData(UUID updaterId, IDynamicTexture texture)
{
DynamicTextureUpdater updater = null;
lock (Updaters)
{
if (Updaters.ContainsKey(id))
if (Updaters.ContainsKey(updaterId))
{
updater = Updaters[id];
updater = Updaters[updaterId];
}
}
@ -103,11 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (RegisteredScenes.ContainsKey(updater.SimUUID))
{
Scene scene = RegisteredScenes[updater.SimUUID];
UUID newTextureID = updater.DataReceived(data, scene);
UUID newTextureID = updater.DataReceived(texture.Data, scene);
if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
if (ReuseTextures
&& !updater.BlendWithOldTexture
&& texture.IsReuseable
&& (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
{
m_reuseableDynamicTextures.Store(
GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
}
}
}
@ -123,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
}
/// <summary>
/// Determines whether the texture is reuseable based on its data size.
/// </summary>
/// <remarks>
/// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
/// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
/// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
/// </remarks>
/// <returns></returns>
private bool IsDataSizeReuseable(IDynamicTexture texture)
{
// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
// m_log.DebugFormat(
// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
// discardLevel2DataThreshold, texture.Data.Length);
return discardLevel2DataThreshold < texture.Data.Length;
}
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
string extraParams, int updateTimer)
{
@ -249,10 +285,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
}
}
// m_log.DebugFormat(
// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
// part.Name, part.ParentGroup.Scene.Name);
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
}
else
{
// m_log.DebugFormat(
// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
// No need to add to updaters as the texture is always the same. Not that this functionality
// apppears to be implemented anyway.
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
@ -285,7 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
IConfig texturesConfig = config.Configs["Textures"];
if (texturesConfig != null)
{
ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
}
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{
@ -448,8 +495,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
if (cacheLayerDecode != null)
{
cacheLayerDecode.Decode(asset.FullID, asset.Data);
cacheLayerDecode = null;
if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
m_log.WarnFormat(
"[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
asset.ID, part.Name, part.ParentGroup.Scene.Name);
}
UUID oldID = UpdatePart(part, asset.FullID);

View File

@ -32,6 +32,7 @@ using System.Net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
@ -73,12 +74,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
// return false;
// }
public byte[] ConvertUrl(string url, string extraParams)
public IDynamicTexture ConvertUrl(string url, string extraParams)
{
return null;
}
public byte[] ConvertData(string bodyData, string extraParams)
public IDynamicTexture ConvertData(string bodyData, string extraParams)
{
return null;
}
@ -171,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
private void HttpRequestReturn(IAsyncResult result)
{
RequestState state = (RequestState) result.AsyncState;
WebRequest request = (WebRequest) state.Request;
Stream stream = null;
byte[] imageJ2000 = new byte[0];
Size newSize = new Size(0, 0);
try
{
@ -188,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
try
{
Bitmap image = new Bitmap(stream);
Size newsize;
// TODO: make this a bit less hard coded
if ((image.Height < 64) && (image.Width < 64))
{
newsize = new Size(32, 32);
newSize.Width = 32;
newSize.Height = 32;
}
else if ((image.Height < 128) && (image.Width < 128))
{
newsize = new Size(64, 64);
newSize.Width = 64;
newSize.Height = 64;
}
else if ((image.Height < 256) && (image.Width < 256))
{
newsize = new Size(128, 128);
newSize.Width = 128;
newSize.Height = 128;
}
else if ((image.Height < 512 && image.Width < 512))
{
newsize = new Size(256, 256);
newSize.Width = 256;
newSize.Height = 256;
}
else if ((image.Height < 1024 && image.Width < 1024))
{
newsize = new Size(512, 512);
newSize.Width = 512;
newSize.Height = 512;
}
else
{
newsize = new Size(1024, 1024);
newSize.Width = 1024;
newSize.Height = 1024;
}
Bitmap resize = new Bitmap(image, newsize);
imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
using (Bitmap resize = new Bitmap(image, newSize))
{
imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
}
}
catch (Exception)
{
@ -233,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
}
catch (WebException)
{
}
finally
{
@ -243,10 +249,13 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
}
}
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
imageJ2000.Length, state.RequestID);
m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
m_textureManager.ReturnData(
state.RequestID,
new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
request.RequestUri, null, imageJ2000, newSize, false));
}
#region Nested type: RequestState

View File

@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
m_dtm = new DynamicTextureModule();
m_dtm.ReuseTextures = reuseTextures;
// m_dtm.ReuseLowDataTextures = reuseTextures;
m_vrm = new VectorRenderModule();
@ -201,6 +202,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
public void TestRepeatSameDrawReusingTexture()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
@ -228,6 +230,46 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
/// <summary>
/// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
/// problems for current viewers.
/// </summary>
/// <remarks>
/// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
/// texture
/// </remarks>
[Test]
public void TestRepeatSameDrawLowDataTexture()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
SetupScene(true);
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"1024",
0);
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
m_dtm.AddDynamicTextureData(
m_scene.RegionInfo.RegionID,
so.UUID,
m_vrm.GetContentType(),
dtText,
"1024",
0);
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
[Test]
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
{

View File

@ -35,6 +35,7 @@ using System.Net;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Imaging;
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using log4net;
@ -46,6 +47,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
public class VectorRenderModule : IRegionModule, IDynamicTextureRender
{
// These fields exist for testing purposes, please do not remove.
// private static bool s_flipper;
// private static byte[] s_asset1Data;
// private static byte[] s_asset2Data;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
@ -80,20 +86,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
// return lines.Any((str, r) => str.StartsWith("Image"));
// }
public byte[] ConvertUrl(string url, string extraParams)
public IDynamicTexture ConvertUrl(string url, string extraParams)
{
return null;
}
public byte[] ConvertData(string bodyData, string extraParams)
public IDynamicTexture ConvertData(string bodyData, string extraParams)
{
bool reuseable;
return Draw(bodyData, extraParams, out reuseable);
}
private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
{
return Draw(bodyData, extraParams, out reuseable);
return Draw(bodyData, extraParams);
}
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@ -104,10 +104,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{
// XXX: This isn't actually being done asynchronously!
bool reuseable;
byte[] data = ConvertData(bodyData, extraParams, out reuseable);
m_textureManager.ReturnData(id, data, reuseable);
m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
return true;
}
@ -161,6 +158,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
m_textureManager.RegisterRender(GetContentType(), this);
}
// This code exists for testing purposes, please do not remove.
// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
// Terrain dirt - smallest bin/assets file (6004 bytes)
// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
}
public void Close()
@ -179,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion
private byte[] Draw(string data, string extraParams, out bool reuseable)
private IDynamicTexture Draw(string data, string extraParams)
{
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@ -322,6 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
Bitmap bitmap = null;
Graphics graph = null;
bool reuseable = false;
try
{
@ -364,6 +369,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
byte[] imageJ2000 = new byte[0];
// This code exists for testing purposes, please do not remove.
// if (s_flipper)
// imageJ2000 = s_asset1Data;
// else
// imageJ2000 = s_asset2Data;
//
// s_flipper = !s_flipper;
try
{
@ -376,7 +389,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
e.Message, e.StackTrace);
}
return imageJ2000;
return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
data, extraParams, imageJ2000, new Size(width, height), reuseable);
}
finally
{

View File

@ -43,7 +43,7 @@ using OpenSim.Tests.Common;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
{
[TestFixture]
public class GridConnectorsTests
public class GridConnectorsTests : OpenSimTestCase
{
LocalGridServicesConnector m_LocalConnector;
private void SetUp()

View File

@ -51,7 +51,7 @@ using RegionSettings = OpenSim.Framework.RegionSettings;
namespace OpenSim.Region.CoreModules.World.Archiver.Tests
{
[TestFixture]
public class ArchiverTests
public class ArchiverTests : OpenSimTestCase
{
private Guid m_lastRequestId;
private string m_lastErrorMessage;

View File

@ -222,6 +222,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
}
// XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
// afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
// then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
// this map tile simply takes a lot of memory.
GC.Collect();
m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
return bitmap;
}

View File

@ -25,6 +25,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Drawing;
using System.IO;
using OpenMetaverse;
@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IDynamicTextureManager
{
void RegisterRender(string handleType, IDynamicTextureRender render);
void ReturnData(UUID id, byte[] data, bool isReuseable);
/// <summary>
/// Used by IDynamicTextureRender implementations to return renders
/// </summary>
/// <param name='id'></param>
/// <param name='data'></param>
/// <param name='isReuseable'></param>
void ReturnData(UUID id, IDynamicTexture texture);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer);
@ -125,11 +134,53 @@ namespace OpenSim.Region.Framework.Interfaces
// /// <param name='extraParams'></param>
// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
byte[] ConvertUrl(string url, string extraParams);
byte[] ConvertData(string bodyData, string extraParams);
IDynamicTexture ConvertUrl(string url, string extraParams);
IDynamicTexture ConvertData(string bodyData, string extraParams);
bool AsyncConvertUrl(UUID id, string url, string extraParams);
bool AsyncConvertData(UUID id, string bodyData, string extraParams);
void GetDrawStringSize(string text, string fontName, int fontSize,
out double xSize, out double ySize);
}
public interface IDynamicTexture
{
/// <summary>
/// Input commands used to generate this data.
/// </summary>
/// <remarks>
/// Null if input commands were not used.
/// </remarks>
string InputCommands { get; }
/// <summary>
/// Uri used to generate this data.
/// </summary>
/// <remarks>
/// Null if a uri was not used.
/// </remarks>
Uri InputUri { get; }
/// <summary>
/// Extra input params used to generate this data.
/// </summary>
string InputParams { get; }
/// <summary>
/// Texture data.
/// </summary>
byte[] Data { get; }
/// <summary>
/// Size of texture.
/// </summary>
Size Size { get; }
/// <summary>
/// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
/// texture).
/// </summary>
bool IsReuseable { get; }
}
}

View File

@ -4810,6 +4810,18 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.GetSceneObjectGroup(name);
}
/// <summary>
/// Attempt to get the SOG via its UUID
/// </summary>
/// <param name="fullID"></param>
/// <param name="sog"></param>
/// <returns></returns>
public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
{
sog = GetSceneObjectGroup(fullID);
return sog != null;
}
/// <summary>
/// Get a prim by name from the scene (will return the first
/// found, if there are more than one prim with the same name)
@ -4841,6 +4853,18 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.GetSceneObjectPart(fullID);
}
/// <summary>
/// Attempt to get a prim via its UUID
/// </summary>
/// <param name="fullID"></param>
/// <param name="sop"></param>
/// <returns></returns>
public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
{
sop = GetSceneObjectPart(fullID);
return sop != null;
}
/// <summary>
/// Get a scene object group that contains the prim with the given local id
/// </summary>

View File

@ -3631,13 +3631,16 @@ namespace OpenSim.Region.Framework.Scenes
public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
{
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
lock (m_attachments)
if (attachmentPoint >= 0)
{
foreach (SceneObjectGroup so in m_attachments)
lock (m_attachments)
{
if (attachmentPoint == so.AttachmentPoint)
attachments.Add(so);
foreach (SceneObjectGroup so in m_attachments)
{
if (attachmentPoint == so.AttachmentPoint)
attachments.Add(so);
}
}
}

View File

@ -39,11 +39,8 @@ using OpenSim.Framework.Console;
using OpenSim.Region.Physics.Manager;
using Mono.Addins;
[assembly: Addin("RegionCombinerModule", "0.1")]
[assembly: AddinDependency("OpenSim", "0.5")]
namespace OpenSim.Region.RegionCombinerModule
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

View File

@ -0,0 +1,14 @@
<Addin id="OpenSim.RegionModules.RegionCombinerModule" version="0.3">
<Runtime>
<Import assembly="OpenSim.Region.RegionCombinerModule.dll"/>
</Runtime>
<Dependencies>
<Addin id="OpenSim" version="0.5" />
</Dependencies>
<Extension path = "/OpenSim/RegionModules">
<RegionModule id="RegionCombinerModule" type="OpenSim.Region.RegionCombinerModule.RegionCombinerModule" />
</Extension>
</Addin>

View File

@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// ---------- Integer ----------
else if (lslparm is LSL_Integer)
{
if (type == typeof(int))
if (type == typeof(int) || type == typeof(float))
return (int)(LSL_Integer)lslparm;
}

View File

@ -1682,6 +1682,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return;
}
MessageObject(objUUID, message);
}
private void MessageObject(UUID objUUID, string message)
{
object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
@ -3272,6 +3277,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
#region Attachment commands
public void osForceAttachToAvatar(int attachmentPoint)
{
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
@ -3361,6 +3368,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
((LSL_Api)m_LSL_Api).DetachFromAvatar();
}
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
{
CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
m_host.AddScriptLPS(1);
UUID targetUUID;
ScenePresence target;
LSL_List resp = new LSL_List();
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
{
foreach (object point in attachmentPoints.Data)
{
LSL_Integer ipoint = new LSL_Integer(
(point is LSL_Integer || point is int || point is uint) ?
(int)point :
0
);
resp.Add(ipoint);
if (ipoint == 0)
{
// indicates zero attachments
resp.Add(new LSL_Integer(0));
}
else
{
// gets the number of attachments on the attachment point
resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
}
}
}
return resp;
}
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
{
CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
m_host.AddScriptLPS(1);
UUID targetUUID;
ScenePresence target;
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
{
List<int> aps = new List<int>();
foreach (object point in attachmentPoints.Data)
{
int ipoint;
if (int.TryParse(point.ToString(), out ipoint))
{
aps.Add(ipoint);
}
}
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
if (msgAll && invertPoints)
{
return;
}
else if (msgAll || invertPoints)
{
attachments = target.GetAttachments();
}
else
{
foreach (int point in aps)
{
if (point > 0)
{
attachments.AddRange(target.GetAttachments((uint)point));
}
}
}
// if we have no attachments at this point, exit now
if (attachments.Count == 0)
{
return;
}
List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
if (invertPoints)
{
foreach (SceneObjectGroup attachment in attachments)
{
if (aps.Contains((int)attachment.AttachmentPoint))
{
ignoreThese.Add(attachment);
}
}
}
foreach (SceneObjectGroup attachment in ignoreThese)
{
attachments.Remove(attachment);
}
ignoreThese.Clear();
// if inverting removed all attachments to check, exit now
if (attachments.Count < 1)
{
return;
}
if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
{
foreach (SceneObjectGroup attachment in attachments)
{
if (attachment.RootPart.CreatorID != m_host.CreatorID)
{
ignoreThese.Add(attachment);
}
}
foreach (SceneObjectGroup attachment in ignoreThese)
{
attachments.Remove(attachment);
}
ignoreThese.Clear();
// if filtering by same object creator removed all
// attachments to check, exit now
if (attachments.Count == 0)
{
return;
}
}
if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
{
foreach (SceneObjectGroup attachment in attachments)
{
if (attachment.RootPart.CreatorID != m_item.CreatorID)
{
ignoreThese.Add(attachment);
}
}
foreach (SceneObjectGroup attachment in ignoreThese)
{
attachments.Remove(attachment);
}
ignoreThese.Clear();
// if filtering by object creator must match originating
// script creator removed all attachments to check,
// exit now
if (attachments.Count == 0)
{
return;
}
}
foreach (SceneObjectGroup attachment in attachments)
{
MessageObject(attachment.RootPart.UUID, message);
}
}
}
#endregion
/// <summary>
/// Checks if thing is a UUID.
/// </summary>

View File

@ -157,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void osAvatarPlayAnimation(string avatar, string animation);
void osAvatarStopAnimation(string avatar, string animation);
// Attachment commands
#region Attachment commands
/// <summary>
/// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
@ -192,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
/// <remarks>Nothing happens if the object is not attached.</remarks>
void osForceDetachFromAvatar();
/// <summary>
/// Returns a strided list of the specified attachment points and the number of attachments on those points.
/// </summary>
/// <param name="avatar">avatar UUID</param>
/// <param name="attachmentPoints">list of ATTACH_* constants</param>
/// <returns></returns>
LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
/// <summary>
/// Sends a specified message to the specified avatar's attachments on
/// the specified attachment points.
/// </summary>
/// <remarks>
/// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
/// </remarks>
/// <param name="avatar">avatar UUID</param>
/// <param name="message">message string</param>
/// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
/// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
#endregion
//texture draw functions
string osMovePen(string drawList, int x, int y);
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);

View File

@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int ATTACH_HUD_BOTTOM = 37;
public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
#region osMessageAttachments constants
/// <summary>
/// Instructs osMessageAttachements to send the message to attachments
/// on every point.
/// </summary>
/// <remarks>
/// One might expect this to be named OS_ATTACH_ALL, but then one might
/// also expect functions designed to attach or detach or get
/// attachments to work with it too. Attaching a no-copy item to
/// many attachments could be dangerous.
/// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
/// message from being sent.
/// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
/// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
/// sent- this is expected behaviour.
/// </remarks>
public const int OS_ATTACH_MSG_ALL = -65535;
/// <summary>
/// Instructs osMessageAttachements to invert how the attachment points
/// list should be treated (e.g. go from inclusive operation to
/// exclusive operation).
/// </summary>
/// <remarks>
/// This might be used if you want to deliver a message to one set of
/// attachments and a different message to everything else. With
/// this flag, you only need to build one explicit list for both calls.
/// </remarks>
public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
/// <summary>
/// Instructs osMessageAttachments to only send the message to
/// attachments with a CreatorID that matches the host object CreatorID
/// </summary>
/// <remarks>
/// This would be used if distributed in an object vendor/updater server.
/// </remarks>
public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
/// <summary>
/// Instructs osMessageAttachments to only send the message to
/// attachments with a CreatorID that matches the sending script CreatorID
/// </summary>
/// <remarks>
/// This might be used if the script is distributed independently of a
/// containing object.
/// </remarks>
public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
#endregion
public const int LAND_LEVEL = 0;
public const int LAND_RAISE = 1;
public const int LAND_LOWER = 2;

View File

@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
}
// Avatar functions
#region Attachment commands
public void osForceAttachToAvatar(int attachmentPoint)
{
@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_OSSL_Functions.osForceDetachFromAvatar();
}
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
{
return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
}
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
{
m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
}
#endregion
// Texture Draw functions
public string osMovePen(string drawList, int x, int y)

View File

@ -26,6 +26,7 @@
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
@ -71,10 +72,17 @@ namespace OpenSim.Server.Base
//
private string m_pidFile = String.Empty;
/// <summary>
/// Time at which this server was started
/// </summary>
protected DateTime m_startuptime;
// Handle all the automagical stuff
//
public ServicesServerBase(string prompt, string[] args)
{
m_startuptime = DateTime.Now;
// Save raw arguments
//
m_Arguments = args;
@ -250,6 +258,10 @@ namespace OpenSim.Server.Base
"command-script <script>",
"Run a command script from file", HandleScript);
MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
"show uptime",
"Show server uptime", HandleShow);
// Allow derived classes to perform initialization that
// needs to be done after the console has opened
@ -345,5 +357,34 @@ namespace OpenSim.Server.Base
{
}
}
public virtual void HandleShow(string module, string[] cmd)
{
List<string> args = new List<string>(cmd);
args.RemoveAt(0);
string[] showParams = args.ToArray();
switch (showParams[0])
{
case "uptime":
MainConsole.Instance.Output(GetUptimeReport());
break;
}
}
/// <summary>
/// Return a report about the uptime of this server
/// </summary>
/// <returns></returns>
protected string GetUptimeReport()
{
StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
return sb.ToString();
}
}
}

View File

@ -703,6 +703,13 @@
; Default is false.
ReuseDynamicTextures = false
; If true, then textures generated dynamically that have a low data size relative to their pixel size are not reused
; This is to workaround an apparent LL 3.3.4 and earlier viewer bug where such textures are not redisplayed properly when pulled from the viewer cache.
; Only set this to true if you are sure that all the viewers using your simulator will not suffer from this problem.
; This setting only has an affect is ReuseDynamicTextures = true
; Default is false
ReuseDynamicLowDataTextures = false
[ODEPhysicsSettings]
; ##

View File

@ -104,6 +104,12 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
; (replace spaces with underscore)
;; Allow Hyperlinks to be created at the console
HypergridLinker = true
Gatekeeper = "http://127.0.0.1:8002"
; * This is the configuration for the freeswitch server in grid mode
[FreeswitchService]
LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService"

View File

@ -36,8 +36,6 @@
SimulationServiceInConnector = true
MapImageServiceInConnector = true
[Profile]
Module = "BasicProfileModule"
[Messaging]
MessageTransferModule = HGMessageTransferModule
@ -97,6 +95,10 @@
GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
GridService = "OpenSim.Services.GridService.dll:GridService"
InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService"
AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 to show a default "Ruth" avatar rather than a cloud.
CreateDefaultAvatarEntries = true
[GridUserService]
LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"