diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 200 |
1 files changed, 171 insertions, 29 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 735bd32..bd11cde 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -147,6 +147,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
147 | get { return ParentGroup.RootPart == this; } | 147 | get { return ParentGroup.RootPart == this; } |
148 | } | 148 | } |
149 | 149 | ||
150 | /// <summary> | ||
151 | /// Is an explicit sit target set for this part? | ||
152 | /// </summary> | ||
153 | public bool IsSitTargetSet | ||
154 | { | ||
155 | get | ||
156 | { | ||
157 | return | ||
158 | !(SitTargetPosition == Vector3.Zero | ||
159 | && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion | ||
160 | || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 1f && SitTargetOrientation.W == 0f // W-Z Mapping was invalid at one point | ||
161 | || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f && SitTargetOrientation.W == 0f)); // Invalid Quaternion | ||
162 | } | ||
163 | } | ||
164 | |||
150 | #region Fields | 165 | #region Fields |
151 | 166 | ||
152 | public bool AllowedDrop; | 167 | public bool AllowedDrop; |
@@ -426,7 +441,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
426 | private uint _category; | 441 | private uint _category; |
427 | private Int32 _creationDate; | 442 | private Int32 _creationDate; |
428 | private uint _parentID = 0; | 443 | private uint _parentID = 0; |
429 | private UUID m_sitTargetAvatar = UUID.Zero; | ||
430 | private uint _baseMask = (uint)PermissionMask.All; | 444 | private uint _baseMask = (uint)PermissionMask.All; |
431 | private uint _ownerMask = (uint)PermissionMask.All; | 445 | private uint _ownerMask = (uint)PermissionMask.All; |
432 | private uint _groupMask = (uint)PermissionMask.None; | 446 | private uint _groupMask = (uint)PermissionMask.None; |
@@ -738,6 +752,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
738 | return m_groupPosition; | 752 | return m_groupPosition; |
739 | } | 753 | } |
740 | 754 | ||
755 | // If I'm an attachment, my position is reported as the position of who I'm attached to | ||
741 | if (ParentGroup.IsAttachment) | 756 | if (ParentGroup.IsAttachment) |
742 | { | 757 | { |
743 | ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); | 758 | ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); |
@@ -765,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
765 | } | 780 | } |
766 | else | 781 | else |
767 | { | 782 | { |
768 | // To move the child prim in respect to the group position and rotation we have to calculate | 783 | // The physics engine always sees all objects (root or linked) in world coordinates. |
769 | actor.Position = GetWorldPosition(); | 784 | actor.Position = GetWorldPosition(); |
770 | actor.Orientation = GetWorldRotation(); | 785 | actor.Orientation = GetWorldRotation(); |
771 | } | 786 | } |
@@ -844,6 +859,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
844 | { | 859 | { |
845 | // We don't want the physics engine mucking up the rotations in a linkset | 860 | // We don't want the physics engine mucking up the rotations in a linkset |
846 | PhysicsActor actor = PhysActor; | 861 | PhysicsActor actor = PhysActor; |
862 | // If this is a root of a linkset, the real rotation is what the physics engine thinks. | ||
863 | // If not a root prim, the offset rotation is computed by SOG and is relative to the root. | ||
847 | if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) | 864 | if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) |
848 | { | 865 | { |
849 | if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f | 866 | if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f |
@@ -1024,7 +1041,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1024 | public int LinkNum | 1041 | public int LinkNum |
1025 | { | 1042 | { |
1026 | get { return m_linkNum; } | 1043 | get { return m_linkNum; } |
1027 | set { m_linkNum = value; } | 1044 | set |
1045 | { | ||
1046 | // if (ParentGroup != null) | ||
1047 | // { | ||
1048 | // m_log.DebugFormat( | ||
1049 | // "[SCENE OBJECT PART]: Setting linknum of {0}@{1} to {2} from {3}", | ||
1050 | // Name, AbsolutePosition, value, m_linkNum); | ||
1051 | // Util.PrintCallStack(); | ||
1052 | // } | ||
1053 | |||
1054 | m_linkNum = value; | ||
1055 | } | ||
1028 | } | 1056 | } |
1029 | 1057 | ||
1030 | public byte ClickAction | 1058 | public byte ClickAction |
@@ -1309,13 +1337,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1309 | } | 1337 | } |
1310 | 1338 | ||
1311 | /// <summary> | 1339 | /// <summary> |
1312 | /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero | 1340 | /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero |
1313 | /// </summary> | 1341 | /// </summary> |
1314 | public UUID SitTargetAvatar | 1342 | public UUID SitTargetAvatar { get; set; } |
1315 | { | 1343 | |
1316 | get { return m_sitTargetAvatar; } | 1344 | /// <summary> |
1317 | set { m_sitTargetAvatar = value; } | 1345 | /// IDs of all avatars start on this object part. |
1318 | } | 1346 | /// </summary> |
1347 | /// <remarks> | ||
1348 | /// We need to track this so that we can stop sat upon prims from being attached. | ||
1349 | /// </remarks> | ||
1350 | /// <value> | ||
1351 | /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene. | ||
1352 | /// </value> | ||
1353 | private HashSet<UUID> m_sittingAvatars; | ||
1319 | 1354 | ||
1320 | public virtual UUID RegionID | 1355 | public virtual UUID RegionID |
1321 | { | 1356 | { |
@@ -2111,7 +2146,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2111 | else | 2146 | else |
2112 | m_log.WarnFormat( | 2147 | m_log.WarnFormat( |
2113 | "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", | 2148 | "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", |
2114 | Name, LocalId, id); | 2149 | Name, UUID, id); |
2115 | } | 2150 | } |
2116 | 2151 | ||
2117 | /// <summary> | 2152 | /// <summary> |
@@ -2216,6 +2251,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2216 | /// <param name="isNew"></param> | 2251 | /// <param name="isNew"></param> |
2217 | public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) | 2252 | public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) |
2218 | { | 2253 | { |
2254 | if (ParentGroup.Scene == null) | ||
2255 | return; | ||
2256 | |||
2219 | if (!ParentGroup.Scene.PhysicalPrims && UsePhysics) | 2257 | if (!ParentGroup.Scene.PhysicalPrims && UsePhysics) |
2220 | return; | 2258 | return; |
2221 | 2259 | ||
@@ -2494,14 +2532,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
2494 | /// <returns>A Linked Child Prim objects position in world</returns> | 2532 | /// <returns>A Linked Child Prim objects position in world</returns> |
2495 | public Vector3 GetWorldPosition() | 2533 | public Vector3 GetWorldPosition() |
2496 | { | 2534 | { |
2497 | Quaternion parentRot = ParentGroup.RootPart.RotationOffset; | 2535 | Vector3 ret; |
2498 | Vector3 axPos = OffsetPosition; | 2536 | if (_parentID == 0) |
2499 | axPos *= parentRot; | 2537 | // if a root SOP, my position is what it is |
2500 | Vector3 translationOffsetPosition = axPos; | 2538 | ret = GroupPosition; |
2501 | if(_parentID == 0) | ||
2502 | return GroupPosition; | ||
2503 | else | 2539 | else |
2504 | return ParentGroup.AbsolutePosition + translationOffsetPosition; | 2540 | { |
2541 | // If a child SOP, my position is relative to the root SOP so take | ||
2542 | // my info and add the root's position and rotation to | ||
2543 | // get my world position. | ||
2544 | Quaternion parentRot = ParentGroup.RootPart.RotationOffset; | ||
2545 | Vector3 translationOffsetPosition = OffsetPosition * parentRot; | ||
2546 | ret = ParentGroup.AbsolutePosition + translationOffsetPosition; | ||
2547 | } | ||
2548 | return ret; | ||
2505 | } | 2549 | } |
2506 | 2550 | ||
2507 | /// <summary> | 2551 | /// <summary> |
@@ -2518,6 +2562,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2518 | } | 2562 | } |
2519 | else | 2563 | else |
2520 | { | 2564 | { |
2565 | // A child SOP's rotation is relative to the root SOP's rotation. | ||
2566 | // Combine them to get my absolute rotation. | ||
2521 | Quaternion parentRot = ParentGroup.RootPart.RotationOffset; | 2567 | Quaternion parentRot = ParentGroup.RootPart.RotationOffset; |
2522 | Quaternion oldRot = RotationOffset; | 2568 | Quaternion oldRot = RotationOffset; |
2523 | newRot = parentRot * oldRot; | 2569 | newRot = parentRot * oldRot; |
@@ -3174,8 +3220,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3174 | if (ParentGroup.IsDeleted) | 3220 | if (ParentGroup.IsDeleted) |
3175 | return; | 3221 | return; |
3176 | 3222 | ||
3177 | if (ParentGroup.IsAttachment && (ParentGroup.AttachedAvatar != remoteClient.AgentId) && | 3223 | if (ParentGroup.IsAttachment |
3178 | (ParentGroup.AttachmentPoint >= 31) && (ParentGroup.AttachmentPoint <= 38)) | 3224 | && ParentGroup.AttachedAvatar != remoteClient.AgentId |
3225 | && ParentGroup.HasPrivateAttachmentPoint) | ||
3179 | return; | 3226 | return; |
3180 | 3227 | ||
3181 | if (remoteClient.AgentId == OwnerID) | 3228 | if (remoteClient.AgentId == OwnerID) |
@@ -3694,7 +3741,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3694 | hasProfileCut = hasDimple; // is it the same thing? | 3741 | hasProfileCut = hasDimple; // is it the same thing? |
3695 | } | 3742 | } |
3696 | 3743 | ||
3697 | |||
3698 | public void SetGroup(UUID groupID, IClientAPI client) | 3744 | public void SetGroup(UUID groupID, IClientAPI client) |
3699 | { | 3745 | { |
3700 | // Scene.AddNewPrims() calls with client == null so can't use this. | 3746 | // Scene.AddNewPrims() calls with client == null so can't use this. |
@@ -3724,10 +3770,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3724 | 3770 | ||
3725 | public void SetPhysicsAxisRotation() | 3771 | public void SetPhysicsAxisRotation() |
3726 | { | 3772 | { |
3727 | if (PhysActor != null) | 3773 | PhysicsActor pa = PhysActor; |
3774 | |||
3775 | if (pa != null) | ||
3728 | { | 3776 | { |
3729 | PhysActor.LockAngularMotion(RotationAxis); | 3777 | pa.LockAngularMotion(RotationAxis); |
3730 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); | 3778 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); |
3731 | } | 3779 | } |
3732 | } | 3780 | } |
3733 | 3781 | ||
@@ -4444,7 +4492,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4444 | // For now, we use the NINJA naming scheme for identifying joints. | 4492 | // For now, we use the NINJA naming scheme for identifying joints. |
4445 | // In the future, we can support other joint specification schemes such as a | 4493 | // In the future, we can support other joint specification schemes such as a |
4446 | // custom checkbox in the viewer GUI. | 4494 | // custom checkbox in the viewer GUI. |
4447 | if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | 4495 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) |
4448 | { | 4496 | { |
4449 | string hingeString = "hingejoint"; | 4497 | string hingeString = "hingejoint"; |
4450 | return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString); | 4498 | return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString); |
@@ -4460,7 +4508,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4460 | // For now, we use the NINJA naming scheme for identifying joints. | 4508 | // For now, we use the NINJA naming scheme for identifying joints. |
4461 | // In the future, we can support other joint specification schemes such as a | 4509 | // In the future, we can support other joint specification schemes such as a |
4462 | // custom checkbox in the viewer GUI. | 4510 | // custom checkbox in the viewer GUI. |
4463 | if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | 4511 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) |
4464 | { | 4512 | { |
4465 | string ballString = "balljoint"; | 4513 | string ballString = "balljoint"; |
4466 | return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString); | 4514 | return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString); |
@@ -4476,7 +4524,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4476 | // For now, we use the NINJA naming scheme for identifying joints. | 4524 | // For now, we use the NINJA naming scheme for identifying joints. |
4477 | // In the future, we can support other joint specification schemes such as a | 4525 | // In the future, we can support other joint specification schemes such as a |
4478 | // custom checkbox in the viewer GUI. | 4526 | // custom checkbox in the viewer GUI. |
4479 | if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | 4527 | if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) |
4480 | { | 4528 | { |
4481 | return IsHingeJoint() || IsBallJoint(); | 4529 | return IsHingeJoint() || IsBallJoint(); |
4482 | } | 4530 | } |
@@ -4598,7 +4646,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4598 | } | 4646 | } |
4599 | */ | 4647 | */ |
4600 | } | 4648 | } |
4601 | |||
4602 | else // it already has a physical representation | 4649 | else // it already has a physical representation |
4603 | { | 4650 | { |
4604 | DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. | 4651 | DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. |
@@ -5074,8 +5121,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
5074 | if (ParentGroup.IsDeleted) | 5121 | if (ParentGroup.IsDeleted) |
5075 | return; | 5122 | return; |
5076 | 5123 | ||
5077 | if (ParentGroup.IsAttachment && ((ParentGroup.RootPart != this) || | 5124 | if (ParentGroup.IsAttachment |
5078 | ((ParentGroup.AttachedAvatar != remoteClient.AgentId) && (ParentGroup.AttachmentPoint >= 31) && (ParentGroup.AttachmentPoint <= 38)))) | 5125 | && (ParentGroup.RootPart != this |
5126 | || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint)) | ||
5079 | return; | 5127 | return; |
5080 | 5128 | ||
5081 | // Causes this thread to dig into the Client Thread Data. | 5129 | // Causes this thread to dig into the Client Thread Data. |
@@ -5147,5 +5195,99 @@ namespace OpenSim.Region.Framework.Scenes | |||
5147 | Inventory.UpdateInventoryItem(item, false, false); | 5195 | Inventory.UpdateInventoryItem(item, false, false); |
5148 | } | 5196 | } |
5149 | } | 5197 | } |
5198 | |||
5199 | /// <summary> | ||
5200 | /// Record an avatar sitting on this part. | ||
5201 | /// </summary> | ||
5202 | /// <remarks>This is called for all the sitting avatars whether there is a sit target set or not.</remarks> | ||
5203 | /// <returns> | ||
5204 | /// true if the avatar was not already recorded, false otherwise. | ||
5205 | /// </returns> | ||
5206 | /// <param name='avatarId'></param> | ||
5207 | protected internal bool AddSittingAvatar(UUID avatarId) | ||
5208 | { | ||
5209 | if (IsSitTargetSet && SitTargetAvatar == UUID.Zero) | ||
5210 | SitTargetAvatar = avatarId; | ||
5211 | |||
5212 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5213 | |||
5214 | if (sittingAvatars == null) | ||
5215 | sittingAvatars = new HashSet<UUID>(); | ||
5216 | |||
5217 | lock (sittingAvatars) | ||
5218 | { | ||
5219 | m_sittingAvatars = sittingAvatars; | ||
5220 | return m_sittingAvatars.Add(avatarId); | ||
5221 | } | ||
5222 | } | ||
5223 | |||
5224 | /// <summary> | ||
5225 | /// Remove an avatar recorded as sitting on this part. | ||
5226 | /// </summary> | ||
5227 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
5228 | /// <returns> | ||
5229 | /// true if the avatar was present and removed, false if it was not present. | ||
5230 | /// </returns> | ||
5231 | /// <param name='avatarId'></param> | ||
5232 | protected internal bool RemoveSittingAvatar(UUID avatarId) | ||
5233 | { | ||
5234 | if (SitTargetAvatar == avatarId) | ||
5235 | SitTargetAvatar = UUID.Zero; | ||
5236 | |||
5237 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5238 | |||
5239 | // This can occur under a race condition where another thread | ||
5240 | if (sittingAvatars == null) | ||
5241 | return false; | ||
5242 | |||
5243 | lock (sittingAvatars) | ||
5244 | { | ||
5245 | if (sittingAvatars.Remove(avatarId)) | ||
5246 | { | ||
5247 | if (sittingAvatars.Count == 0) | ||
5248 | m_sittingAvatars = null; | ||
5249 | |||
5250 | return true; | ||
5251 | } | ||
5252 | } | ||
5253 | |||
5254 | return false; | ||
5255 | } | ||
5256 | |||
5257 | /// <summary> | ||
5258 | /// Get a copy of the list of sitting avatars. | ||
5259 | /// </summary> | ||
5260 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
5261 | /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns> | ||
5262 | public HashSet<UUID> GetSittingAvatars() | ||
5263 | { | ||
5264 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5265 | |||
5266 | if (sittingAvatars == null) | ||
5267 | { | ||
5268 | return null; | ||
5269 | } | ||
5270 | else | ||
5271 | { | ||
5272 | lock (sittingAvatars) | ||
5273 | return new HashSet<UUID>(sittingAvatars); | ||
5274 | } | ||
5275 | } | ||
5276 | |||
5277 | /// <summary> | ||
5278 | /// Gets the number of sitting avatars. | ||
5279 | /// </summary> | ||
5280 | /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> | ||
5281 | /// <returns></returns> | ||
5282 | public int GetSittingAvatarsCount() | ||
5283 | { | ||
5284 | HashSet<UUID> sittingAvatars = m_sittingAvatars; | ||
5285 | |||
5286 | if (sittingAvatars == null) | ||
5287 | return 0; | ||
5288 | |||
5289 | lock (sittingAvatars) | ||
5290 | return sittingAvatars.Count; | ||
5291 | } | ||
5150 | } | 5292 | } |
5151 | } | 5293 | } |