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.cs918
1 files changed, 697 insertions, 221 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 44e8fdf..d1c5f72 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -37,11 +37,13 @@ using System.Xml.Serialization;
37using log4net; 37using log4net;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenMetaverse.Packets; 39using OpenMetaverse.Packets;
40using OpenMetaverse.StructuredData;
40using OpenSim.Framework; 41using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes.Scripting; 43using OpenSim.Region.Framework.Scenes.Scripting;
43using OpenSim.Region.Framework.Scenes.Serialization; 44using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Region.Physics.Manager; 45using OpenSim.Region.PhysicsModules.SharedBase;
46using PermissionMask = OpenSim.Framework.PermissionMask;
45 47
46namespace OpenSim.Region.Framework.Scenes 48namespace OpenSim.Region.Framework.Scenes
47{ 49{
@@ -115,7 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
115 117
116 #endregion Enumerations 118 #endregion Enumerations
117 119
118 public class SceneObjectPart : IScriptHost, ISceneEntity 120 public class SceneObjectPart : ISceneEntity
119 { 121 {
120 /// <value> 122 /// <value>
121 /// Denote all sides of the prim 123 /// Denote all sides of the prim
@@ -124,6 +126,32 @@ namespace OpenSim.Region.Framework.Scenes
124 126
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 128
129 /// <summary>
130 /// Dynamic attributes can be created and deleted as required.
131 /// </summary>
132 public DAMap DynAttrs { get; set; }
133
134 private DOMap m_dynObjs;
135
136 /// <summary>
137 /// Dynamic objects that can be created and deleted as required.
138 /// </summary>
139 public DOMap DynObjs
140 {
141 get
142 {
143 if (m_dynObjs == null)
144 m_dynObjs = new DOMap();
145
146 return m_dynObjs;
147 }
148
149 set
150 {
151 m_dynObjs = value;
152 }
153 }
154
127 /// <value> 155 /// <value>
128 /// Is this a root part? 156 /// Is this a root part?
129 /// </value> 157 /// </value>
@@ -158,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes
158 186
159 public bool RETURN_AT_EDGE; 187 public bool RETURN_AT_EDGE;
160 188
161 public bool BlockGrab; 189 public bool BlockGrab { get; set; }
162 190
163 public bool StatusSandbox; 191 public bool StatusSandbox;
164 192
@@ -191,6 +219,14 @@ namespace OpenSim.Region.Framework.Scenes
191 219
192 public double SoundRadius; 220 public double SoundRadius;
193 221
222 /// <summary>
223 /// Should sounds played from this prim be queued?
224 /// </summary>
225 /// <remarks>
226 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
227 /// </remarks>
228 public bool SoundQueueing { get; set; }
229
194 public uint TimeStampFull; 230 public uint TimeStampFull;
195 231
196 public uint TimeStampLastActivity; // Will be used for AutoReturn 232 public uint TimeStampLastActivity; // Will be used for AutoReturn
@@ -230,7 +266,7 @@ namespace OpenSim.Region.Framework.Scenes
230 266
231 public Quaternion SpinOldOrientation = Quaternion.Identity; 267 public Quaternion SpinOldOrientation = Quaternion.Identity;
232 268
233 protected int m_APIDIterations = 0; 269 protected bool m_APIDActive = false;
234 protected Quaternion m_APIDTarget = Quaternion.Identity; 270 protected Quaternion m_APIDTarget = Quaternion.Identity;
235 protected float m_APIDDamp = 0; 271 protected float m_APIDDamp = 0;
236 protected float m_APIDStrength = 0; 272 protected float m_APIDStrength = 0;
@@ -296,6 +332,12 @@ namespace OpenSim.Region.Framework.Scenes
296 protected Vector3 m_lastAcceleration; 332 protected Vector3 m_lastAcceleration;
297 protected Vector3 m_lastAngularVelocity; 333 protected Vector3 m_lastAngularVelocity;
298 protected int m_lastTerseSent; 334 protected int m_lastTerseSent;
335
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood
299 341
300 /// <summary> 342 /// <summary>
301 /// Stores media texture data 343 /// Stores media texture data
@@ -312,6 +354,11 @@ namespace OpenSim.Region.Framework.Scenes
312 private UUID m_collisionSound; 354 private UUID m_collisionSound;
313 private float m_collisionSoundVolume; 355 private float m_collisionSoundVolume;
314 356
357 public KeyframeMotion KeyframeMotion
358 {
359 get; set;
360 }
361
315 #endregion Fields 362 #endregion Fields
316 363
317// ~SceneObjectPart() 364// ~SceneObjectPart()
@@ -335,6 +382,7 @@ namespace OpenSim.Region.Framework.Scenes
335 m_particleSystem = Utils.EmptyBytes; 382 m_particleSystem = Utils.EmptyBytes;
336 Rezzed = DateTime.UtcNow; 383 Rezzed = DateTime.UtcNow;
337 Description = String.Empty; 384 Description = String.Empty;
385 DynAttrs = new DAMap();
338 386
339 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol, 387 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
340 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 388 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
@@ -389,8 +437,8 @@ namespace OpenSim.Region.Framework.Scenes
389 private uint _category; 437 private uint _category;
390 private Int32 _creationDate; 438 private Int32 _creationDate;
391 private uint _parentID = 0; 439 private uint _parentID = 0;
392 private uint _baseMask = (uint)PermissionMask.All; 440 private uint _baseMask = (uint)(PermissionMask.All | PermissionMask.Export);
393 private uint _ownerMask = (uint)PermissionMask.All; 441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
394 private uint _groupMask = (uint)PermissionMask.None; 442 private uint _groupMask = (uint)PermissionMask.None;
395 private uint _everyoneMask = (uint)PermissionMask.None; 443 private uint _everyoneMask = (uint)PermissionMask.None;
396 private uint _nextOwnerMask = (uint)PermissionMask.All; 444 private uint _nextOwnerMask = (uint)PermissionMask.All;
@@ -425,7 +473,7 @@ namespace OpenSim.Region.Framework.Scenes
425 { 473 {
426 get 474 get
427 { 475 {
428 if (CreatorData != null && CreatorData != string.Empty) 476 if (!string.IsNullOrEmpty(CreatorData))
429 return CreatorID.ToString() + ';' + CreatorData; 477 return CreatorID.ToString() + ';' + CreatorData;
430 else 478 else
431 return CreatorID.ToString(); 479 return CreatorID.ToString();
@@ -455,7 +503,11 @@ namespace OpenSim.Region.Framework.Scenes
455 CreatorID = uuid; 503 CreatorID = uuid;
456 } 504 }
457 if (parts.Length >= 2) 505 if (parts.Length >= 2)
506 {
458 CreatorData = parts[1]; 507 CreatorData = parts[1];
508 if (!CreatorData.EndsWith("/"))
509 CreatorData += "/";
510 }
459 if (parts.Length >= 3) 511 if (parts.Length >= 3)
460 name = parts[2]; 512 name = parts[2];
461 513
@@ -590,6 +642,12 @@ namespace OpenSim.Region.Framework.Scenes
590 } 642 }
591 } 643 }
592 644
645 protected bool APIDActive
646 {
647 get { return m_APIDActive; }
648 set { m_APIDActive = value; }
649 }
650
593 protected Quaternion APIDTarget 651 protected Quaternion APIDTarget
594 { 652 {
595 get { return m_APIDTarget; } 653 get { return m_APIDTarget; }
@@ -729,23 +787,14 @@ namespace OpenSim.Region.Framework.Scenes
729 } 787 }
730 788
731 // Tell the physics engines that this prim changed. 789 // Tell the physics engines that this prim changed.
732 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 790 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
791 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
733 } 792 }
734 catch (Exception e) 793 catch (Exception e)
735 { 794 {
736 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); 795 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
737 } 796 }
738 } 797 }
739
740 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
741 if (SitTargetAvatar != UUID.Zero)
742 {
743 ScenePresence avatar;
744 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
745 {
746 avatar.ParentPosition = GetWorldPosition();
747 }
748 }
749 } 798 }
750 } 799 }
751 800
@@ -842,7 +891,7 @@ namespace OpenSim.Region.Framework.Scenes
842 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 891 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
843 } 892 }
844 893
845 if (ParentGroup != null) 894 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
846 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 895 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
847 //} 896 //}
848 } 897 }
@@ -880,14 +929,17 @@ namespace OpenSim.Region.Framework.Scenes
880 929
881 set 930 set
882 { 931 {
883 m_velocity = value; 932 if (Util.IsNanOrInfinity(value))
933 m_velocity = Vector3.Zero;
934 else
935 m_velocity = value;
884 936
885 PhysicsActor actor = PhysActor; 937 PhysicsActor actor = PhysActor;
886 if (actor != null) 938 if (actor != null)
887 { 939 {
888 if (actor.IsPhysical) 940 if (actor.IsPhysical)
889 { 941 {
890 actor.Velocity = value; 942 actor.Velocity = m_velocity;
891 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 943 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
892 } 944 }
893 } 945 }
@@ -914,14 +966,30 @@ namespace OpenSim.Region.Framework.Scenes
914 } 966 }
915 return m_angularVelocity; 967 return m_angularVelocity;
916 } 968 }
917 set { m_angularVelocity = value; } 969 set
970 {
971 if (Util.IsNanOrInfinity(value))
972 m_angularVelocity = Vector3.Zero;
973 else
974 m_angularVelocity = value;
975
976 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical)
978 actor.RotationalVelocity = m_angularVelocity;
979 }
918 } 980 }
919 981
920 /// <summary></summary> 982 /// <summary></summary>
921 public Vector3 Acceleration 983 public Vector3 Acceleration
922 { 984 {
923 get { return m_acceleration; } 985 get { return m_acceleration; }
924 set { m_acceleration = value; } 986 set
987 {
988 if (Util.IsNanOrInfinity(value))
989 m_acceleration = Vector3.Zero;
990 else
991 m_acceleration = value;
992 }
925 } 993 }
926 994
927 public string Description { get; set; } 995 public string Description { get; set; }
@@ -1028,6 +1096,7 @@ namespace OpenSim.Region.Framework.Scenes
1028 } 1096 }
1029 1097
1030 public UpdateRequired UpdateFlag { get; set; } 1098 public UpdateRequired UpdateFlag { get; set; }
1099 public bool UpdatePhysRequired { get; set; }
1031 1100
1032 /// <summary> 1101 /// <summary>
1033 /// Used for media on a prim. 1102 /// Used for media on a prim.
@@ -1110,23 +1179,14 @@ namespace OpenSim.Region.Framework.Scenes
1110 // the mappings more consistant. 1179 // the mappings more consistant.
1111 public Vector3 SitTargetPositionLL 1180 public Vector3 SitTargetPositionLL
1112 { 1181 {
1113 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1182 get { return m_sitTargetPosition; }
1114 set { m_sitTargetPosition = value; } 1183 set { m_sitTargetPosition = value; }
1115 } 1184 }
1116 1185
1117 public Quaternion SitTargetOrientationLL 1186 public Quaternion SitTargetOrientationLL
1118 { 1187 {
1119 get 1188 get { return m_sitTargetOrientation; }
1120 { 1189 set { m_sitTargetOrientation = value; }
1121 return new Quaternion(
1122 m_sitTargetOrientation.X,
1123 m_sitTargetOrientation.Y,
1124 m_sitTargetOrientation.Z,
1125 m_sitTargetOrientation.W
1126 );
1127 }
1128
1129 set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); }
1130 } 1190 }
1131 1191
1132 public bool Stopped 1192 public bool Stopped
@@ -1264,7 +1324,7 @@ namespace OpenSim.Region.Framework.Scenes
1264 /// <value> 1324 /// <value>
1265 /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene. 1325 /// null if there are no sitting avatars. This is to save us create a hashset for every prim in a scene.
1266 /// </value> 1326 /// </value>
1267 private HashSet<UUID> m_sittingAvatars; 1327 private HashSet<ScenePresence> m_sittingAvatars;
1268 1328
1269 public virtual UUID RegionID 1329 public virtual UUID RegionID
1270 { 1330 {
@@ -1315,6 +1375,157 @@ namespace OpenSim.Region.Framework.Scenes
1315 set { m_collisionSoundVolume = value; } 1375 set { m_collisionSoundVolume = value; }
1316 } 1376 }
1317 1377
1378 public byte DefaultPhysicsShapeType()
1379 {
1380 byte type;
1381
1382 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1383 type = (byte)PhysShapeType.convex;
1384 else
1385 type = (byte)PhysShapeType.prim;
1386
1387 return type;
1388 }
1389
1390 public byte PhysicsShapeType
1391 {
1392 get { return m_physicsShapeType; }
1393 set
1394 {
1395 byte oldv = m_physicsShapeType;
1396
1397 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1398 {
1399 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1400 m_physicsShapeType = DefaultPhysicsShapeType();
1401 else
1402 m_physicsShapeType = value;
1403 }
1404 else
1405 m_physicsShapeType = DefaultPhysicsShapeType();
1406
1407 if (m_physicsShapeType != oldv && ParentGroup != null)
1408 {
1409 if (m_physicsShapeType == (byte)PhysShapeType.none)
1410 {
1411 if (PhysActor != null)
1412 {
1413 Velocity = new Vector3(0, 0, 0);
1414 Acceleration = new Vector3(0, 0, 0);
1415 if (ParentGroup.RootPart == this)
1416 AngularVelocity = new Vector3(0, 0, 0);
1417 ParentGroup.Scene.RemovePhysicalPrim(1);
1418 RemoveFromPhysics();
1419 }
1420 }
1421 else if (PhysActor == null)
1422 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive);
1424 }
1425 else
1426 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType;
1428 }
1429
1430 if (ParentGroup != null)
1431 ParentGroup.HasGroupChanged = true;
1432 }
1433
1434 if (m_physicsShapeType != value)
1435 {
1436 UpdatePhysRequired = true;
1437 }
1438 }
1439 }
1440
1441 public float Density // in kg/m^3
1442 {
1443 get { return m_density; }
1444 set
1445 {
1446 if (value >=1 && value <= 22587.0)
1447 {
1448 m_density = value;
1449 UpdatePhysRequired = true;
1450 }
1451
1452 ScheduleFullUpdateIfNone();
1453
1454 if (ParentGroup != null)
1455 ParentGroup.HasGroupChanged = true;
1456
1457 PhysicsActor pa = PhysActor;
1458 if (pa != null)
1459 pa.Density = Density;
1460 }
1461 }
1462
1463 public float GravityModifier
1464 {
1465 get { return m_gravitymod; }
1466 set
1467 {
1468 if( value >= -1 && value <=28.0f)
1469 {
1470 m_gravitymod = value;
1471 UpdatePhysRequired = true;
1472 }
1473
1474 ScheduleFullUpdateIfNone();
1475
1476 if (ParentGroup != null)
1477 ParentGroup.HasGroupChanged = true;
1478
1479 PhysicsActor pa = PhysActor;
1480 if (pa != null)
1481 pa.GravModifier = GravityModifier;
1482 }
1483 }
1484
1485 public float Friction
1486 {
1487 get { return m_friction; }
1488 set
1489 {
1490 if (value >= 0 && value <= 255.0f)
1491 {
1492 m_friction = value;
1493 UpdatePhysRequired = true;
1494 }
1495
1496 ScheduleFullUpdateIfNone();
1497
1498 if (ParentGroup != null)
1499 ParentGroup.HasGroupChanged = true;
1500
1501 PhysicsActor pa = PhysActor;
1502 if (pa != null)
1503 pa.Friction = Friction;
1504 }
1505 }
1506
1507 public float Restitution
1508 {
1509 get { return m_bounce; }
1510 set
1511 {
1512 if (value >= 0 && value <= 1.0f)
1513 {
1514 m_bounce = value;
1515 UpdatePhysRequired = true;
1516 }
1517
1518 ScheduleFullUpdateIfNone();
1519
1520 if (ParentGroup != null)
1521 ParentGroup.HasGroupChanged = true;
1522
1523 PhysicsActor pa = PhysActor;
1524 if (pa != null)
1525 pa.Restitution = Restitution;
1526 }
1527 }
1528
1318 #endregion Public Properties with only Get 1529 #endregion Public Properties with only Get
1319 1530
1320 private uint ApplyMask(uint val, bool set, uint mask) 1531 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1403,20 +1614,29 @@ namespace OpenSim.Region.Framework.Scenes
1403 1614
1404 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim) 1615 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
1405 { 1616 {
1406 byte[] data = new byte[16]; 1617 byte[] data;
1407 int pos = 0;
1408 1618
1409 // The flags don't like conversion from uint to byte, so we have to do 1619 if (pTexAnim.Flags == Primitive.TextureAnimMode.ANIM_OFF)
1410 // it the crappy way. See the above function :( 1620 {
1621 data = Utils.EmptyBytes;
1622 }
1623 else
1624 {
1625 data = new byte[16];
1626 int pos = 0;
1411 1627
1412 data[pos] = ConvertScriptUintToByte((uint)pTexAnim.Flags); pos++; 1628 // The flags don't like conversion from uint to byte, so we have to do
1413 data[pos] = (byte)pTexAnim.Face; pos++; 1629 // it the crappy way. See the above function :(
1414 data[pos] = (byte)pTexAnim.SizeX; pos++;
1415 data[pos] = (byte)pTexAnim.SizeY; pos++;
1416 1630
1417 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1631 data[pos] = ConvertScriptUintToByte((uint)pTexAnim.Flags); pos++;
1418 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1632 data[pos] = (byte)pTexAnim.Face; pos++;
1419 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1633 data[pos] = (byte)pTexAnim.SizeX; pos++;
1634 data[pos] = (byte)pTexAnim.SizeY; pos++;
1635
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1639 }
1420 1640
1421 m_TextureAnimation = data; 1641 m_TextureAnimation = data;
1422 } 1642 }
@@ -1511,40 +1731,36 @@ namespace OpenSim.Region.Framework.Scenes
1511 /// </summary> 1731 /// </summary>
1512 /// <param name="rootObjectFlags"></param> 1732 /// <param name="rootObjectFlags"></param>
1513 /// <param name="VolumeDetectActive"></param> 1733 /// <param name="VolumeDetectActive"></param>
1514 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive)
1515 { 1735 {
1736 VolumeDetectActive = _VolumeDetectActive;
1737
1516 if (!ParentGroup.Scene.CollidablePrims) 1738 if (!ParentGroup.Scene.CollidablePrims)
1517 return; 1739 return;
1518 1740
1519// m_log.DebugFormat( 1741 if (PhysicsShapeType == (byte)PhysShapeType.none)
1520// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1742 return;
1521// Name, LocalId, UUID, m_physicalPrim);
1522 1743
1523 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0;
1524 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0;
1525 1746
1747 if (_VolumeDetectActive)
1748 isPhantom = true;
1749
1526 if (IsJoint()) 1750 if (IsJoint())
1527 { 1751 {
1528 DoPhysicsPropertyUpdate(isPhysical, true); 1752 DoPhysicsPropertyUpdate(isPhysical, true);
1529 } 1753 }
1530 else 1754 else
1531 { 1755 {
1532 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1756 if ((!isPhantom || isPhysical || _VolumeDetectActive)
1533 if (VolumeDetectActive) 1757 && !ParentGroup.IsAttachmentCheckFull()
1534 isPhantom = false; 1758 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1535
1536 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
1537 // or flexible
1538 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1539 { 1759 {
1540 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1760 AddToPhysics(isPhysical, isPhantom, isPhysical);
1541 bool rigidBody = isPhysical && !isPhantom;
1542
1543 PhysicsActor pa = AddToPhysics(rigidBody);
1544
1545 if (pa != null)
1546 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1547 } 1761 }
1762 else
1763 PhysActor = null; // just to be sure
1548 } 1764 }
1549 } 1765 }
1550 1766
@@ -1572,7 +1788,11 @@ namespace OpenSim.Region.Framework.Scenes
1572 /// <returns></returns> 1788 /// <returns></returns>
1573 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 1789 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1574 { 1790 {
1791 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1792 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1793 // but not between regions on different simulators). Really, all copying should be done explicitly.
1575 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); 1794 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone();
1795
1576 dupe.m_shape = m_shape.Copy(); 1796 dupe.m_shape = m_shape.Copy();
1577 dupe.m_regionHandle = m_regionHandle; 1797 dupe.m_regionHandle = m_regionHandle;
1578 if (userExposed) 1798 if (userExposed)
@@ -1618,6 +1838,14 @@ namespace OpenSim.Region.Framework.Scenes
1618 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 1838 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1619 dupe.Shape.ExtraParams = extraP; 1839 dupe.Shape.ExtraParams = extraP;
1620 1840
1841 dupe.m_sittingAvatars = new HashSet<ScenePresence>();
1842
1843 // safeguard actual copy is done in sog.copy
1844 dupe.KeyframeMotion = null;
1845 dupe.PayPrice = (int[])PayPrice.Clone();
1846
1847 dupe.DynAttrs.CopyFrom(DynAttrs);
1848
1621 if (userExposed) 1849 if (userExposed)
1622 { 1850 {
1623/* 1851/*
@@ -1816,6 +2044,9 @@ namespace OpenSim.Region.Framework.Scenes
1816 { 2044 {
1817 if (UsePhysics) 2045 if (UsePhysics)
1818 { 2046 {
2047 if (ParentGroup.RootPart.KeyframeMotion != null)
2048 ParentGroup.RootPart.KeyframeMotion.Stop();
2049 ParentGroup.RootPart.KeyframeMotion = null;
1819 ParentGroup.Scene.AddPhysicalPrim(1); 2050 ParentGroup.Scene.AddPhysicalPrim(1);
1820 2051
1821 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2052 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
@@ -1848,7 +2079,7 @@ namespace OpenSim.Region.Framework.Scenes
1848 /// </summary> 2079 /// </summary>
1849 /// <param name="xmlReader"></param> 2080 /// <param name="xmlReader"></param>
1850 /// <returns></returns> 2081 /// <returns></returns>
1851 public static SceneObjectPart FromXml(XmlTextReader xmlReader) 2082 public static SceneObjectPart FromXml(XmlReader xmlReader)
1852 { 2083 {
1853 SceneObjectPart part = SceneObjectSerializer.Xml2ToSOP(xmlReader); 2084 SceneObjectPart part = SceneObjectSerializer.Xml2ToSOP(xmlReader);
1854 2085
@@ -1883,22 +2114,6 @@ namespace OpenSim.Region.Framework.Scenes
1883 ParentGroup.RootPart.RETURN_AT_EDGE = p; 2114 ParentGroup.RootPart.RETURN_AT_EDGE = p;
1884 } 2115 }
1885 2116
1886 public bool GetBlockGrab()
1887 {
1888 if (ParentGroup.IsDeleted)
1889 return false;
1890
1891 return ParentGroup.RootPart.BlockGrab;
1892 }
1893
1894 public void SetBlockGrab(bool p)
1895 {
1896 if (ParentGroup.IsDeleted)
1897 return;
1898
1899 ParentGroup.RootPart.BlockGrab = p;
1900 }
1901
1902 public void SetStatusSandbox(bool p) 2117 public void SetStatusSandbox(bool p)
1903 { 2118 {
1904 if (ParentGroup.IsDeleted) 2119 if (ParentGroup.IsDeleted)
@@ -1952,9 +2167,19 @@ namespace OpenSim.Region.Framework.Scenes
1952 PhysicsActor pa = PhysActor; 2167 PhysicsActor pa = PhysActor;
1953 2168
1954 if (pa != null) 2169 if (pa != null)
1955 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2170 return pa.GeometricCenter;
2171 else
2172 return Vector3.Zero;
2173 }
2174
2175 public Vector3 GetCenterOfMass()
2176 {
2177 PhysicsActor pa = PhysActor;
2178
2179 if (pa != null)
2180 return pa.CenterOfMass;
1956 else 2181 else
1957 return new Vector3(0, 0, 0); 2182 return Vector3.Zero;
1958 } 2183 }
1959 2184
1960 public float GetMass() 2185 public float GetMass()
@@ -2030,7 +2255,7 @@ namespace OpenSim.Region.Framework.Scenes
2030 { 2255 {
2031 if (tau > 0) 2256 if (tau > 0)
2032 { 2257 {
2033 ParentGroup.moveToTarget(target, tau); 2258 ParentGroup.MoveToTarget(target, tau);
2034 } 2259 }
2035 else 2260 else
2036 { 2261 {
@@ -2168,7 +2393,7 @@ namespace OpenSim.Region.Framework.Scenes
2168 CollidingMessage = CreateColliderArgs(this, colliders); 2393 CollidingMessage = CreateColliderArgs(this, colliders);
2169 2394
2170 if (CollidingMessage.Colliders.Count > 0) 2395 if (CollidingMessage.Colliders.Count > 0)
2171 notify(LocalId, CollidingMessage); 2396 DoNotify(notify, LocalId, CollidingMessage);
2172 2397
2173 if (PassCollisions) 2398 if (PassCollisions)
2174 sendToRoot = true; 2399 sendToRoot = true;
@@ -2182,7 +2407,7 @@ namespace OpenSim.Region.Framework.Scenes
2182 { 2407 {
2183 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2408 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2184 if (CollidingMessage.Colliders.Count > 0) 2409 if (CollidingMessage.Colliders.Count > 0)
2185 notify(ParentGroup.RootPart.LocalId, CollidingMessage); 2410 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage);
2186 } 2411 }
2187 } 2412 }
2188 } 2413 }
@@ -2197,7 +2422,33 @@ namespace OpenSim.Region.Framework.Scenes
2197 colliding.Add(CreateDetObjectForGround()); 2422 colliding.Add(CreateDetObjectForGround());
2198 LandCollidingMessage.Colliders = colliding; 2423 LandCollidingMessage.Colliders = colliding;
2199 2424
2200 notify(LocalId, LandCollidingMessage); 2425 DoNotify(notify, LocalId, LandCollidingMessage);
2426 }
2427 }
2428
2429 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs)
2430 {
2431 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2432 {
2433 // For those learning C#, FireAndForget takes a function, an object to pass
2434 // to that function and an ID string. The "oo => {}" construct is a lambda expression
2435 // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object
2436 // that is an object array and initializes it with three items (the parameters
2437 // being passed). The parameters passed are the function to call ('notify') and
2438 // its two arguements. Finally, once in the function (called later by the FireAndForget
2439 // thread scheduler), the passed object is cast to an object array and then each
2440 // of its items (aoo[0] to aoo[2]) are individually cast to what they are and
2441 // then used in a call of the passed ScriptCollidingNotification function.
2442 Util.FireAndForget(oo =>
2443 {
2444 Object[] aoo = (Object[])oo;
2445 ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]);
2446
2447 }, new Object[] { notify, id, collargs }, "SOP.Collision");
2448 }
2449 else
2450 {
2451 notify(id, collargs);
2201 } 2452 }
2202 } 2453 }
2203 2454
@@ -2244,7 +2495,7 @@ namespace OpenSim.Region.Framework.Scenes
2244 if (soundModule != null) 2495 if (soundModule != null)
2245 { 2496 {
2246 soundModule.SendSound(UUID, CollisionSound, 2497 soundModule.SendSound(UUID, CollisionSound,
2247 CollisionSoundVolume, true, (byte)0, 0, false, 2498 CollisionSoundVolume, true, 0, 0, false,
2248 false); 2499 false);
2249 } 2500 }
2250 } 2501 }
@@ -2254,12 +2505,9 @@ namespace OpenSim.Region.Framework.Scenes
2254 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2505 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2255 2506
2256 if (startedColliders.Contains(0)) 2507 if (startedColliders.Contains(0))
2257 { 2508 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2258 if (m_lastColliders.Contains(0)) 2509 if (m_lastColliders.Contains(0))
2259 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2510 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2260 else
2261 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2262 }
2263 if (endedColliders.Contains(0)) 2511 if (endedColliders.Contains(0))
2264 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2512 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2265 } 2513 }
@@ -2282,19 +2530,36 @@ namespace OpenSim.Region.Framework.Scenes
2282 2530
2283 if (pa != null) 2531 if (pa != null)
2284 { 2532 {
2285 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2533 Vector3 newpos = pa.Position;
2286 2534 if (!ParentGroup.Scene.PositionIsInCurrentRegion(newpos))
2287 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2288 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2289 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2290 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2291 { 2535 {
2536 // Setting position outside current region will start region crossing
2292 ParentGroup.AbsolutePosition = newpos; 2537 ParentGroup.AbsolutePosition = newpos;
2293 return; 2538 return;
2294 } 2539 }
2295 //ParentGroup.RootPart.m_groupPosition = newpos; 2540 //ParentGroup.RootPart.m_groupPosition = newpos;
2296 } 2541 }
2297 2542
2543 if (pa != null && ParentID != 0 && ParentGroup != null)
2544 {
2545 // Special case where a child object is requesting property updates.
2546 // This happens when linksets are modified to use flexible links rather than
2547 // the default links.
2548 // The simulator code presumes that child parts are only modified by scripts
2549 // so the logic for changing position/rotation/etc does not take into
2550 // account the physical object actually moving.
2551 // This code updates the offset position and rotation of the child and then
2552 // lets the update code push the update to the viewer.
2553 // Since physics engines do not normally generate this event for linkset children,
2554 // this code will not be active unless you have a specially configured
2555 // physics engine.
2556 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
2557 m_offsetPosition = pa.Position - m_groupPosition;
2558 RotationOffset = pa.Orientation * invRootRotation;
2559 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2560 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2561 }
2562
2298 ScheduleTerseUpdate(); 2563 ScheduleTerseUpdate();
2299 } 2564 }
2300 2565
@@ -2397,7 +2662,7 @@ namespace OpenSim.Region.Framework.Scenes
2397 return; 2662 return;
2398 } 2663 }
2399 2664
2400 m_APIDIterations = 1 + (int)(Math.PI * APIDStrength); 2665 APIDActive = true;
2401 } 2666 }
2402 2667
2403 // Necessary to get the lookat deltas applied 2668 // Necessary to get the lookat deltas applied
@@ -2411,7 +2676,20 @@ namespace OpenSim.Region.Framework.Scenes
2411 2676
2412 public void StopLookAt() 2677 public void StopLookAt()
2413 { 2678 {
2414 APIDTarget = Quaternion.Identity; 2679 APIDActive = false;
2680 }
2681
2682
2683
2684 public void ScheduleFullUpdateIfNone()
2685 {
2686 if (ParentGroup == null)
2687 return;
2688
2689// ??? ParentGroup.HasGroupChanged = true;
2690
2691 if (UpdateFlag != UpdateRequired.FULL)
2692 ScheduleFullUpdate();
2415 } 2693 }
2416 2694
2417 /// <summary> 2695 /// <summary>
@@ -2460,7 +2738,8 @@ namespace OpenSim.Region.Framework.Scenes
2460 return; 2738 return;
2461 2739
2462 // This was pulled from SceneViewer. Attachments always receive full updates. 2740 // This was pulled from SceneViewer. Attachments always receive full updates.
2463 // I could not verify if this is a requirement but this maintains existing behavior 2741 // This is needed because otherwise if only the root prim changes position, then
2742 // it looks as if the entire object has moved (including the other prims).
2464 if (ParentGroup.IsAttachment) 2743 if (ParentGroup.IsAttachment)
2465 { 2744 {
2466 ScheduleFullUpdate(); 2745 ScheduleFullUpdate();
@@ -2996,6 +3275,10 @@ namespace OpenSim.Region.Framework.Scenes
2996 /// <param name="events"></param> 3275 /// <param name="events"></param>
2997 public void SetScriptEvents(UUID scriptid, int events) 3276 public void SetScriptEvents(UUID scriptid, int events)
2998 { 3277 {
3278// m_log.DebugFormat(
3279// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}",
3280// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name);
3281
2999 // scriptEvents oldparts; 3282 // scriptEvents oldparts;
3000 lock (m_scriptEvents) 3283 lock (m_scriptEvents)
3001 { 3284 {
@@ -3048,10 +3331,7 @@ namespace OpenSim.Region.Framework.Scenes
3048 3331
3049 public void StopMoveToTarget() 3332 public void StopMoveToTarget()
3050 { 3333 {
3051 ParentGroup.stopMoveToTarget(); 3334 ParentGroup.StopMoveToTarget();
3052
3053 ParentGroup.ScheduleGroupForTerseUpdate();
3054 //ParentGroup.ScheduleGroupForFullUpdate();
3055 } 3335 }
3056 3336
3057 public void StoreUndoState() 3337 public void StoreUndoState()
@@ -3618,6 +3898,7 @@ namespace OpenSim.Region.Framework.Scenes
3618 result.distance = distance2; 3898 result.distance = distance2;
3619 result.HitTF = true; 3899 result.HitTF = true;
3620 result.ipoint = q; 3900 result.ipoint = q;
3901 result.face = i;
3621 //m_log.Info("[FACE]:" + i.ToString()); 3902 //m_log.Info("[FACE]:" + i.ToString());
3622 //m_log.Info("[POINT]: " + q.ToString()); 3903 //m_log.Info("[POINT]: " + q.ToString());
3623 //m_log.Info("[DIST]: " + distance2.ToString()); 3904 //m_log.Info("[DIST]: " + distance2.ToString());
@@ -3664,10 +3945,10 @@ namespace OpenSim.Region.Framework.Scenes
3664 3945
3665 public void TrimPermissions() 3946 public void TrimPermissions()
3666 { 3947 {
3667 BaseMask &= (uint)PermissionMask.All; 3948 BaseMask &= (uint)(PermissionMask.All | PermissionMask.Export);
3668 OwnerMask &= (uint)PermissionMask.All; 3949 OwnerMask &= (uint)(PermissionMask.All | PermissionMask.Export);
3669 GroupMask &= (uint)PermissionMask.All; 3950 GroupMask &= (uint)PermissionMask.All;
3670 EveryoneMask &= (uint)PermissionMask.All; 3951 EveryoneMask &= (uint)(PermissionMask.All | PermissionMask.Export);
3671 NextOwnerMask &= (uint)PermissionMask.All; 3952 NextOwnerMask &= (uint)PermissionMask.All;
3672 } 3953 }
3673 3954
@@ -3690,30 +3971,31 @@ namespace OpenSim.Region.Framework.Scenes
3690 } 3971 }
3691 } 3972 }
3692 3973
3693 public void UpdateGroupPosition(Vector3 pos) 3974 public void UpdateGroupPosition(Vector3 newPos)
3694 { 3975 {
3695 if ((pos.X != GroupPosition.X) || 3976 Vector3 oldPos = GroupPosition;
3696 (pos.Y != GroupPosition.Y) || 3977
3697 (pos.Z != GroupPosition.Z)) 3978 if ((newPos.X != oldPos.X) ||
3979 (newPos.Y != oldPos.Y) ||
3980 (newPos.Z != oldPos.Z))
3698 { 3981 {
3699 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3700 GroupPosition = newPos; 3982 GroupPosition = newPos;
3701 ScheduleTerseUpdate(); 3983 ScheduleTerseUpdate();
3702 } 3984 }
3703 } 3985 }
3704 3986
3705 /// <summary> 3987 /// <summary>
3706 /// 3988 /// Update this part's offset position.
3707 /// </summary> 3989 /// </summary>
3708 /// <param name="pos"></param> 3990 /// <param name="pos"></param>
3709 public void UpdateOffSet(Vector3 pos) 3991 public void UpdateOffSet(Vector3 newPos)
3710 { 3992 {
3711 if ((pos.X != OffsetPosition.X) || 3993 Vector3 oldPos = OffsetPosition;
3712 (pos.Y != OffsetPosition.Y) ||
3713 (pos.Z != OffsetPosition.Z))
3714 {
3715 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3716 3994
3995 if ((newPos.X != oldPos.X) ||
3996 (newPos.Y != oldPos.Y) ||
3997 (newPos.Z != oldPos.Z))
3998 {
3717 if (ParentGroup.RootPart.GetStatusSandbox()) 3999 if (ParentGroup.RootPart.GetStatusSandbox())
3718 { 4000 {
3719 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4001 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -3770,10 +4052,22 @@ namespace OpenSim.Region.Framework.Scenes
3770 baseMask; 4052 baseMask;
3771 break; 4053 break;
3772 case 8: 4054 case 8:
4055 // Trying to set export permissions - extra checks
4056 if (set && (mask & (uint)PermissionMask.Export) != 0)
4057 {
4058 if ((OwnerMask & (uint)PermissionMask.Export) == 0 || (BaseMask & (uint)PermissionMask.Export) == 0 || (NextOwnerMask & (uint)PermissionMask.All) != (uint)PermissionMask.All)
4059 mask &= ~(uint)PermissionMask.Export;
4060 }
3773 EveryoneMask = ApplyMask(EveryoneMask, set, mask) & 4061 EveryoneMask = ApplyMask(EveryoneMask, set, mask) &
3774 baseMask; 4062 baseMask;
3775 break; 4063 break;
3776 case 16: 4064 case 16:
4065 // Force full perm if export
4066 if ((EveryoneMask & (uint)PermissionMask.Export) != 0)
4067 {
4068 NextOwnerMask = (uint)PermissionMask.All;
4069 break;
4070 }
3777 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4071 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
3778 baseMask; 4072 baseMask;
3779 // Prevent the client from creating no mod, no copy 4073 // Prevent the client from creating no mod, no copy
@@ -3848,7 +4142,7 @@ namespace OpenSim.Region.Framework.Scenes
3848 // For now, we use the NINJA naming scheme for identifying joints. 4142 // For now, we use the NINJA naming scheme for identifying joints.
3849 // In the future, we can support other joint specification schemes such as a 4143 // In the future, we can support other joint specification schemes such as a
3850 // custom checkbox in the viewer GUI. 4144 // custom checkbox in the viewer GUI.
3851 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4145 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
3852 { 4146 {
3853 return IsHingeJoint() || IsBallJoint(); 4147 return IsHingeJoint() || IsBallJoint();
3854 } 4148 }
@@ -3858,6 +4152,26 @@ namespace OpenSim.Region.Framework.Scenes
3858 } 4152 }
3859 } 4153 }
3860 4154
4155 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4156 {
4157 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4158 return;
4159
4160 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4161 {
4162 PhysicsShapeType = (byte)physdata.PhysShapeType;
4163
4164 }
4165
4166 if(Density != physdata.Density)
4167 Density = physdata.Density;
4168 if(GravityModifier != physdata.GravitationModifier)
4169 GravityModifier = physdata.GravitationModifier;
4170 if(Friction != physdata.Friction)
4171 Friction = physdata.Friction;
4172 if(Restitution != physdata.Bounce)
4173 Restitution = physdata.Bounce;
4174 }
3861 /// <summary> 4175 /// <summary>
3862 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4176 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3863 /// </summary> 4177 /// </summary>
@@ -3928,7 +4242,8 @@ namespace OpenSim.Region.Framework.Scenes
3928 } 4242 }
3929 4243
3930 if (SetPhantom 4244 if (SetPhantom
3931 || ParentGroup.IsAttachment 4245 || ParentGroup.IsAttachmentCheckFull()
4246 || PhysicsShapeType == (byte)PhysShapeType.none
3932 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints 4247 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3933 { 4248 {
3934 AddFlag(PrimFlags.Phantom); 4249 AddFlag(PrimFlags.Phantom);
@@ -3948,32 +4263,17 @@ namespace OpenSim.Region.Framework.Scenes
3948 4263
3949 if (ParentGroup.Scene.CollidablePrims && pa == null) 4264 if (ParentGroup.Scene.CollidablePrims && pa == null)
3950 { 4265 {
3951 pa = AddToPhysics(UsePhysics); 4266 AddToPhysics(UsePhysics, SetPhantom, false);
4267 pa = PhysActor;
3952 4268
3953 if (pa != null) 4269 if (pa != null)
3954 { 4270 {
3955 pa.SetMaterial(Material); 4271 pa.SetMaterial(Material);
4272 pa.Position = GetWorldPosition();
4273 pa.Orientation = GetWorldRotation();
3956 DoPhysicsPropertyUpdate(UsePhysics, true); 4274 DoPhysicsPropertyUpdate(UsePhysics, true);
3957 4275
3958 if ( 4276 SubscribeForCollisionEvents();
3959 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
3960 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3961 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3962 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
3963 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
3964 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
3965 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
3966 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3967 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3968 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
3969 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
3970 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
3971 (CollisionSound != UUID.Zero)
3972 )
3973 {
3974 pa.OnCollisionUpdate += PhysicsCollision;
3975 pa.SubscribeEvents(1000);
3976 }
3977 } 4277 }
3978 } 4278 }
3979 else // it already has a physical representation 4279 else // it already has a physical representation
@@ -4028,6 +4328,50 @@ namespace OpenSim.Region.Framework.Scenes
4028 } 4328 }
4029 4329
4030 /// <summary> 4330 /// <summary>
4331 /// Subscribe for physics collision events if needed for scripts and sounds
4332 /// </summary>
4333 public void SubscribeForCollisionEvents()
4334 {
4335 PhysicsActor pa = PhysActor;
4336
4337 if (pa != null)
4338 {
4339 if (
4340 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4344 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4345 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4350 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4351 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4352 (CollisionSound != UUID.Zero)
4353 )
4354 {
4355 if (!pa.SubscribedEvents())
4356 {
4357 // If not already subscribed for event, set up for a collision event.
4358 pa.OnCollisionUpdate += PhysicsCollision;
4359 pa.SubscribeEvents(1000);
4360 }
4361 }
4362 else
4363 {
4364 // There is no need to be subscribed to collisions so, if subscribed, remove subscription
4365 if (pa.SubscribedEvents())
4366 {
4367 pa.OnCollisionUpdate -= PhysicsCollision;
4368 pa.UnSubscribeEvents();
4369 }
4370 }
4371 }
4372 }
4373
4374 /// <summary>
4031 /// Adds this part to the physics scene. 4375 /// Adds this part to the physics scene.
4032 /// </summary> 4376 /// </summary>
4033 /// <remarks>This method also sets the PhysActor property.</remarks> 4377 /// <remarks>This method also sets the PhysActor property.</remarks>
@@ -4035,10 +4379,13 @@ namespace OpenSim.Region.Framework.Scenes
4035 /// <returns> 4379 /// <returns>
4036 /// The physics actor. null if there was a failure. 4380 /// The physics actor. null if there was a failure.
4037 /// </returns> 4381 /// </returns>
4038 private PhysicsActor AddToPhysics(bool rigidBody) 4382 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics)
4039 { 4383 {
4040 PhysicsActor pa; 4384 PhysicsActor pa;
4041 4385
4386 Vector3 velocity = Velocity;
4387 Vector3 rotationalVelocity = AngularVelocity;;
4388
4042 try 4389 try
4043 { 4390 {
4044 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4391 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
@@ -4046,8 +4393,10 @@ namespace OpenSim.Region.Framework.Scenes
4046 Shape, 4393 Shape,
4047 AbsolutePosition, 4394 AbsolutePosition,
4048 Scale, 4395 Scale,
4049 RotationOffset, 4396 GetWorldRotation(),
4050 rigidBody, 4397 isPhysical,
4398 isPhantom,
4399 PhysicsShapeType,
4051 m_localId); 4400 m_localId);
4052 } 4401 }
4053 catch (Exception e) 4402 catch (Exception e)
@@ -4056,20 +4405,56 @@ namespace OpenSim.Region.Framework.Scenes
4056 pa = null; 4405 pa = null;
4057 } 4406 }
4058 4407
4059 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4060 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4061 // being set.
4062 PhysActor = pa;
4063
4064 // Basic Physics can also return null as well as an exception catch.
4065 if (pa != null) 4408 if (pa != null)
4066 { 4409 {
4067 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4410 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4068 pa.SetMaterial(Material); 4411 pa.SetMaterial(Material);
4069 DoPhysicsPropertyUpdate(rigidBody, true); 4412
4413 pa.Density = Density;
4414 pa.GravModifier = GravityModifier;
4415 pa.Friction = Friction;
4416 pa.Restitution = Restitution;
4417
4418 if (VolumeDetectActive) // change if not the default only
4419 pa.SetVolumeDetect(1);
4420 // we are going to tell rest of code about physics so better have this here
4421 PhysActor = pa;
4422
4423 if (isPhysical)
4424 {
4425 if (ParentGroup.RootPart.KeyframeMotion != null)
4426 ParentGroup.RootPart.KeyframeMotion.Stop();
4427 ParentGroup.RootPart.KeyframeMotion = null;
4428 ParentGroup.Scene.AddPhysicalPrim(1);
4429
4430 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4431 pa.OnOutOfBounds += PhysicsOutOfBounds;
4432
4433 if (ParentID != 0 && ParentID != LocalId)
4434 {
4435 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4436
4437 if (parentPa != null)
4438 {
4439 pa.link(parentPa);
4440 }
4441 }
4442 }
4443
4444 if (applyDynamics)
4445 // do independent of isphysical so parameters get setted (at least some)
4446 {
4447 Velocity = velocity;
4448 AngularVelocity = rotationalVelocity;
4449// pa.Velocity = velocity;
4450 pa.RotationalVelocity = rotationalVelocity;
4451 }
4452
4453 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4070 } 4454 }
4071 4455
4072 return pa; 4456 PhysActor = pa;
4457 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4073 } 4458 }
4074 4459
4075 /// <summary> 4460 /// <summary>
@@ -4082,7 +4467,9 @@ namespace OpenSim.Region.Framework.Scenes
4082 /// </remarks> 4467 /// </remarks>
4083 public void RemoveFromPhysics() 4468 public void RemoveFromPhysics()
4084 { 4469 {
4085 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4470 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
4471 if (ParentGroup.Scene.PhysicsScene != null)
4472 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
4086 PhysActor = null; 4473 PhysActor = null;
4087 } 4474 }
4088 4475
@@ -4255,8 +4642,33 @@ namespace OpenSim.Region.Framework.Scenes
4255 4642
4256 Changed changeFlags = 0; 4643 Changed changeFlags = 0;
4257 4644
4645 Primitive.TextureEntryFace fallbackNewFace = newTex.DefaultTexture;
4646 Primitive.TextureEntryFace fallbackOldFace = oldTex.DefaultTexture;
4647
4648 // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all
4649 // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point.
4650 if (fallbackNewFace == null)
4651 {
4652 fallbackNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
4653 newTex.DefaultTexture = fallbackNewFace;
4654 }
4655 if (fallbackOldFace == null)
4656 {
4657 fallbackOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
4658 oldTex.DefaultTexture = fallbackOldFace;
4659 }
4660
4661 // Materials capable viewers can send a ObjectImage packet
4662 // when nothing in TE has changed. MaterialID should be updated
4663 // by the RenderMaterials CAP handler, so updating it here may cause a
4664 // race condtion. Therefore, if no non-materials TE fields have changed,
4665 // we should ignore any changes and not update Shape.TextureEntry
4666
4667 bool otherFieldsChanged = false;
4668
4258 for (int i = 0 ; i < GetNumberOfSides(); i++) 4669 for (int i = 0 ; i < GetNumberOfSides(); i++)
4259 { 4670 {
4671
4260 Primitive.TextureEntryFace newFace = newTex.DefaultTexture; 4672 Primitive.TextureEntryFace newFace = newTex.DefaultTexture;
4261 Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture; 4673 Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture;
4262 4674
@@ -4280,18 +4692,36 @@ namespace OpenSim.Region.Framework.Scenes
4280 // Max change, skip the rest of testing 4692 // Max change, skip the rest of testing
4281 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 4693 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
4282 break; 4694 break;
4695
4696 if (!otherFieldsChanged)
4697 {
4698 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
4699 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
4700 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
4701 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
4702 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
4703 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
4704 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
4705 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
4706 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
4707 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
4708 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
4709 }
4283 } 4710 }
4284 4711
4285 m_shape.TextureEntry = newTex.GetBytes(); 4712 if (changeFlags != 0 || otherFieldsChanged)
4286 if (changeFlags != 0) 4713 {
4287 TriggerScriptChangedEvent(changeFlags); 4714 m_shape.TextureEntry = newTex.GetBytes();
4288 UpdateFlag = UpdateRequired.FULL; 4715 if (changeFlags != 0)
4289 ParentGroup.HasGroupChanged = true; 4716 TriggerScriptChangedEvent(changeFlags);
4717 UpdateFlag = UpdateRequired.FULL;
4718 ParentGroup.HasGroupChanged = true;
4290 4719
4291 //This is madness.. 4720 //This is madness..
4292 //ParentGroup.ScheduleGroupForFullUpdate(); 4721 //ParentGroup.ScheduleGroupForFullUpdate();
4293 //This is sparta 4722 //This is sparta
4294 ScheduleFullUpdate(); 4723 ScheduleFullUpdate();
4724 }
4295 } 4725 }
4296 4726
4297 public void aggregateScriptEvents() 4727 public void aggregateScriptEvents()
@@ -4331,39 +4761,7 @@ namespace OpenSim.Region.Framework.Scenes
4331 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4761 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4332 } 4762 }
4333 4763
4334 PhysicsActor pa = PhysActor; 4764 SubscribeForCollisionEvents();
4335
4336 if (
4337 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4338 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4339 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4340 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4343 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4344 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4345 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4349 (CollisionSound != UUID.Zero)
4350 )
4351 {
4352 // subscribe to physics updates.
4353 if (pa != null)
4354 {
4355 pa.OnCollisionUpdate += PhysicsCollision;
4356 pa.SubscribeEvents(1000);
4357 }
4358 }
4359 else
4360 {
4361 if (pa != null)
4362 {
4363 pa.UnSubscribeEvents();
4364 pa.OnCollisionUpdate -= PhysicsCollision;
4365 }
4366 }
4367 4765
4368 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 4766 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4369 //{ 4767 //{
@@ -4449,12 +4847,76 @@ namespace OpenSim.Region.Framework.Scenes
4449 { 4847 {
4450 ParentGroup.AddScriptLPS(count); 4848 ParentGroup.AddScriptLPS(count);
4451 } 4849 }
4850
4851 /// <summary>
4852 /// Sets a prim's owner and permissions when it's rezzed.
4853 /// </summary>
4854 /// <param name="item">The inventory item from which the item was rezzed</param>
4855 /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
4856 /// <param name="scene">The scene the prim is being rezzed into</param>
4857 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
4858 {
4859 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
4860 {
4861 if (scene.Permissions.PropagatePermissions())
4862 {
4863 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
4864 {
4865 // Apply the item's permissions to the object
4866 //LogPermissions("Before applying item permissions");
4867 if (userInventory)
4868 {
4869 EveryoneMask = item.EveryOnePermissions;
4870 NextOwnerMask = item.NextPermissions;
4871 }
4872 else
4873 {
4874 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
4875 EveryoneMask = item.EveryOnePermissions;
4876 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
4877 NextOwnerMask = item.NextPermissions;
4878 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
4879 GroupMask = item.GroupPermissions;
4880 }
4881 //LogPermissions("After applying item permissions");
4882 }
4883 }
4884
4885 GroupMask = 0; // DO NOT propagate here
4886 }
4887
4888 if (OwnerID != item.Owner)
4889 {
4890 //LogPermissions("Before ApplyNextOwnerPermissions");
4891
4892 if (scene.Permissions.PropagatePermissions())
4893 ApplyNextOwnerPermissions();
4894
4895 //LogPermissions("After ApplyNextOwnerPermissions");
4896
4897 LastOwnerID = OwnerID;
4898 OwnerID = item.Owner;
4899 Inventory.ChangeInventoryOwner(item.Owner);
4900 }
4901 }
4902
4903 /// <summary>
4904 /// Logs the prim's permissions. Useful when debugging permission problems.
4905 /// </summary>
4906 /// <param name="message"></param>
4907 private void LogPermissions(String message)
4908 {
4909 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
4910 }
4452 4911
4453 public void ApplyNextOwnerPermissions() 4912 public void ApplyNextOwnerPermissions()
4454 { 4913 {
4455 BaseMask &= NextOwnerMask; 4914 // Export needs to be preserved in the base and everyone
4915 // mask, but removed in the owner mask as a next owner
4916 // can never change the export status
4917 BaseMask &= NextOwnerMask | (uint)PermissionMask.Export;
4456 OwnerMask &= NextOwnerMask; 4918 OwnerMask &= NextOwnerMask;
4457 EveryoneMask &= NextOwnerMask; 4919 EveryoneMask &= NextOwnerMask | (uint)PermissionMask.Export;
4458 4920
4459 Inventory.ApplyNextOwnerPermissions(); 4921 Inventory.ApplyNextOwnerPermissions();
4460 } 4922 }
@@ -4463,20 +4925,34 @@ namespace OpenSim.Region.Framework.Scenes
4463 { 4925 {
4464 try 4926 try
4465 { 4927 {
4466 if (APIDTarget != Quaternion.Identity) 4928 if (APIDActive)
4467 { 4929 {
4468 if (m_APIDIterations <= 1) 4930 PhysicsActor pa = ParentGroup.RootPart.PhysActor;
4931 if (pa == null || !pa.IsPhysical || APIDStrength < 0.04)
4469 { 4932 {
4470 UpdateRotation(APIDTarget); 4933 StopLookAt();
4471 APIDTarget = Quaternion.Identity;
4472 return; 4934 return;
4473 } 4935 }
4474 4936
4475 Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations); 4937 Quaternion currRot = GetWorldRotation();
4476 rot.Normalize(); 4938 currRot.Normalize();
4477 UpdateRotation(rot); 4939
4940 // difference between current orientation and desired orientation
4941 Quaternion dR = currRot / APIDTarget;
4942
4943 // find axis and angle of rotation to rotate to desired orientation
4944 Vector3 axis = Vector3.UnitX;
4945 float angle;
4946 dR.GetAxisAngle(out axis, out angle);
4947 axis = axis * currRot;
4948
4949 // clamp strength to avoid overshoot
4950 float strength = 1.0f / APIDStrength;
4951 if (strength > 1.0) strength = 1.0f;
4478 4952
4479 m_APIDIterations--; 4953 // set angular velocity to rotate to desired orientation
4954 // with velocity proportional to strength and angle
4955 AngularVelocity = axis * angle * strength * (float)Math.PI;
4480 4956
4481 // This ensures that we'll check this object on the next iteration 4957 // This ensures that we'll check this object on the next iteration
4482 ParentGroup.QueueForUpdateCheck(); 4958 ParentGroup.QueueForUpdateCheck();
@@ -4502,19 +4978,19 @@ namespace OpenSim.Region.Framework.Scenes
4502 /// true if the avatar was not already recorded, false otherwise. 4978 /// true if the avatar was not already recorded, false otherwise.
4503 /// </returns> 4979 /// </returns>
4504 /// <param name='avatarId'></param> 4980 /// <param name='avatarId'></param>
4505 protected internal bool AddSittingAvatar(UUID avatarId) 4981 protected internal bool AddSittingAvatar(ScenePresence sp)
4506 { 4982 {
4507 lock (ParentGroup.m_sittingAvatars) 4983 lock (ParentGroup.m_sittingAvatars)
4508 { 4984 {
4509 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero) 4985 if (IsSitTargetSet && SitTargetAvatar == UUID.Zero)
4510 SitTargetAvatar = avatarId; 4986 SitTargetAvatar = sp.UUID;
4511 4987
4512 if (m_sittingAvatars == null) 4988 if (m_sittingAvatars == null)
4513 m_sittingAvatars = new HashSet<UUID>(); 4989 m_sittingAvatars = new HashSet<ScenePresence>();
4514 4990
4515 if (m_sittingAvatars.Add(avatarId)) 4991 if (m_sittingAvatars.Add(sp))
4516 { 4992 {
4517 ParentGroup.m_sittingAvatars.Add(avatarId); 4993 ParentGroup.m_sittingAvatars.Add(sp);
4518 4994
4519 return true; 4995 return true;
4520 } 4996 }
@@ -4531,22 +5007,22 @@ namespace OpenSim.Region.Framework.Scenes
4531 /// true if the avatar was present and removed, false if it was not present. 5007 /// true if the avatar was present and removed, false if it was not present.
4532 /// </returns> 5008 /// </returns>
4533 /// <param name='avatarId'></param> 5009 /// <param name='avatarId'></param>
4534 protected internal bool RemoveSittingAvatar(UUID avatarId) 5010 protected internal bool RemoveSittingAvatar(ScenePresence sp)
4535 { 5011 {
4536 lock (ParentGroup.m_sittingAvatars) 5012 lock (ParentGroup.m_sittingAvatars)
4537 { 5013 {
4538 if (SitTargetAvatar == avatarId) 5014 if (SitTargetAvatar == sp.UUID)
4539 SitTargetAvatar = UUID.Zero; 5015 SitTargetAvatar = UUID.Zero;
4540 5016
4541 if (m_sittingAvatars == null) 5017 if (m_sittingAvatars == null)
4542 return false; 5018 return false;
4543 5019
4544 if (m_sittingAvatars.Remove(avatarId)) 5020 if (m_sittingAvatars.Remove(sp))
4545 { 5021 {
4546 if (m_sittingAvatars.Count == 0) 5022 if (m_sittingAvatars.Count == 0)
4547 m_sittingAvatars = null; 5023 m_sittingAvatars = null;
4548 5024
4549 ParentGroup.m_sittingAvatars.Remove(avatarId); 5025 ParentGroup.m_sittingAvatars.Remove(sp);
4550 5026
4551 return true; 5027 return true;
4552 } 5028 }
@@ -4560,14 +5036,14 @@ namespace OpenSim.Region.Framework.Scenes
4560 /// </summary> 5036 /// </summary>
4561 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks> 5037 /// <remarks>This applies to all sitting avatars whether there is a sit target set or not.</remarks>
4562 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns> 5038 /// <returns>A hashset of the sitting avatars. Returns null if there are no sitting avatars.</returns>
4563 public HashSet<UUID> GetSittingAvatars() 5039 public HashSet<ScenePresence> GetSittingAvatars()
4564 { 5040 {
4565 lock (ParentGroup.m_sittingAvatars) 5041 lock (ParentGroup.m_sittingAvatars)
4566 { 5042 {
4567 if (m_sittingAvatars == null) 5043 if (m_sittingAvatars == null)
4568 return null; 5044 return null;
4569 else 5045 else
4570 return new HashSet<UUID>(m_sittingAvatars); 5046 return new HashSet<ScenePresence>(m_sittingAvatars);
4571 } 5047 }
4572 } 5048 }
4573 5049