From b1cb4f5b04f076c067842de6971ec1016b9a3912 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 11 Nov 2011 21:42:58 +0000 Subject: [PATCH] As per mailing list last week, remove facility that would automatically move the avatar if prim with no sit target was out of sitting range. Now, no movement occurs. Note that you can still sit on a prim with an explicit sit target from any distance, as was the case before. --- .../Region/Framework/Scenes/ScenePresence.cs | 391 ++++++++---------- .../Scenes/Tests/ScenePresenceSitTests.cs | 33 +- 2 files changed, 197 insertions(+), 227 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index e098c6279d..6979d2ef2f 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -188,20 +188,12 @@ namespace OpenSim.Region.Framework.Scenes private readonly Vector3[] Dir_Vectors = new Vector3[11]; - protected Timer m_reprioritization_timer; protected bool m_reprioritizing; protected bool m_reprioritization_called; private Quaternion m_headrotation = Quaternion.Identity; - //Reuse the Vector3 instead of creating a new one on the UpdateMovement method -// private Vector3 movementvector; - - private bool m_autopilotMoving; - private Vector3 m_autoPilotTarget; - private bool m_sitAtAutoTarget; - private string m_nextSitAnimation = String.Empty; //PauPaw:Proper PID Controler for autopilot************ @@ -1417,9 +1409,6 @@ namespace OpenSim.Region.Framework.Scenes } } - if (m_autopilotMoving) - CheckAtSitTarget(); - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) { m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. @@ -1636,111 +1625,109 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); - if (!m_autopilotMoving) - { - double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); + double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); + // m_log.DebugFormat( // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); - // Check the error term of the current position in relation to the target position - if (distanceToTarget <= 1) + // Check the error term of the current position in relation to the target position + if (distanceToTarget <= 1) + { + // We are close enough to the target + AbsolutePosition = MoveToPositionTarget; + ResetMoveToTarget(); + updated = true; + } + else + { + try { - // We are close enough to the target - AbsolutePosition = MoveToPositionTarget; - ResetMoveToTarget(); - updated = true; - } - else - { - try - { - // move avatar in 3D at one meter/second towards target, in avatar coordinate frame. - // This movement vector gets added to the velocity through AddNewMovement(). - // Theoretically we might need a more complex PID approach here if other - // unknown forces are acting on the avatar and we need to adaptively respond - // to such forces, but the following simple approach seems to works fine. - Vector3 LocalVectorToTarget3D = - (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords - * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords - // Ignore z component of vector + // move avatar in 3D at one meter/second towards target, in avatar coordinate frame. + // This movement vector gets added to the velocity through AddNewMovement(). + // Theoretically we might need a more complex PID approach here if other + // unknown forces are acting on the avatar and we need to adaptively respond + // to such forces, but the following simple approach seems to works fine. + Vector3 LocalVectorToTarget3D = + (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords + * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords + // Ignore z component of vector // Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); - LocalVectorToTarget3D.Normalize(); + LocalVectorToTarget3D.Normalize(); - // update avatar movement flags. the avatar coordinate system is as follows: - // - // +X (forward) - // - // ^ - // | - // | - // | - // | - // (left) +Y <--------o--------> -Y - // avatar - // | - // | - // | - // | - // v - // -X - // + // update avatar movement flags. the avatar coordinate system is as follows: + // + // +X (forward) + // + // ^ + // | + // | + // | + // | + // (left) +Y <--------o--------> -Y + // avatar + // | + // | + // | + // | + // v + // -X + // - // based on the above avatar coordinate system, classify the movement into - // one of left/right/back/forward. - if (LocalVectorToTarget3D.X < 0) //MoveBack - { - MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - updated = true; - } - else if (LocalVectorToTarget3D.X > 0) //Move Forward - { - MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - updated = true; - } + // based on the above avatar coordinate system, classify the movement into + // one of left/right/back/forward. + if (LocalVectorToTarget3D.X < 0) //MoveBack + { + MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + updated = true; + } + else if (LocalVectorToTarget3D.X > 0) //Move Forward + { + MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + updated = true; + } - if (LocalVectorToTarget3D.Y > 0) //MoveLeft - { - MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - updated = true; - } - else if (LocalVectorToTarget3D.Y < 0) //MoveRight - { - MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - updated = true; - } + if (LocalVectorToTarget3D.Y > 0) //MoveLeft + { + MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + updated = true; + } + else if (LocalVectorToTarget3D.Y < 0) //MoveRight + { + MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + updated = true; + } - if (LocalVectorToTarget3D.Z > 0) //Up - { - // Don't set these flags for up or down - doing so will make the avatar crouch or - // keep trying to jump even if walking along level ground - //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; - //AgentControlFlags - //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; - updated = true; - } - else if (LocalVectorToTarget3D.Z < 0) //Down - { - //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN; - //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN; - updated = true; - } + if (LocalVectorToTarget3D.Z > 0) //Up + { + // Don't set these flags for up or down - doing so will make the avatar crouch or + // keep trying to jump even if walking along level ground + //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; + //AgentControlFlags + //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; + updated = true; + } + else if (LocalVectorToTarget3D.Z < 0) //Down + { + //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN; + //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN; + updated = true; + } // m_log.DebugFormat( // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", // LocalVectorToTarget3D, agent_control_v3, Name); - agent_control_v3 += LocalVectorToTarget3D; - } - catch (Exception e) - { - //Avoid system crash, can be slower but... - m_log.DebugFormat("Crash! {0}", e.ToString()); - } + agent_control_v3 += LocalVectorToTarget3D; + } + catch (Exception e) + { + //Avoid system crash, can be slower but... + m_log.DebugFormat("Crash! {0}", e.ToString()); } } @@ -1842,47 +1829,6 @@ namespace OpenSim.Region.Framework.Scenes AgentControlFlags = (uint)AgentManager.ControlFlags.NONE; } - private void CheckAtSitTarget() - { - //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString()); - if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5) - { - if (m_sitAtAutoTarget) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID); - if (part != null) - { - AbsolutePosition = part.AbsolutePosition; - Velocity = Vector3.Zero; - SendAvatarDataToAllAgents(); - - //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); - } - //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); - m_requestedSitTargetUUID = UUID.Zero; - } - /* - else - { - //ControllingClient.SendAlertMessage("Autopilot cancelled"); - //SendTerseUpdateToAllClients(); - //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; - //proxy.PCode = (byte)PCode.ParticleSystem; - ////uint nextUUID = m_scene.NextLocalId; - - //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy); - //if (proxyObjectGroup != null) - //{ - //proxyObjectGroup.SendGroupFullUpdate(); - //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); - //m_scene.DeleteSceneObject(proxyObjectGroup); - //} - } - */ - m_autoPilotTarget = Vector3.Zero; - m_autopilotMoving = false; - } - } /// /// Perform the logic necessary to stand the avatar up. This method also executes /// the stand animation. @@ -1893,7 +1839,7 @@ namespace OpenSim.Region.Framework.Scenes if (ParentID != 0) { - m_log.Debug("StandupCode Executed"); +// m_log.Debug("StandupCode Executed"); SceneObjectPart part = m_scene.GetSceneObjectPart(ParentID); if (part != null) { @@ -1983,7 +1929,6 @@ namespace OpenSim.Region.Framework.Scenes private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) { - bool autopilot = true; Vector3 pos = new Vector3(); Quaternion sitOrientation = pSitOrientation; Vector3 cameraEyeOffset = Vector3.Zero; @@ -1991,86 +1936,85 @@ namespace OpenSim.Region.Framework.Scenes bool forceMouselook = false; SceneObjectPart part = FindNextAvailableSitTarget(targetID); - if (part != null) - { - // TODO: determine position to sit at based on scene geometry; don't trust offset from client - // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it + if (part == null) + return; - // Is a sit target available? - Vector3 avSitOffSet = part.SitTargetPosition; - Quaternion avSitOrientation = part.SitTargetOrientation; - UUID avOnTargetAlready = part.SitTargetAvatar; + // TODO: determine position to sit at based on scene geometry; don't trust offset from client + // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); - bool SitTargetisSet = - (!(avSitOffSet == Vector3.Zero && - ( - avSitOrientation == Quaternion.Identity // Valid Zero Rotation quaternion - || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point - || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion - ) - )); + // Is a sit target available? + Vector3 avSitOffSet = part.SitTargetPosition; + Quaternion avSitOrientation = part.SitTargetOrientation; + UUID avOnTargetAlready = part.SitTargetAvatar; + + bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); + bool SitTargetisSet = + (!(avSitOffSet == Vector3.Zero && + ( + avSitOrientation == Quaternion.Identity // Valid Zero Rotation quaternion + || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point + || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion + ) + )); // m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied); - if (SitTargetisSet && SitTargetUnOccupied) + if (PhysicsActor != null) + m_sitAvatarHeight = m_physicsActor.Size.Z; + + bool canSit = false; + pos = part.AbsolutePosition + offset; + + if (SitTargetisSet) + { + if (SitTargetUnOccupied) { + m_log.DebugFormat( + "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied", + Name, part.Name, part.LocalId); + part.SitTargetAvatar = UUID; offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); sitOrientation = avSitOrientation; - autopilot = false; + canSit = true; } - pos = part.AbsolutePosition + offset; - //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) - //{ - // offset = pos; - //autopilot = false; - //} + } + else + { + if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) + { + m_log.DebugFormat( + "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m", + Name, part.Name, part.LocalId); + + AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); + canSit = true; + } + } + + if (canSit) + { if (PhysicsActor != null) { - // If we're not using the client autopilot, we're immediately warping the avatar to the location // We can remove the physicsActor until they stand up. - m_sitAvatarHeight = PhysicsActor.Size.Z; - - if (autopilot) - { - if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) - { - autopilot = false; - - RemoveFromPhysicalScene(); - AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); - } - } - else - { - RemoveFromPhysicalScene(); - } + RemoveFromPhysicalScene(); } cameraAtOffset = part.GetCameraAtOffset(); cameraEyeOffset = part.GetCameraEyeOffset(); forceMouselook = part.GetForceMouselook(); - } - ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); - m_requestedSitTargetUUID = targetID; + ControllingClient.SendSitResponse( + targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); + + m_requestedSitTargetUUID = targetID; - // This calls HandleAgentSit twice, once from here, and the client calls - // HandleAgentSit itself after it gets to the location - // It doesn't get to the location until we've moved them there though - // which happens in HandleAgentSit :P - m_autopilotMoving = autopilot; - m_autoPilotTarget = pos; - m_sitAtAutoTarget = autopilot; - if (!autopilot) HandleAgentSit(remoteClient, UUID); - // Moved here to avoid a race with default sit anim - // The script event needs to be raised after the default sit anim is set. - if (part != null) + // Moved here to avoid a race with default sit anim + // The script event needs to be raised after the default sit anim is set. part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); - + } } // public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation) @@ -2099,11 +2043,11 @@ namespace OpenSim.Region.Framework.Scenes { m_nextSitAnimation = part.SitAnimation; } + m_requestedSitTargetID = part.LocalId; - //m_requestedSitOffset = offset; m_requestedSitTargetUUID = targetID; - m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); +// m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); if (m_scene.PhysicsScene.SupportsRayCast()) { @@ -2328,43 +2272,40 @@ namespace OpenSim.Region.Framework.Scenes { SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); - if (m_sitAtAutoTarget || !m_autopilotMoving) + if (part != null) { - if (part != null) + if (part.SitTargetAvatar == UUID) { - if (part.SitTargetAvatar == UUID) - { - Vector3 sitTargetPos = part.SitTargetPosition; - Quaternion sitTargetOrient = part.SitTargetOrientation; + Vector3 sitTargetPos = part.SitTargetPosition; + Quaternion sitTargetOrient = part.SitTargetOrientation; // m_log.DebugFormat( // "[SCENE PRESENCE]: Sitting {0} at sit target {1}, {2} on {3} {4}", // Name, sitTargetPos, sitTargetOrient, part.Name, part.LocalId); - //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0); - //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w); + //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0); + //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w); - //Quaternion result = (sitTargetOrient * vq) * nq; + //Quaternion result = (sitTargetOrient * vq) * nq; - m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; - Rotation = sitTargetOrient; - ParentPosition = part.AbsolutePosition; - } - else - { - m_pos -= part.AbsolutePosition; - ParentPosition = part.AbsolutePosition; + m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; + Rotation = sitTargetOrient; + ParentPosition = part.AbsolutePosition; + } + else + { + m_pos -= part.AbsolutePosition; + ParentPosition = part.AbsolutePosition; // m_log.DebugFormat( // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", // Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); - } - } - else - { - return; } } + else + { + return; + } ParentID = m_requestedSitTargetID; diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs index 2636473af8..a1d30f3848 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs @@ -53,7 +53,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests } [Test] - public void TestSitOutsideRange() + public void TestSitOutsideRangeNoTarget() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests } [Test] - public void TestSitWithinRange() + public void TestSitWithinRangeNoTarget() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -124,5 +124,34 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); Assert.That(sp.ParentID, Is.EqualTo(0)); } + + [Test] + public void TestSitAndStandWithSitTarget() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); + + // If a prim has a sit target then we can sit from any distance away + Vector3 startPos = new Vector3(128, 128, 30); + sp.AbsolutePosition = startPos; + + SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene); + part.SitTargetPosition = new Vector3(0, 0, 1); + + sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, part.UUID, Vector3.Zero); + + Assert.That(part.SitTargetAvatar, Is.EqualTo(sp.UUID)); + Assert.That(sp.ParentID, Is.EqualTo(part.LocalId)); + Assert.That( + sp.AbsolutePosition, + Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); + + sp.StandUp(); + + Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); + Assert.That(sp.ParentID, Is.EqualTo(0)); + } } } \ No newline at end of file