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