aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs200
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}