diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs index 91252f7396..df5ac92bb4 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs @@ -111,6 +111,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap asset = assetService.GetCached(cacheID.ToString()); if (asset != null) { +// m_log.DebugFormat( +// "[TERRAIN SPLAT]: Got asset service cached terrain texture {0} {1}", i, asset.ID); + try { using (System.IO.MemoryStream stream = new System.IO.MemoryStream(asset.Data)) @@ -129,6 +132,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap asset = assetService.Get(textureIDs[i].ToString()); if (asset != null) { +// m_log.DebugFormat( +// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); + try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } catch (Exception ex) { @@ -137,15 +143,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap } if (detailTexture[i] != null) - { - Bitmap bitmap = detailTexture[i]; - + { // Make sure this texture is the correct size, otherwise resize - if (bitmap.Width != 256 || bitmap.Height != 256) + if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) { - using (Bitmap origBitmap = bitmap) + using (Bitmap origBitmap = detailTexture[i]) { - bitmap = ImageUtils.ResizeImage(origBitmap, 256, 256); + detailTexture[i] = ImageUtils.ResizeImage(origBitmap, 256, 256); } } @@ -153,7 +157,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap byte[] data; using (System.IO.MemoryStream stream = new System.IO.MemoryStream()) { - bitmap.Save(stream, ImageFormat.Png); + detailTexture[i].Save(stream, ImageFormat.Png); data = stream.ToArray(); } @@ -185,6 +189,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap { if (detailTexture[i] == null) { +// m_log.DebugFormat( +// "[TERRAIN SPLAT]: Generating solid colour for missing texture {0}", i); + // Create a solid color texture for this layer detailTexture[i] = new Bitmap(256, 256, PixelFormat.Format24bppRgb); using (Graphics gfx = Graphics.FromImage(detailTexture[i])) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0ebcd8dbe6..f88338d3c6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -421,15 +421,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return LSL_Vector.Norm(v); } - public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) + private double VecDist(LSL_Vector a, LSL_Vector b) { - m_host.AddScriptLPS(1); double dx = a.x - b.x; double dy = a.y - b.y; double dz = a.z - b.z; return Math.Sqrt(dx * dx + dy * dy + dz * dz); } + public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) + { + m_host.AddScriptLPS(1); + return VecDist(a, b); + } + //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke /// @@ -1242,6 +1247,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + private bool IsPhysical() + { + return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics); + } + public LSL_Integer llGetStatus(int status) { m_host.AddScriptLPS(1); @@ -1249,11 +1259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch (status) { case ScriptBaseClass.STATUS_PHYSICS: - if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics) - { - return 1; - } - return 0; + return IsPhysical() ? 1 : 0; case ScriptBaseClass.STATUS_PHANTOM: if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) @@ -1917,11 +1923,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - SetPos(m_host, pos); + SetPos(m_host, pos, true); ScriptSleep(200); } + /// + /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos + /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into. + /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking. + /// + /// + /// 1 if successful, 0 otherwise. + public LSL_Integer llSetRegionPos(LSL_Vector pos) + { + m_host.AddScriptLPS(1); + + // BEGIN WORKAROUND + // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. + // + // This workaround is to prevent silent failure of this function. + // According to the specification on the SL Wiki, providing a position outside of the + if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize) + { + return 0; + } + // END WORK AROUND + else if ( // this is not part of the workaround if-block because it's not related to the workaround. + IsPhysical() || + m_host.ParentGroup.IsAttachment || // return FALSE if attachment + ( + pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. + pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. + pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. + pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. + pos.z > 4096 // return FALSE if altitude than 4096m + ) + ) + { + return 0; + } + + // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range. + // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. + + Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; + LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); + LandData there = World.GetLandData((float)pos.x, (float)pos.y); + + // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. + + bool sameParcel = here.GlobalID == there.GlobalID; + + if (!sameParcel && !World.Permissions.CanRezObject(m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) + { + return 0; + } + + SetPos(m_host.ParentGroup.RootPart, pos, false); + + return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0; + } + // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) // note linked setpos is capped "differently" private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end) @@ -1953,7 +2016,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return real_vec; } - protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) + /// + /// set object position, optionally capping the distance. + /// + /// + /// + /// if TRUE, will cap the distance to 10m. + protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) { // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) LSL_Vector currentPos = GetPartLocalPos(part); @@ -1966,12 +2035,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) targetPos.z = ground; SceneObjectGroup parent = part.ParentGroup; - LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); + LSL_Vector real_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); } else { - LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); + LSL_Vector rel_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index d39b20454c..3fb463b766 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -359,6 +359,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetPrimitiveParams(LSL_List rules); void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); void llSetPrimURL(string url); + LSL_Integer llSetRegionPos(LSL_Vector pos); void llSetRemoteScriptAccessPin(int pin); void llSetRot(LSL_Rotation rot); void llSetScale(LSL_Vector scale); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index a0b3bc8d4c..c4578804c2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -1618,6 +1618,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llSetPrimURL(url); } + public LSL_Integer llSetRegionPos(LSL_Vector pos) + { + return m_LSL_Functions.llSetRegionPos(pos); + } + public void llSetRemoteScriptAccessPin(int pin) { m_LSL_Functions.llSetRemoteScriptAccessPin(pin);