diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 180 |
1 files changed, 141 insertions, 39 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 443e7a5..67dee02 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -126,11 +126,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
126 | m_TransferModule = | 126 | m_TransferModule = |
127 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); | 127 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); |
128 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); | 128 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); |
129 | if (m_UrlModule != null) | ||
130 | { | ||
131 | m_ScriptEngine.OnScriptRemoved += m_UrlModule.ScriptRemoved; | ||
132 | m_ScriptEngine.OnObjectRemoved += m_UrlModule.ObjectRemoved; | ||
133 | } | ||
134 | 129 | ||
135 | AsyncCommands = new AsyncCommandManager(ScriptEngine); | 130 | AsyncCommands = new AsyncCommandManager(ScriptEngine); |
136 | } | 131 | } |
@@ -468,26 +463,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
468 | 463 | ||
469 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke | 464 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke |
470 | 465 | ||
471 | // Old implementation of llRot2Euler. Normalization not required as Atan2 function will | 466 | /// <summary> |
472 | // only return values >= -PI (-180 degrees) and <= PI (180 degrees). | 467 | /// Convert an LSL rotation to a Euler vector. |
473 | 468 | /// </summary> | |
469 | /// <remarks> | ||
470 | /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf | ||
471 | /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2 | ||
472 | /// </remarks> | ||
473 | /// <param name="r"></param> | ||
474 | /// <returns></returns> | ||
474 | public LSL_Vector llRot2Euler(LSL_Rotation r) | 475 | public LSL_Vector llRot2Euler(LSL_Rotation r) |
475 | { | 476 | { |
476 | m_host.AddScriptLPS(1); | 477 | m_host.AddScriptLPS(1); |
477 | //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke | 478 | |
478 | LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); | 479 | LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. |
479 | double m = (t.x + t.y + t.z + t.s); | 480 | double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. |
480 | if (m == 0) return new LSL_Vector(); | 481 | if (m == 0.0) return new LSL_Vector(); |
481 | double n = 2 * (r.y * r.s + r.x * r.z); | 482 | double x = Math.Atan2(-v.y, v.z); |
482 | double p = m * m - n * n; | 483 | double sin = v.x / m; |
483 | if (p > 0) | 484 | if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. |
484 | return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), | 485 | double y = Math.Asin(sin); |
485 | Math.Atan2(n, Math.Sqrt(p)), | 486 | // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation |
486 | Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); | 487 | v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); |
487 | else if (n > 0) | 488 | double z = Math.Atan2(v.y, v.x); |
488 | return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); | 489 | |
489 | else | 490 | return new LSL_Vector(x, y, z); |
490 | return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); | ||
491 | } | 491 | } |
492 | 492 | ||
493 | /* From wiki: | 493 | /* From wiki: |
@@ -2856,11 +2856,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2856 | // we need to convert from a vector describing | 2856 | // we need to convert from a vector describing |
2857 | // the angles of rotation in radians into rotation value | 2857 | // the angles of rotation in radians into rotation value |
2858 | 2858 | ||
2859 | LSL_Types.Quaternion rot = llEuler2Rot(angle); | 2859 | LSL_Rotation rot = llEuler2Rot(angle); |
2860 | Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); | 2860 | |
2861 | m_host.startLookAt(rotation, (float)damping, (float)strength); | 2861 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply |
2862 | // Orient the object to the angle calculated | 2862 | // set the rotation of the object, copy that behavior |
2863 | //llSetRot(rot); | 2863 | if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical) |
2864 | { | ||
2865 | llSetRot(rot); | ||
2866 | } | ||
2867 | else | ||
2868 | { | ||
2869 | m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); | ||
2870 | } | ||
2864 | } | 2871 | } |
2865 | 2872 | ||
2866 | public void llStopLookAt() | 2873 | public void llStopLookAt() |
@@ -3236,8 +3243,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3236 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) | 3243 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) |
3237 | { | 3244 | { |
3238 | m_host.AddScriptLPS(1); | 3245 | m_host.AddScriptLPS(1); |
3239 | Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s); | 3246 | |
3240 | m_host.RotLookAt(rot, (float)strength, (float)damping); | 3247 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply |
3248 | // set the rotation of the object, copy that behavior | ||
3249 | if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical) | ||
3250 | { | ||
3251 | llSetLocalRot(target); | ||
3252 | } | ||
3253 | else | ||
3254 | { | ||
3255 | m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); | ||
3256 | } | ||
3241 | } | 3257 | } |
3242 | 3258 | ||
3243 | public LSL_Integer llStringLength(string str) | 3259 | public LSL_Integer llStringLength(string str) |
@@ -4023,9 +4039,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4023 | Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), | 4039 | Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), |
4024 | Util.Clip((float)color.y, 0.0f, 1.0f), | 4040 | Util.Clip((float)color.y, 0.0f, 1.0f), |
4025 | Util.Clip((float)color.z, 0.0f, 1.0f)); | 4041 | Util.Clip((float)color.z, 0.0f, 1.0f)); |
4026 | m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); | 4042 | m_host.SetText(text.Length > 254 ? text.Remove(255) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); |
4027 | m_host.ParentGroup.HasGroupChanged = true; | 4043 | //m_host.ParentGroup.HasGroupChanged = true; |
4028 | m_host.ParentGroup.ScheduleGroupForFullUpdate(); | 4044 | //m_host.ParentGroup.ScheduleGroupForFullUpdate(); |
4029 | } | 4045 | } |
4030 | 4046 | ||
4031 | public LSL_Float llWater(LSL_Vector offset) | 4047 | public LSL_Float llWater(LSL_Vector offset) |
@@ -4693,15 +4709,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4693 | return (double)Math.Asin(val); | 4709 | return (double)Math.Asin(val); |
4694 | } | 4710 | } |
4695 | 4711 | ||
4696 | // Xantor 30/apr/2008 | 4712 | // jcochran 5/jan/2012 |
4697 | public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) | 4713 | public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) |
4698 | { | 4714 | { |
4699 | m_host.AddScriptLPS(1); | 4715 | m_host.AddScriptLPS(1); |
4700 | 4716 | ||
4701 | double angle = Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2; | 4717 | double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s); |
4702 | if (angle < 0) angle = -angle; | 4718 | double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s); |
4703 | if (angle > Math.PI) return (Math.PI * 2 - angle); | 4719 | double aa_bb = aa * bb; |
4704 | return angle; | 4720 | if (aa_bb == 0) return 0.0; |
4721 | double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s); | ||
4722 | double quotient = (ab * ab) / aa_bb; | ||
4723 | if (quotient >= 1.0) return 0.0; | ||
4724 | return Math.Acos(2 * quotient - 1); | ||
4705 | } | 4725 | } |
4706 | 4726 | ||
4707 | public LSL_String llGetInventoryKey(string name) | 4727 | public LSL_String llGetInventoryKey(string name) |
@@ -5486,7 +5506,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5486 | 5506 | ||
5487 | foreach (GridRegion sri in neighbors) | 5507 | foreach (GridRegion sri in neighbors) |
5488 | { | 5508 | { |
5489 | if (sri.RegionLocX == neighborX && sri.RegionLocY == neighborY) | 5509 | if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY) |
5490 | return 0; | 5510 | return 0; |
5491 | } | 5511 | } |
5492 | 5512 | ||
@@ -6583,7 +6603,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6583 | } | 6603 | } |
6584 | 6604 | ||
6585 | // the rest of the permission checks are done in RezScript, so check the pin there as well | 6605 | // the rest of the permission checks are done in RezScript, so check the pin there as well |
6586 | World.RezScript(srcId, m_host, destId, pin, running, start_param); | 6606 | World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); |
6607 | |||
6587 | // this will cause the delay even if the script pin or permissions were wrong - seems ok | 6608 | // this will cause the delay even if the script pin or permissions were wrong - seems ok |
6588 | ScriptSleep(3000); | 6609 | ScriptSleep(3000); |
6589 | } | 6610 | } |
@@ -7546,6 +7567,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7546 | ScriptSleep(2000); | 7567 | ScriptSleep(2000); |
7547 | } | 7568 | } |
7548 | 7569 | ||
7570 | public LSL_String llGetParcelMusicURL() | ||
7571 | { | ||
7572 | m_host.AddScriptLPS(1); | ||
7573 | |||
7574 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
7575 | |||
7576 | if (land.LandData.OwnerID != m_host.OwnerID) | ||
7577 | return String.Empty; | ||
7578 | |||
7579 | return land.GetMusicUrl(); | ||
7580 | } | ||
7581 | |||
7549 | public LSL_Vector llGetRootPosition() | 7582 | public LSL_Vector llGetRootPosition() |
7550 | { | 7583 | { |
7551 | m_host.AddScriptLPS(1); | 7584 | m_host.AddScriptLPS(1); |
@@ -10613,6 +10646,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10613 | return list; | 10646 | return list; |
10614 | } | 10647 | } |
10615 | 10648 | ||
10649 | public LSL_Integer llManageEstateAccess(int action, string avatar) | ||
10650 | { | ||
10651 | m_host.AddScriptLPS(1); | ||
10652 | EstateSettings estate = World.RegionInfo.EstateSettings; | ||
10653 | bool isAccount = false; | ||
10654 | bool isGroup = false; | ||
10655 | |||
10656 | if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManager(m_host.OwnerID)) | ||
10657 | return 0; | ||
10658 | |||
10659 | UUID id = new UUID(); | ||
10660 | if (!UUID.TryParse(avatar, out id)) | ||
10661 | return 0; | ||
10662 | |||
10663 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id); | ||
10664 | isAccount = account != null ? true : false; | ||
10665 | if (!isAccount) | ||
10666 | { | ||
10667 | IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); | ||
10668 | if (groups != null) | ||
10669 | { | ||
10670 | GroupRecord group = groups.GetGroupRecord(id); | ||
10671 | isGroup = group != null ? true : false; | ||
10672 | if (!isGroup) | ||
10673 | return 0; | ||
10674 | } | ||
10675 | else | ||
10676 | return 0; | ||
10677 | } | ||
10678 | |||
10679 | switch (action) | ||
10680 | { | ||
10681 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: | ||
10682 | if (!isAccount) return 0; | ||
10683 | if (estate.HasAccess(id)) return 1; | ||
10684 | if (estate.IsBanned(id)) | ||
10685 | estate.RemoveBan(id); | ||
10686 | estate.AddEstateUser(id); | ||
10687 | break; | ||
10688 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE: | ||
10689 | if (!isAccount || !estate.HasAccess(id)) return 0; | ||
10690 | estate.RemoveEstateUser(id); | ||
10691 | break; | ||
10692 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD: | ||
10693 | if (!isGroup) return 0; | ||
10694 | if (estate.GroupAccess(id)) return 1; | ||
10695 | estate.AddEstateGroup(id); | ||
10696 | break; | ||
10697 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE: | ||
10698 | if (!isGroup || !estate.GroupAccess(id)) return 0; | ||
10699 | estate.RemoveEstateGroup(id); | ||
10700 | break; | ||
10701 | case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: | ||
10702 | if (!isAccount) return 0; | ||
10703 | if (estate.IsBanned(id)) return 1; | ||
10704 | EstateBan ban = new EstateBan(); | ||
10705 | ban.EstateID = estate.EstateID; | ||
10706 | ban.BannedUserID = id; | ||
10707 | estate.AddBan(ban); | ||
10708 | break; | ||
10709 | case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: | ||
10710 | if (!isAccount || !estate.IsBanned(id)) return 0; | ||
10711 | estate.RemoveBan(id); | ||
10712 | break; | ||
10713 | default: return 0; | ||
10714 | } | ||
10715 | return 1; | ||
10716 | } | ||
10717 | |||
10616 | #region Not Implemented | 10718 | #region Not Implemented |
10617 | // | 10719 | // |
10618 | // Listing the unimplemented lsl functions here, please move | 10720 | // Listing the unimplemented lsl functions here, please move |