From 49d7d8534ccd037f4690c5ac6aecd66a460960df Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 19 Jun 2010 10:06:09 -0700 Subject: [PATCH] Allow moving an avatar as part of a linkset using llSetLinkPrimitiveParams. This unlocks an awful lot of poseball-free content, and is a step towards resolving mantis #59. --- .../Framework/Scenes/SceneObjectGroup.cs | 56 ++++++++++- .../Region/Framework/Scenes/ScenePresence.cs | 39 +++++++- .../Shared/Api/Implementation/LSL_Api.cs | 97 +++++++++++++++++++ 3 files changed, 188 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c7d21bba90..3e92954aed 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -110,8 +110,8 @@ namespace OpenSim.Region.Framework.Scenes private long m_minPersistTime = 0; private Random m_rand; private bool m_suspendUpdates; - - private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); + private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); + private List m_linkedAvatars = new List(); public bool areUpdatesSuspended { @@ -1115,6 +1115,47 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Add the avatar to this linkset (avatar is sat). + /// + /// + public void AddAvatar(UUID agentID) + { + ScenePresence presence; + if (m_scene.TryGetScenePresence(agentID, out presence)) + { + if (!m_linkedAvatars.Contains(presence)) + { + m_linkedAvatars.Add(presence); + } + } + } + + /// + /// Delete the avatar from this linkset (avatar is unsat). + /// + /// + public void DeleteAvatar(UUID agentID) + { + ScenePresence presence; + if (m_scene.TryGetScenePresence(agentID, out presence)) + { + if (m_linkedAvatars.Contains(presence)) + { + m_linkedAvatars.Remove(presence); + } + } + } + + /// + /// Returns the list of linked presences (avatars sat on this group) + /// + /// + public List GetLinkedAvatars() + { + return m_linkedAvatars; + } + /// /// Attach this scene object to the given avatar. /// @@ -2974,6 +3015,17 @@ namespace OpenSim.Region.Framework.Scenes } } + + + /// + /// Gets the number of parts + /// + /// + public int GetPartCount() + { + return Children.Count; + } + /// /// Get the parts of this scene object /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d4fc6cd4e9..76267ab818 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -219,6 +219,7 @@ namespace OpenSim.Region.Framework.Scenes //PauPaw:Proper PID Controler for autopilot************ private bool m_moveToPositionInProgress; private Vector3 m_moveToPositionTarget; + private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); private bool m_followCamAuto; @@ -537,10 +538,39 @@ namespace OpenSim.Region.Framework.Scenes } } + public Quaternion OffsetRotation + { + get { return m_offsetRotation; } + set { m_offsetRotation = value; } + } + public Quaternion Rotation { - get { return m_bodyRot; } - set { m_bodyRot = value; } + get { + if (m_parentID != 0) + { + if (m_offsetRotation != null) + { + return m_offsetRotation; + } + else + { + return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + + } + else + { + return m_bodyRot; + } + } + set { + m_bodyRot = value; + if (m_parentID != 0) + { + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + } } public Quaternion PreviousRotation @@ -1795,6 +1825,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! AbsolutePosition = avWorldStandUp; //KF: Fix stand up. part.IsOccupied = false; + part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); } else { @@ -1804,6 +1835,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentPosition = Vector3.Zero; m_parentID = 0; + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); SendFullUpdateToAllClients(); m_requestedSitTargetID = 0; @@ -1904,6 +1936,7 @@ namespace OpenSim.Region.Framework.Scenes part.SetAvatarOnSitTarget(UUID); // set that Av will be on it offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one sitOrientation = avSitOrientation; // Change rotatione to the scripted one + OffsetRotation = avSitOrientation; autopilot = false; // Jump direct to scripted llSitPos() } else @@ -2311,6 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes m_bodyRot = sitTargetOrient; m_parentPosition = part.AbsolutePosition; part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); Console.WriteLine("Scripted Sit ofset {0}", m_pos); } else @@ -2341,6 +2375,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); m_parentPosition = part.AbsolutePosition; part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fe8c70ee57..61c5add77c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -219,6 +219,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public List GetLinkAvatars(int linkType) + { + List ret = new List(); + if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) + return ret; + + List avs = m_host.ParentGroup.GetLinkedAvatars(); + + switch (linkType) + { + case ScriptBaseClass.LINK_SET: + return avs; + + case ScriptBaseClass.LINK_ROOT: + return ret; + + case ScriptBaseClass.LINK_ALL_OTHERS: + return avs; + + case ScriptBaseClass.LINK_ALL_CHILDREN: + return avs; + + case ScriptBaseClass.LINK_THIS: + return ret; + + default: + if (linkType < 0) + return ret; + + int partCount = m_host.ParentGroup.GetPartCount(); + + if (linkType <= partCount) + { + return ret; + } + else + { + linkType = linkType - partCount; + if (linkType > avs.Count) + { + return ret; + } + else + { + ret.Add(avs[linkType-1]); + return ret; + } + } + } + } + public List GetLinkParts(int linkType) { List ret = new List(); @@ -7152,6 +7203,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); + List avatars = GetLinkAvatars(linknumber); if (parts.Count>0) { try @@ -7165,6 +7217,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts[0].ParentGroup.areUpdatesSuspended = false; } } + if (avatars.Count > 0) + { + foreach (ScenePresence avatar in avatars) + SetPrimParams(avatar, rules); + } } public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) @@ -7172,6 +7229,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api llSetLinkPrimitiveParams(linknumber, rules); } + protected void SetPrimParams(ScenePresence av, LSL_List rules) + { + //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. + //We only support PRIM_POSITION and PRIM_ROTATION + + int idx = 0; + + while (idx < rules.Length) + { + int code = rules.GetLSLIntegerItem(idx++); + + int remain = rules.Length - idx; + + + + switch (code) + { + case (int)ScriptBaseClass.PRIM_POSITION: + if (remain < 1) + return; + LSL_Vector v; + v = rules.GetVector3Item(idx++); + av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); + av.SendFullUpdateToAllClients(); + + break; + + case (int)ScriptBaseClass.PRIM_ROTATION: + if (remain < 1) + return; + LSL_Rotation r; + r = rules.GetQuaternionItem(idx++); + av.OffsetRotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + av.SendFullUpdateToAllClients(); + break; + } + } + + } + protected void SetPrimParams(SceneObjectPart part, LSL_List rules) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)