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.cs1669
1 files changed, 1118 insertions, 551 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d1c5f72..52f9b51 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.Framework.Scenes
64 TELEPORT = 512, 64 TELEPORT = 512,
65 REGION_RESTART = 1024, 65 REGION_RESTART = 1024,
66 MEDIA = 2048, 66 MEDIA = 2048,
67 ANIMATION = 16384 67 ANIMATION = 16384,
68 POSITION = 32768
68 } 69 }
69 70
70 // I don't really know where to put this except here. 71 // I don't really know where to put this except here.
@@ -123,7 +124,18 @@ namespace OpenSim.Region.Framework.Scenes
123 /// Denote all sides of the prim 124 /// Denote all sides of the prim
124 /// </value> 125 /// </value>
125 public const int ALL_SIDES = -1; 126 public const int ALL_SIDES = -1;
126 127
128 private const scriptEvents PhysicsNeededSubsEvents = (
129 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
130 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
131 );
132 private const scriptEvents PhyscicsPhantonSubsEvents = (
133 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
134 );
135 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
136 scriptEvents.collision_start | scriptEvents.collision_end
137 );
138
127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 139 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
128 140
129 /// <summary> 141 /// <summary>
@@ -160,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes
160 /// </remarks> 172 /// </remarks>
161 public bool IsRoot 173 public bool IsRoot
162 { 174 {
163 get { return ParentGroup.RootPart == this; } 175 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
164 } 176 }
165 177
166 /// <summary> 178 /// <summary>
@@ -233,11 +245,22 @@ namespace OpenSim.Region.Framework.Scenes
233 245
234 public uint TimeStampTerse; 246 public uint TimeStampTerse;
235 247
236 public int STATUS_ROTATE_X; 248 // The following two are to hold the attachment data
249 // while an object is inworld
250 [XmlIgnore]
251 public byte AttachPoint = 0;
252
253 [XmlIgnore]
254 public Quaternion AttachRotation = Quaternion.Identity;
237 255
238 public int STATUS_ROTATE_Y; 256 [XmlIgnore]
257 public int STATUS_ROTATE_X; // this should not be used
258
259 [XmlIgnore]
260 public int STATUS_ROTATE_Y; // this should not be used
239 261
240 public int STATUS_ROTATE_Z; 262 [XmlIgnore]
263 public int STATUS_ROTATE_Z; // this should not be used
241 264
242 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>(); 265 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
243 266
@@ -257,10 +280,12 @@ namespace OpenSim.Region.Framework.Scenes
257 280
258 public Vector3 AttachedPos; 281 public Vector3 AttachedPos;
259 282
260 public Vector3 RotationAxis = Vector3.One; 283 // rotation locks on local X,Y and or Z axis bit flags
284 // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum
285 // but reversed logic: bit cleared means free to rotate
286 public byte RotationAxisLocks = 0;
261 287
262 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 288 public bool VolumeDetectActive;
263 // Certainly this must be a persistant setting finally
264 289
265 public bool IsWaitingForFirstSpinUpdatePacket; 290 public bool IsWaitingForFirstSpinUpdatePacket;
266 291
@@ -300,10 +325,10 @@ namespace OpenSim.Region.Framework.Scenes
300 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 325 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
301 private Vector3 m_sitTargetPosition; 326 private Vector3 m_sitTargetPosition;
302 private string m_sitAnimation = "SIT"; 327 private string m_sitAnimation = "SIT";
328 private bool m_occupied; // KF if any av is sitting on this prim
303 private string m_text = String.Empty; 329 private string m_text = String.Empty;
304 private string m_touchName = String.Empty; 330 private string m_touchName = String.Empty;
305 private readonly List<UndoState> m_undo = new List<UndoState>(5); 331 private UndoRedoState m_UndoRedo = null;
306 private readonly List<UndoState> m_redo = new List<UndoState>(5);
307 332
308 private bool m_passTouches = false; 333 private bool m_passTouches = false;
309 private bool m_passCollisions = false; 334 private bool m_passCollisions = false;
@@ -331,14 +356,20 @@ namespace OpenSim.Region.Framework.Scenes
331 protected Vector3 m_lastVelocity; 356 protected Vector3 m_lastVelocity;
332 protected Vector3 m_lastAcceleration; 357 protected Vector3 m_lastAcceleration;
333 protected Vector3 m_lastAngularVelocity; 358 protected Vector3 m_lastAngularVelocity;
334 protected int m_lastTerseSent; 359 protected int m_lastUpdateSentTime;
360 protected float m_buoyancy = 0.0f;
361 protected Vector3 m_force;
362 protected Vector3 m_torque;
335 363
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 364 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3 365 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f; 366 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood 367 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood 368 protected float m_bounce = 0.5f; // wood
341 369
370
371 protected bool m_isSelected = false;
372
342 /// <summary> 373 /// <summary>
343 /// Stores media texture data 374 /// Stores media texture data
344 /// </summary> 375 /// </summary>
@@ -350,15 +381,23 @@ namespace OpenSim.Region.Framework.Scenes
350 private Vector3 m_cameraAtOffset; 381 private Vector3 m_cameraAtOffset;
351 private bool m_forceMouselook; 382 private bool m_forceMouselook;
352 383
353 // TODO: Collision sound should have default. 384
385 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
386 private sbyte m_collisionSoundType;
354 private UUID m_collisionSound; 387 private UUID m_collisionSound;
355 private float m_collisionSoundVolume; 388 private float m_collisionSoundVolume;
356 389
390 private int LastColSoundSentTime;
391
392
393 private SOPVehicle m_vehicleParams = null;
394
357 public KeyframeMotion KeyframeMotion 395 public KeyframeMotion KeyframeMotion
358 { 396 {
359 get; set; 397 get; set;
360 } 398 }
361 399
400
362 #endregion Fields 401 #endregion Fields
363 402
364// ~SceneObjectPart() 403// ~SceneObjectPart()
@@ -388,6 +427,7 @@ namespace OpenSim.Region.Framework.Scenes
388 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 427 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
389 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 428 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
390 m_inventory = new SceneObjectPartInventory(this); 429 m_inventory = new SceneObjectPartInventory(this);
430 LastColSoundSentTime = Util.EnvironmentTickCount();
391 } 431 }
392 432
393 /// <summary> 433 /// <summary>
@@ -402,7 +442,7 @@ namespace OpenSim.Region.Framework.Scenes
402 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 442 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
403 Quaternion rotationOffset, Vector3 offsetPosition) : this() 443 Quaternion rotationOffset, Vector3 offsetPosition) : this()
404 { 444 {
405 m_name = "Primitive"; 445 m_name = "Object";
406 446
407 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 447 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
408 LastOwnerID = CreatorID = OwnerID = ownerID; 448 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -441,7 +481,7 @@ namespace OpenSim.Region.Framework.Scenes
441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export); 481 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
442 private uint _groupMask = (uint)PermissionMask.None; 482 private uint _groupMask = (uint)PermissionMask.None;
443 private uint _everyoneMask = (uint)PermissionMask.None; 483 private uint _everyoneMask = (uint)PermissionMask.None;
444 private uint _nextOwnerMask = (uint)PermissionMask.All; 484 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
445 private PrimFlags _flags = PrimFlags.None; 485 private PrimFlags _flags = PrimFlags.None;
446 private DateTime m_expires; 486 private DateTime m_expires;
447 private DateTime m_rezzed; 487 private DateTime m_rezzed;
@@ -539,12 +579,16 @@ namespace OpenSim.Region.Framework.Scenes
539 } 579 }
540 580
541 /// <value> 581 /// <value>
542 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 582 /// Get the inventory list
543 /// </value> 583 /// </value>
544 public TaskInventoryDictionary TaskInventory 584 public TaskInventoryDictionary TaskInventory
545 { 585 {
546 get { return m_inventory.Items; } 586 get {
547 set { m_inventory.Items = value; } 587 return m_inventory.Items;
588 }
589 set {
590 m_inventory.Items = value;
591 }
548 } 592 }
549 593
550 /// <summary> 594 /// <summary>
@@ -594,20 +638,6 @@ namespace OpenSim.Region.Framework.Scenes
594 } 638 }
595 } 639 }
596 640
597 public byte Material
598 {
599 get { return (byte) m_material; }
600 set
601 {
602 m_material = (Material)value;
603
604 PhysicsActor pa = PhysActor;
605
606 if (pa != null)
607 pa.SetMaterial((int)value);
608 }
609 }
610
611 [XmlIgnore] 641 [XmlIgnore]
612 public bool PassTouches 642 public bool PassTouches
613 { 643 {
@@ -633,6 +663,19 @@ namespace OpenSim.Region.Framework.Scenes
633 } 663 }
634 } 664 }
635 665
666 public bool IsSelected
667 {
668 get { return m_isSelected; }
669 set
670 {
671 m_isSelected = value;
672 if (ParentGroup != null)
673 ParentGroup.PartSelectChanged(value);
674
675 }
676 }
677
678
636 public Dictionary<int, string> CollisionFilter 679 public Dictionary<int, string> CollisionFilter
637 { 680 {
638 get { return m_CollisionFilter; } 681 get { return m_CollisionFilter; }
@@ -707,14 +750,12 @@ namespace OpenSim.Region.Framework.Scenes
707 set { m_LoopSoundSlavePrims = value; } 750 set { m_LoopSoundSlavePrims = value; }
708 } 751 }
709 752
710
711 public Byte[] TextureAnimation 753 public Byte[] TextureAnimation
712 { 754 {
713 get { return m_TextureAnimation; } 755 get { return m_TextureAnimation; }
714 set { m_TextureAnimation = value; } 756 set { m_TextureAnimation = value; }
715 } 757 }
716 758
717
718 public Byte[] ParticleSystem 759 public Byte[] ParticleSystem
719 { 760 {
720 get { return m_particleSystem; } 761 get { return m_particleSystem; }
@@ -742,18 +783,28 @@ namespace OpenSim.Region.Framework.Scenes
742 set { m_damage = value; } 783 set { m_damage = value; }
743 } 784 }
744 785
786 public void setGroupPosition(Vector3 pos)
787 {
788 m_groupPosition = pos;
789 }
790
745 /// <summary> 791 /// <summary>
746 /// The position of the entire group that this prim belongs to. 792 /// The position of the entire group that this prim belongs to.
747 /// </summary> 793 /// </summary>
794 ///
795
748 public Vector3 GroupPosition 796 public Vector3 GroupPosition
749 { 797 {
750 get 798 get
751 { 799 {
752 // If this is a linkset, we don't want the physics engine mucking up our group position here. 800 // If this is a linkset, we don't want the physics engine mucking up our group position here.
753 PhysicsActor actor = PhysActor; 801 PhysicsActor actor = PhysActor;
754 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 802 if (ParentID == 0)
755 if (actor != null && ParentID == 0) 803 {
756 m_groupPosition = actor.Position; 804 if (actor != null)
805 m_groupPosition = actor.Position;
806 return m_groupPosition;
807 }
757 808
758 // If I'm an attachment, my position is reported as the position of who I'm attached to 809 // If I'm an attachment, my position is reported as the position of who I'm attached to
759 if (ParentGroup.IsAttachment) 810 if (ParentGroup.IsAttachment)
@@ -763,21 +814,23 @@ namespace OpenSim.Region.Framework.Scenes
763 return sp.AbsolutePosition; 814 return sp.AbsolutePosition;
764 } 815 }
765 816
817 // use root prim's group position. Physics may have updated it
818 if (ParentGroup.RootPart != this)
819 m_groupPosition = ParentGroup.RootPart.GroupPosition;
766 return m_groupPosition; 820 return m_groupPosition;
767 } 821 }
768 set 822 set
769 { 823 {
770 m_groupPosition = value; 824 m_groupPosition = value;
771
772 PhysicsActor actor = PhysActor; 825 PhysicsActor actor = PhysActor;
773 if (actor != null) 826 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
774 { 827 {
775 try 828 try
776 { 829 {
777 // Root prim actually goes at Position 830 // Root prim actually goes at Position
778 if (ParentID == 0) 831 if (ParentID == 0)
779 { 832 {
780 actor.Position = value; 833 actor.Position = value;
781 } 834 }
782 else 835 else
783 { 836 {
@@ -798,12 +851,17 @@ namespace OpenSim.Region.Framework.Scenes
798 } 851 }
799 } 852 }
800 853
854 public void setOffsetPosition(Vector3 pos)
855 {
856 m_offsetPosition = pos;
857 }
858
801 public Vector3 OffsetPosition 859 public Vector3 OffsetPosition
802 { 860 {
803 get { return m_offsetPosition; } 861 get { return m_offsetPosition; }
804 set 862 set
805 { 863 {
806// StoreUndoState(); 864 Vector3 oldpos = m_offsetPosition;
807 m_offsetPosition = value; 865 m_offsetPosition = value;
808 866
809 if (ParentGroup != null && !ParentGroup.IsDeleted) 867 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -815,10 +873,26 @@ namespace OpenSim.Region.Framework.Scenes
815 actor.Orientation = GetWorldRotation(); 873 actor.Orientation = GetWorldRotation();
816 874
817 // Tell the physics engines that this prim changed. 875 // Tell the physics engines that this prim changed.
818 if (ParentGroup.Scene != null) 876 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 877 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
820 } 878 }
879
880 if (!m_parentGroup.m_dupeInProgress)
881 {
882 List<ScenePresence> avs = ParentGroup.GetSittingAvatars();
883 foreach (ScenePresence av in avs)
884 {
885 if (av.ParentID == m_localId)
886 {
887 Vector3 offset = (m_offsetPosition - oldpos);
888 av.AbsolutePosition += offset;
889// av.SendAvatarDataToAllAgents();
890 av.SendTerseUpdateToAllClients();
891 }
892 }
893 }
821 } 894 }
895 TriggerScriptChangedEvent(Changed.POSITION);
822 } 896 }
823 } 897 }
824 898
@@ -840,6 +914,11 @@ namespace OpenSim.Region.Framework.Scenes
840 } 914 }
841 } 915 }
842 916
917 public void setRotationOffset(Quaternion q)
918 {
919 m_rotationOffset = q;
920 }
921
843 public Quaternion RotationOffset 922 public Quaternion RotationOffset
844 { 923 {
845 get 924 get
@@ -869,7 +948,7 @@ namespace OpenSim.Region.Framework.Scenes
869 948
870 set 949 set
871 { 950 {
872 StoreUndoState(); 951// StoreUndoState();
873 m_rotationOffset = value; 952 m_rotationOffset = value;
874 953
875 PhysicsActor actor = PhysActor; 954 PhysicsActor actor = PhysActor;
@@ -960,7 +1039,7 @@ namespace OpenSim.Region.Framework.Scenes
960 get 1039 get
961 { 1040 {
962 PhysicsActor actor = PhysActor; 1041 PhysicsActor actor = PhysActor;
963 if ((actor != null) && actor.IsPhysical) 1042 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
964 { 1043 {
965 m_angularVelocity = actor.RotationalVelocity; 1044 m_angularVelocity = actor.RotationalVelocity;
966 } 1045 }
@@ -974,15 +1053,26 @@ namespace OpenSim.Region.Framework.Scenes
974 m_angularVelocity = value; 1053 m_angularVelocity = value;
975 1054
976 PhysicsActor actor = PhysActor; 1055 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical) 1056 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE)
1057 {
978 actor.RotationalVelocity = m_angularVelocity; 1058 actor.RotationalVelocity = m_angularVelocity;
1059 }
979 } 1060 }
980 } 1061 }
981 1062
982 /// <summary></summary> 1063 /// <summary></summary>
983 public Vector3 Acceleration 1064 public Vector3 Acceleration
984 { 1065 {
985 get { return m_acceleration; } 1066 get
1067 {
1068 PhysicsActor actor = PhysActor;
1069 if (actor != null)
1070 {
1071 m_acceleration = actor.Acceleration;
1072 }
1073 return m_acceleration;
1074 }
1075
986 set 1076 set
987 { 1077 {
988 if (Util.IsNanOrInfinity(value)) 1078 if (Util.IsNanOrInfinity(value))
@@ -1056,7 +1146,10 @@ namespace OpenSim.Region.Framework.Scenes
1056 public PrimitiveBaseShape Shape 1146 public PrimitiveBaseShape Shape
1057 { 1147 {
1058 get { return m_shape; } 1148 get { return m_shape; }
1059 set { m_shape = value;} 1149 set
1150 {
1151 m_shape = value;
1152 }
1060 } 1153 }
1061 1154
1062 /// <summary> 1155 /// <summary>
@@ -1069,7 +1162,6 @@ namespace OpenSim.Region.Framework.Scenes
1069 { 1162 {
1070 if (m_shape != null) 1163 if (m_shape != null)
1071 { 1164 {
1072 StoreUndoState();
1073 1165
1074 m_shape.Scale = value; 1166 m_shape.Scale = value;
1075 1167
@@ -1137,10 +1229,7 @@ namespace OpenSim.Region.Framework.Scenes
1137 { 1229 {
1138 get 1230 get
1139 { 1231 {
1140 if (ParentGroup.IsAttachment) 1232 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1141 return GroupPosition;
1142
1143 return m_offsetPosition + m_groupPosition;
1144 } 1233 }
1145 } 1234 }
1146 1235
@@ -1309,6 +1398,13 @@ namespace OpenSim.Region.Framework.Scenes
1309 _flags = value; 1398 _flags = value;
1310 } 1399 }
1311 } 1400 }
1401
1402 [XmlIgnore]
1403 public bool IsOccupied // KF If an av is sittingon this prim
1404 {
1405 get { return m_occupied; }
1406 set { m_occupied = value; }
1407 }
1312 1408
1313 /// <summary> 1409 /// <summary>
1314 /// 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 1410 /// 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
@@ -1359,12 +1455,41 @@ namespace OpenSim.Region.Framework.Scenes
1359 set { m_sitAnimation = value; } 1455 set { m_sitAnimation = value; }
1360 } 1456 }
1361 1457
1458 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1459
1460 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1461 // runtime thing.. do not persist
1462 [XmlIgnore]
1463 public sbyte CollisionSoundType
1464 {
1465 get
1466 {
1467 return m_collisionSoundType;
1468 }
1469 set
1470 {
1471 m_collisionSoundType = value;
1472 if (value == -1)
1473 m_collisionSound = invalidCollisionSoundUUID;
1474 else if (value == 0)
1475 m_collisionSound = UUID.Zero;
1476 }
1477 }
1478
1362 public UUID CollisionSound 1479 public UUID CollisionSound
1363 { 1480 {
1364 get { return m_collisionSound; } 1481 get { return m_collisionSound; }
1365 set 1482 set
1366 { 1483 {
1367 m_collisionSound = value; 1484 m_collisionSound = value;
1485
1486 if (value == invalidCollisionSoundUUID)
1487 m_collisionSoundType = -1;
1488 else if (value == UUID.Zero)
1489 m_collisionSoundType = 0;
1490 else
1491 m_collisionSoundType = 1;
1492
1368 aggregateScriptEvents(); 1493 aggregateScriptEvents();
1369 } 1494 }
1370 } 1495 }
@@ -1375,6 +1500,125 @@ namespace OpenSim.Region.Framework.Scenes
1375 set { m_collisionSoundVolume = value; } 1500 set { m_collisionSoundVolume = value; }
1376 } 1501 }
1377 1502
1503 public float Buoyancy
1504 {
1505 get
1506 {
1507 if (ParentGroup.RootPart == this)
1508 return m_buoyancy;
1509
1510 return ParentGroup.RootPart.Buoyancy;
1511 }
1512 set
1513 {
1514 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1515 {
1516 ParentGroup.RootPart.Buoyancy = value;
1517 return;
1518 }
1519 m_buoyancy = value;
1520 if (PhysActor != null)
1521 PhysActor.Buoyancy = value;
1522 }
1523 }
1524
1525 public Vector3 Force
1526 {
1527 get
1528 {
1529 if (ParentGroup.RootPart == this)
1530 return m_force;
1531
1532 return ParentGroup.RootPart.Force;
1533 }
1534
1535 set
1536 {
1537 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1538 {
1539 ParentGroup.RootPart.Force = value;
1540 return;
1541 }
1542 m_force = value;
1543 if (PhysActor != null)
1544 PhysActor.Force = value;
1545 }
1546 }
1547
1548 public Vector3 Torque
1549 {
1550 get
1551 {
1552 if (ParentGroup.RootPart == this)
1553 return m_torque;
1554
1555 return ParentGroup.RootPart.Torque;
1556 }
1557
1558 set
1559 {
1560 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1561 {
1562 ParentGroup.RootPart.Torque = value;
1563 return;
1564 }
1565 m_torque = value;
1566 if (PhysActor != null)
1567 PhysActor.Torque = value;
1568 }
1569 }
1570
1571 public byte Material
1572 {
1573 get { return (byte)m_material; }
1574 set
1575 {
1576 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1577 {
1578 bool update = false;
1579
1580 if (m_material != (Material)value)
1581 {
1582 update = true;
1583 m_material = (Material)value;
1584 }
1585
1586 if (m_friction != SOPMaterialData.friction(m_material))
1587 {
1588 update = true;
1589 m_friction = SOPMaterialData.friction(m_material);
1590 }
1591
1592 if (m_bounce != SOPMaterialData.bounce(m_material))
1593 {
1594 update = true;
1595 m_bounce = SOPMaterialData.bounce(m_material);
1596 }
1597
1598 if (update)
1599 {
1600 if (PhysActor != null)
1601 {
1602 PhysActor.SetMaterial((int)value);
1603 }
1604 if(ParentGroup != null)
1605 ParentGroup.HasGroupChanged = true;
1606 ScheduleFullUpdateIfNone();
1607 UpdatePhysRequired = true;
1608 }
1609 }
1610 }
1611 }
1612
1613 // not a propriety to move to methods place later
1614 private bool HasMesh()
1615 {
1616 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1617 return true;
1618 return false;
1619 }
1620
1621 // not a propriety to move to methods place later
1378 public byte DefaultPhysicsShapeType() 1622 public byte DefaultPhysicsShapeType()
1379 { 1623 {
1380 byte type; 1624 byte type;
@@ -1387,6 +1631,65 @@ namespace OpenSim.Region.Framework.Scenes
1387 return type; 1631 return type;
1388 } 1632 }
1389 1633
1634 [XmlIgnore]
1635 public bool UsesComplexCost
1636 {
1637 get
1638 {
1639 byte pst = PhysicsShapeType;
1640 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1641 return true;
1642 return false;
1643 }
1644 }
1645
1646 [XmlIgnore]
1647 public float PhysicsCost
1648 {
1649 get
1650 {
1651 if(PhysicsShapeType == (byte)PhysShapeType.none)
1652 return 0;
1653
1654 float cost = 0.1f;
1655 if (PhysActor != null)
1656 cost = PhysActor.PhysicsCost;
1657 else
1658 cost = 0.1f;
1659
1660 if ((Flags & PrimFlags.Physics) != 0)
1661 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1662 return cost;
1663 }
1664 }
1665
1666 [XmlIgnore]
1667 public float StreamingCost
1668 {
1669 get
1670 {
1671 float cost;
1672 if (PhysActor != null)
1673 cost = PhysActor.StreamCost;
1674 else
1675 cost = 1.0f;
1676 return 1.0f;
1677 }
1678 }
1679
1680 [XmlIgnore]
1681 public float SimulationCost
1682 {
1683 get
1684 {
1685 // ignoring scripts. Don't like considering them for this
1686 if((Flags & PrimFlags.Physics) != 0)
1687 return 1.0f;
1688
1689 return 0.5f;
1690 }
1691 }
1692
1390 public byte PhysicsShapeType 1693 public byte PhysicsShapeType
1391 { 1694 {
1392 get { return m_physicsShapeType; } 1695 get { return m_physicsShapeType; }
@@ -1420,11 +1723,14 @@ namespace OpenSim.Region.Framework.Scenes
1420 } 1723 }
1421 else if (PhysActor == null) 1724 else if (PhysActor == null)
1422 { 1725 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive); 1726 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1727 UpdatePhysicsSubscribedEvents();
1424 } 1728 }
1425 else 1729 else
1426 { 1730 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType; 1731 PhysActor.PhysicsShapeType = m_physicsShapeType;
1732// if (Shape.SculptEntry)
1733// CheckSculptAndLoad();
1428 } 1734 }
1429 1735
1430 if (ParentGroup != null) 1736 if (ParentGroup != null)
@@ -1526,6 +1832,7 @@ namespace OpenSim.Region.Framework.Scenes
1526 } 1832 }
1527 } 1833 }
1528 1834
1835
1529 #endregion Public Properties with only Get 1836 #endregion Public Properties with only Get
1530 1837
1531 private uint ApplyMask(uint val, bool set, uint mask) 1838 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1636,8 +1943,8 @@ namespace OpenSim.Region.Framework.Scenes
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1943 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1944 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1945 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1946
1639 } 1947 }
1640
1641 m_TextureAnimation = data; 1948 m_TextureAnimation = data;
1642 } 1949 }
1643 1950
@@ -1680,6 +1987,61 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 1987 }
1681 } 1988 }
1682 1989
1990 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1991 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1992 {
1993 if (ParentGroup == null || ParentGroup.IsDeleted)
1994 return;
1995
1996 if (ParentGroup.IsAttachment)
1997 return; // don't work on attachments (for now ??)
1998
1999 SceneObjectPart root = ParentGroup.RootPart;
2000
2001 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2002 return;
2003
2004 PhysicsActor pa = root.PhysActor;
2005
2006 if (pa == null || !pa.IsPhysical)
2007 return;
2008
2009 if (localGlobalTF)
2010 {
2011 pVel = pVel * GetWorldRotation();
2012 }
2013
2014 ParentGroup.Velocity = pVel;
2015 }
2016
2017 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
2018 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
2019 {
2020 if (ParentGroup == null || ParentGroup.IsDeleted)
2021 return;
2022
2023 if (ParentGroup.IsAttachment)
2024 return; // don't work on attachments (for now ??)
2025
2026 SceneObjectPart root = ParentGroup.RootPart;
2027
2028 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2029 return;
2030
2031 PhysicsActor pa = root.PhysActor;
2032
2033 if (pa == null || !pa.IsPhysical)
2034 return;
2035
2036 if (localGlobalTF)
2037 {
2038 pAngVel = pAngVel * GetWorldRotation();
2039 }
2040
2041 root.AngularVelocity = pAngVel;
2042 }
2043
2044
1683 /// <summary> 2045 /// <summary>
1684 /// hook to the physics scene to apply angular impulse 2046 /// hook to the physics scene to apply angular impulse
1685 /// This is sent up to the group, which then finds the root prim 2047 /// This is sent up to the group, which then finds the root prim
@@ -1700,7 +2062,7 @@ namespace OpenSim.Region.Framework.Scenes
1700 impulse = newimpulse; 2062 impulse = newimpulse;
1701 } 2063 }
1702 2064
1703 ParentGroup.applyAngularImpulse(impulse); 2065 ParentGroup.ApplyAngularImpulse(impulse);
1704 } 2066 }
1705 2067
1706 /// <summary> 2068 /// <summary>
@@ -1710,20 +2072,24 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// </summary> 2072 /// </summary>
1711 /// <param name="impulsei">Vector force</param> 2073 /// <param name="impulsei">Vector force</param>
1712 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2074 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1713 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2075
2076 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
2077 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1714 { 2078 {
1715 Vector3 impulse = impulsei; 2079 Vector3 torque = torquei;
1716 2080
1717 if (localGlobalTF) 2081 if (localGlobalTF)
1718 { 2082 {
2083/*
1719 Quaternion grot = GetWorldRotation(); 2084 Quaternion grot = GetWorldRotation();
1720 Quaternion AXgrot = grot; 2085 Quaternion AXgrot = grot;
1721 Vector3 AXimpulsei = impulsei; 2086 Vector3 AXimpulsei = impulsei;
1722 Vector3 newimpulse = AXimpulsei * AXgrot; 2087 Vector3 newimpulse = AXimpulsei * AXgrot;
1723 impulse = newimpulse; 2088 */
2089 torque *= GetWorldRotation();
1724 } 2090 }
1725 2091
1726 ParentGroup.setAngularImpulse(impulse); 2092 Torque = torque;
1727 } 2093 }
1728 2094
1729 /// <summary> 2095 /// <summary>
@@ -1731,7 +2097,9 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// </summary> 2097 /// </summary>
1732 /// <param name="rootObjectFlags"></param> 2098 /// <param name="rootObjectFlags"></param>
1733 /// <param name="VolumeDetectActive"></param> 2099 /// <param name="VolumeDetectActive"></param>
1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive) 2100 /// <param name="building"></param>
2101
2102 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1735 { 2103 {
1736 VolumeDetectActive = _VolumeDetectActive; 2104 VolumeDetectActive = _VolumeDetectActive;
1737 2105
@@ -1741,8 +2109,8 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (PhysicsShapeType == (byte)PhysShapeType.none) 2109 if (PhysicsShapeType == (byte)PhysShapeType.none)
1742 return; 2110 return;
1743 2111
1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2112 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2113 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1746 2114
1747 if (_VolumeDetectActive) 2115 if (_VolumeDetectActive)
1748 isPhantom = true; 2116 isPhantom = true;
@@ -1757,7 +2125,8 @@ namespace OpenSim.Region.Framework.Scenes
1757 && !ParentGroup.IsAttachmentCheckFull() 2125 && !ParentGroup.IsAttachmentCheckFull()
1758 && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 2126 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1759 { 2127 {
1760 AddToPhysics(isPhysical, isPhantom, isPhysical); 2128 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
2129 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1761 } 2130 }
1762 else 2131 else
1763 PhysActor = null; // just to be sure 2132 PhysActor = null; // just to be sure
@@ -1786,7 +2155,7 @@ namespace OpenSim.Region.Framework.Scenes
1786 /// <param name="linkNum"></param> 2155 /// <param name="linkNum"></param>
1787 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2156 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1788 /// <returns></returns> 2157 /// <returns></returns>
1789 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2158 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1790 { 2159 {
1791 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2160 // 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 2161 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
@@ -1816,6 +2185,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 dupe.Category = Category; 2185 dupe.Category = Category;
1817 dupe.m_rezzed = m_rezzed; 2186 dupe.m_rezzed = m_rezzed;
1818 2187
2188 dupe.m_UndoRedo = null;
2189 dupe.m_isSelected = false;
2190
2191 dupe.IgnoreUndoUpdate = false;
2192 dupe.Undoing = false;
2193
1819 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2194 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1820 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2195 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1821 2196
@@ -1830,7 +2205,8 @@ namespace OpenSim.Region.Framework.Scenes
1830 } 2205 }
1831 2206
1832 // Move afterwards ResetIDs as it clears the localID 2207 // Move afterwards ResetIDs as it clears the localID
1833 dupe.LocalId = localID; 2208 dupe.LocalId = plocalID;
2209
1834 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2210 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1835 dupe.LastOwnerID = OwnerID; 2211 dupe.LastOwnerID = OwnerID;
1836 2212
@@ -1857,8 +2233,12 @@ namespace OpenSim.Region.Framework.Scenes
1857*/ 2233*/
1858 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2234 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1859 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2235 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2236// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1860 } 2237 }
1861 2238
2239 if (dupe.PhysActor != null)
2240 dupe.PhysActor.LocalID = plocalID;
2241
1862 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2242 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1863 2243
1864// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2244// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1877,10 +2257,10 @@ namespace OpenSim.Region.Framework.Scenes
1877 { 2257 {
1878 if (asset != null) 2258 if (asset != null)
1879 SculptTextureCallback(asset); 2259 SculptTextureCallback(asset);
1880 else 2260// else
1881 m_log.WarnFormat( 2261// m_log.WarnFormat(
1882 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2262// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1883 Name, UUID, id); 2263// Name, UUID, id);
1884 } 2264 }
1885*/ 2265*/
1886 /// <summary> 2266 /// <summary>
@@ -1979,6 +2359,7 @@ namespace OpenSim.Region.Framework.Scenes
1979 2359
1980 /// <summary> 2360 /// <summary>
1981 /// Do a physics propery update for this part. 2361 /// Do a physics propery update for this part.
2362 /// now also updates phantom and volume detector
1982 /// </summary> 2363 /// </summary>
1983 /// <param name="UsePhysics"></param> 2364 /// <param name="UsePhysics"></param>
1984 /// <param name="isNew"></param> 2365 /// <param name="isNew"></param>
@@ -2004,64 +2385,69 @@ namespace OpenSim.Region.Framework.Scenes
2004 { 2385 {
2005 if (pa.IsPhysical) // implies UsePhysics==false for this block 2386 if (pa.IsPhysical) // implies UsePhysics==false for this block
2006 { 2387 {
2007 if (!isNew) 2388 if (!isNew) // implies UsePhysics==false for this block
2389 {
2008 ParentGroup.Scene.RemovePhysicalPrim(1); 2390 ParentGroup.Scene.RemovePhysicalPrim(1);
2009 2391
2010 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2392 Velocity = new Vector3(0, 0, 0);
2011 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2393 Acceleration = new Vector3(0, 0, 0);
2012 pa.delink(); 2394 if (ParentGroup.RootPart == this)
2395 AngularVelocity = new Vector3(0, 0, 0);
2013 2396
2014 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2397 if (pa.Phantom && !VolumeDetectActive)
2015 { 2398 {
2016 // destroy all joints connected to this now deactivated body 2399 RemoveFromPhysics();
2017 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2400 return;
2018 } 2401 }
2019 2402
2020 // stop client-side interpolation of all joint proxy objects that have just been deleted 2403 pa.IsPhysical = UsePhysics;
2021 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2404 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
2022 // which stops client-side interpolation of deactivated joint proxy objects. 2405 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2406 pa.delink();
2407 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2408 {
2409 // destroy all joints connected to this now deactivated body
2410 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2411 }
2412 }
2023 } 2413 }
2024 2414
2025 if (!UsePhysics && !isNew) 2415 if (pa.IsPhysical != UsePhysics)
2026 { 2416 pa.IsPhysical = UsePhysics;
2027 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
2028 // prim still has velocity and continues to interpolate its position along the old
2029 // velocity-vector.
2030 Velocity = new Vector3(0, 0, 0);
2031 Acceleration = new Vector3(0, 0, 0);
2032 AngularVelocity = new Vector3(0, 0, 0);
2033 //RotationalVelocity = new Vector3(0, 0, 0);
2034 }
2035 2417
2036 pa.IsPhysical = UsePhysics; 2418 if (UsePhysics)
2419 {
2420 if (ParentGroup.RootPart.KeyframeMotion != null)
2421 ParentGroup.RootPart.KeyframeMotion.Stop();
2422 ParentGroup.RootPart.KeyframeMotion = null;
2423 ParentGroup.Scene.AddPhysicalPrim(1);
2037 2424
2038 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2425 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2039 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2426 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
2040 /// that's not wholesome. Had to make Scene public
2041 //PhysActor = null;
2042 2427
2043 if ((Flags & PrimFlags.Phantom) == 0) 2428 if (ParentID != 0 && ParentID != LocalId)
2044 {
2045 if (UsePhysics)
2046 { 2429 {
2047 if (ParentGroup.RootPart.KeyframeMotion != null) 2430 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2048 ParentGroup.RootPart.KeyframeMotion.Stop();
2049 ParentGroup.RootPart.KeyframeMotion = null;
2050 ParentGroup.Scene.AddPhysicalPrim(1);
2051
2052 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2053 pa.OnOutOfBounds += PhysicsOutOfBounds;
2054 if (ParentID != 0 && ParentID != LocalId)
2055 {
2056 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2057 2431
2058 if (parentPa != null) 2432 if (parentPa != null)
2059 { 2433 {
2060 pa.link(parentPa); 2434 pa.link(parentPa);
2061 }
2062 } 2435 }
2063 } 2436 }
2064 } 2437 }
2438 }
2439
2440 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2441 if (pa.Phantom != phan)
2442 pa.Phantom = phan;
2443
2444// some engines dont' have this check still
2445// if (VolumeDetectActive != pa.IsVolumeDtc)
2446 {
2447 if (VolumeDetectActive)
2448 pa.SetVolumeDetect(1);
2449 else
2450 pa.SetVolumeDetect(0);
2065 } 2451 }
2066 2452
2067 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2453 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -2132,13 +2518,8 @@ namespace OpenSim.Region.Framework.Scenes
2132 2518
2133 public int GetAxisRotation(int axis) 2519 public int GetAxisRotation(int axis)
2134 { 2520 {
2135 //Cannot use ScriptBaseClass constants as no referance to it currently. 2521 if (!ParentGroup.IsDeleted)
2136 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) 2522 return ParentGroup.GetAxisRotation(axis);
2137 return STATUS_ROTATE_X;
2138 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2139 return STATUS_ROTATE_Y;
2140 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2141 return STATUS_ROTATE_Z;
2142 2523
2143 return 0; 2524 return 0;
2144 } 2525 }
@@ -2164,42 +2545,63 @@ namespace OpenSim.Region.Framework.Scenes
2164 2545
2165 public Vector3 GetGeometricCenter() 2546 public Vector3 GetGeometricCenter()
2166 { 2547 {
2548 // this is not real geometric center but a average of positions relative to root prim acording to
2549 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2550 // ignoring tortured prims details since sl also seems to ignore
2551 // so no real use in doing it on physics
2552 if (ParentGroup.IsDeleted)
2553 return new Vector3(0, 0, 0);
2554
2555 return ParentGroup.GetGeometricCenter();
2556 }
2557
2558 public float GetMass()
2559 {
2167 PhysicsActor pa = PhysActor; 2560 PhysicsActor pa = PhysActor;
2168 2561
2169 if (pa != null) 2562 if (pa != null)
2170 return pa.GeometricCenter; 2563 return pa.Mass;
2171 else 2564 else
2172 return Vector3.Zero; 2565 return 0;
2173 } 2566 }
2174 2567
2175 public Vector3 GetCenterOfMass() 2568 public Vector3 GetCenterOfMass()
2176 { 2569 {
2570 if (ParentGroup.RootPart == this)
2571 {
2572 if (ParentGroup.IsDeleted)
2573 return AbsolutePosition;
2574 return ParentGroup.GetCenterOfMass();
2575 }
2576
2177 PhysicsActor pa = PhysActor; 2577 PhysicsActor pa = PhysActor;
2178 2578
2179 if (pa != null) 2579 if (pa != null)
2180 return pa.CenterOfMass; 2580 {
2581 Vector3 tmp = pa.CenterOfMass;
2582 return tmp;
2583 }
2181 else 2584 else
2182 return Vector3.Zero; 2585 return AbsolutePosition;
2183 } 2586 }
2184 2587
2185 public float GetMass() 2588 public Vector3 GetPartCenterOfMass()
2186 { 2589 {
2187 PhysicsActor pa = PhysActor; 2590 PhysicsActor pa = PhysActor;
2188 2591
2189 if (pa != null) 2592 if (pa != null)
2190 return pa.Mass; 2593 {
2594 Vector3 tmp = pa.CenterOfMass;
2595 return tmp;
2596 }
2191 else 2597 else
2192 return 0; 2598 return AbsolutePosition;
2193 } 2599 }
2194 2600
2601
2195 public Vector3 GetForce() 2602 public Vector3 GetForce()
2196 { 2603 {
2197 PhysicsActor pa = PhysActor; 2604 return Force;
2198
2199 if (pa != null)
2200 return pa.Force;
2201 else
2202 return Vector3.Zero;
2203 } 2605 }
2204 2606
2205 /// <summary> 2607 /// <summary>
@@ -2314,6 +2716,7 @@ namespace OpenSim.Region.Framework.Scenes
2314 detobj.velVector = obj.Velocity; 2716 detobj.velVector = obj.Velocity;
2315 detobj.colliderType = 0; 2717 detobj.colliderType = 0;
2316 detobj.groupUUID = obj.GroupID; 2718 detobj.groupUUID = obj.GroupID;
2719 detobj.linkNumber = LinkNum; // pass my link number
2317 2720
2318 return detobj; 2721 return detobj;
2319 } 2722 }
@@ -2329,6 +2732,7 @@ namespace OpenSim.Region.Framework.Scenes
2329 detobj.velVector = av.Velocity; 2732 detobj.velVector = av.Velocity;
2330 detobj.colliderType = 0; 2733 detobj.colliderType = 0;
2331 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2734 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2735 detobj.linkNumber = LinkNum; // pass my link number
2332 2736
2333 return detobj; 2737 return detobj;
2334 } 2738 }
@@ -2344,6 +2748,7 @@ namespace OpenSim.Region.Framework.Scenes
2344 detobj.velVector = Vector3.Zero; 2748 detobj.velVector = Vector3.Zero;
2345 detobj.colliderType = 0; 2749 detobj.colliderType = 0;
2346 detobj.groupUUID = UUID.Zero; 2750 detobj.groupUUID = UUID.Zero;
2751 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2347 2752
2348 return detobj; 2753 return detobj;
2349 } 2754 }
@@ -2393,7 +2798,7 @@ namespace OpenSim.Region.Framework.Scenes
2393 CollidingMessage = CreateColliderArgs(this, colliders); 2798 CollidingMessage = CreateColliderArgs(this, colliders);
2394 2799
2395 if (CollidingMessage.Colliders.Count > 0) 2800 if (CollidingMessage.Colliders.Count > 0)
2396 DoNotify(notify, LocalId, CollidingMessage); 2801 notify(LocalId, CollidingMessage);
2397 2802
2398 if (PassCollisions) 2803 if (PassCollisions)
2399 sendToRoot = true; 2804 sendToRoot = true;
@@ -2407,48 +2812,32 @@ namespace OpenSim.Region.Framework.Scenes
2407 { 2812 {
2408 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2813 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2409 if (CollidingMessage.Colliders.Count > 0) 2814 if (CollidingMessage.Colliders.Count > 0)
2410 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); 2815 notify(ParentGroup.RootPart.LocalId, CollidingMessage);
2411 } 2816 }
2412 } 2817 }
2413 } 2818 }
2414 2819
2415 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2820 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2416 { 2821 {
2417 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2822 bool sendToRoot = true;
2418 {
2419 ColliderArgs LandCollidingMessage = new ColliderArgs();
2420 List<DetectedObject> colliding = new List<DetectedObject>();
2421
2422 colliding.Add(CreateDetObjectForGround());
2423 LandCollidingMessage.Colliders = colliding;
2424 2823
2425 DoNotify(notify, LocalId, LandCollidingMessage); 2824 ColliderArgs LandCollidingMessage = new ColliderArgs();
2426 } 2825 List<DetectedObject> colliding = new List<DetectedObject>();
2427 } 2826
2827 colliding.Add(CreateDetObjectForGround());
2828 LandCollidingMessage.Colliders = colliding;
2428 2829
2429 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) 2830 if (Inventory.ContainsScripts())
2430 {
2431 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2432 { 2831 {
2433 // For those learning C#, FireAndForget takes a function, an object to pass 2832 if (!PassCollisions)
2434 // to that function and an ID string. The "oo => {}" construct is a lambda expression 2833 sendToRoot = false;
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 } 2834 }
2449 else 2835 if ((ScriptEvents & ev) != 0)
2836 notify(LocalId, LandCollidingMessage);
2837
2838 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2450 { 2839 {
2451 notify(id, collargs); 2840 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2452 } 2841 }
2453 } 2842 }
2454 2843
@@ -2464,44 +2853,81 @@ namespace OpenSim.Region.Framework.Scenes
2464 List<uint> endedColliders = new List<uint>(); 2853 List<uint> endedColliders = new List<uint>();
2465 List<uint> startedColliders = new List<uint>(); 2854 List<uint> startedColliders = new List<uint>();
2466 2855
2467 // calculate things that started colliding this time 2856 if (collissionswith.Count == 0)
2468 // and build up list of colliders this time
2469 foreach (uint localid in collissionswith.Keys)
2470 { 2857 {
2471 thisHitColliders.Add(localid); 2858 if (m_lastColliders.Count == 0)
2472 if (!m_lastColliders.Contains(localid)) 2859 return; // nothing to do
2473 startedColliders.Add(localid);
2474 }
2475 2860
2476 // calculate things that ended colliding 2861 foreach (uint localID in m_lastColliders)
2477 foreach (uint localID in m_lastColliders) 2862 {
2478 {
2479 if (!thisHitColliders.Contains(localID))
2480 endedColliders.Add(localID); 2863 endedColliders.Add(localID);
2864 }
2865 m_lastColliders.Clear();
2481 } 2866 }
2482 2867
2483 //add the items that started colliding this time to the last colliders list. 2868 else
2484 foreach (uint localID in startedColliders) 2869 {
2485 m_lastColliders.Add(localID); 2870 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2486 2871
2487 // remove things that ended colliding from the last colliders list 2872 // calculate things that started colliding this time
2488 foreach (uint localID in endedColliders) 2873 // and build up list of colliders this time
2489 m_lastColliders.Remove(localID); 2874 if (!VolumeDetectActive && CollisionSoundType >= 0)
2875 {
2876 CollisionForSoundInfo soundinfo;
2877 ContactPoint curcontact;
2490 2878
2491 // play the sound. 2879 foreach (uint id in collissionswith.Keys)
2492 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2880 {
2493 { 2881 thisHitColliders.Add(id);
2494 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2882 if (!m_lastColliders.Contains(id))
2495 if (soundModule != null) 2883 {
2884 startedColliders.Add(id);
2885
2886 curcontact = collissionswith[id];
2887 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2888 {
2889 soundinfo = new CollisionForSoundInfo();
2890 soundinfo.colliderID = id;
2891 soundinfo.position = curcontact.Position;
2892 soundinfo.relativeVel = curcontact.RelativeSpeed;
2893 soundinfolist.Add(soundinfo);
2894 }
2895 }
2896 }
2897 }
2898 else
2899 {
2900 foreach (uint id in collissionswith.Keys)
2901 {
2902 thisHitColliders.Add(id);
2903 if (!m_lastColliders.Contains(id))
2904 startedColliders.Add(id);
2905 }
2906 }
2907
2908 // calculate things that ended colliding
2909 foreach (uint localID in m_lastColliders)
2496 { 2910 {
2497 soundModule.SendSound(UUID, CollisionSound, 2911 if (!thisHitColliders.Contains(localID))
2498 CollisionSoundVolume, true, 0, 0, false, 2912 endedColliders.Add(localID);
2499 false);
2500 } 2913 }
2914
2915 //add the items that started colliding this time to the last colliders list.
2916 foreach (uint localID in startedColliders)
2917 m_lastColliders.Add(localID);
2918
2919 // remove things that ended colliding from the last colliders list
2920 foreach (uint localID in endedColliders)
2921 m_lastColliders.Remove(localID);
2922
2923 // play sounds.
2924 if (soundinfolist.Count > 0)
2925 CollisionSounds.PartCollisionSound(this, soundinfolist);
2501 } 2926 }
2502 2927
2503 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2928 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2504 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2929 if (!VolumeDetectActive)
2930 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2505 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2931 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2506 2932
2507 if (startedColliders.Contains(0)) 2933 if (startedColliders.Contains(0))
@@ -2512,6 +2938,35 @@ namespace OpenSim.Region.Framework.Scenes
2512 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2938 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2513 } 2939 }
2514 2940
2941 // The Collision sounds code calls this
2942 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2943 {
2944 if (soundID == UUID.Zero)
2945 return;
2946
2947 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2948 if (soundModule == null)
2949 return;
2950
2951 if (volume > 1)
2952 volume = 1;
2953 if (volume < 0)
2954 volume = 0;
2955
2956 int now = Util.EnvironmentTickCount();
2957 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2958 return;
2959
2960 LastColSoundSentTime = now;
2961
2962 UUID ownerID = OwnerID;
2963 UUID objectID = ParentGroup.RootPart.UUID;
2964 UUID parentID = ParentGroup.UUID;
2965 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2966
2967 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2968 }
2969
2515 public void PhysicsOutOfBounds(Vector3 pos) 2970 public void PhysicsOutOfBounds(Vector3 pos)
2516 { 2971 {
2517 // Note: This is only being called on the root prim at this time. 2972 // Note: This is only being called on the root prim at this time.
@@ -2539,7 +2994,7 @@ namespace OpenSim.Region.Framework.Scenes
2539 } 2994 }
2540 //ParentGroup.RootPart.m_groupPosition = newpos; 2995 //ParentGroup.RootPart.m_groupPosition = newpos;
2541 } 2996 }
2542 2997/* ubit: there are no flexible links
2543 if (pa != null && ParentID != 0 && ParentGroup != null) 2998 if (pa != null && ParentID != 0 && ParentGroup != null)
2544 { 2999 {
2545 // Special case where a child object is requesting property updates. 3000 // Special case where a child object is requesting property updates.
@@ -2559,7 +3014,7 @@ namespace OpenSim.Region.Framework.Scenes
2559 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", 3014 // 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); 3015 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2561 } 3016 }
2562 3017*/
2563 ScheduleTerseUpdate(); 3018 ScheduleTerseUpdate();
2564 } 3019 }
2565 3020
@@ -2619,18 +3074,17 @@ namespace OpenSim.Region.Framework.Scenes
2619 3074
2620 if (ParentGroup.Scene != null) 3075 if (ParentGroup.Scene != null)
2621 { 3076 {
2622 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); 3077 float minsize = ParentGroup.Scene.m_minNonphys;
2623 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); 3078 float maxsize = ParentGroup.Scene.m_maxNonphys;
2624 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2625
2626 if (pa != null && pa.IsPhysical) 3079 if (pa != null && pa.IsPhysical)
2627 { 3080 {
2628 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); 3081 minsize = ParentGroup.Scene.m_minPhys;
2629 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); 3082 maxsize = ParentGroup.Scene.m_maxPhys;
2630 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); 3083 }
2631 } 3084 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3085 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3086 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
2632 } 3087 }
2633
2634// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 3088// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2635 3089
2636 Scale = scale; 3090 Scale = scale;
@@ -2812,7 +3266,19 @@ namespace OpenSim.Region.Framework.Scenes
2812 3266
2813// m_log.DebugFormat( 3267// m_log.DebugFormat(
2814// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3268// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
2815 3269
3270
3271 if (ParentGroup.IsAttachment)
3272 {
3273 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3274 if (sp != null)
3275 {
3276 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3277 }
3278 }
3279
3280/* this does nothing
3281SendFullUpdateToClient(remoteClient, Position) ignores position parameter
2816 if (IsRoot) 3282 if (IsRoot)
2817 { 3283 {
2818 if (ParentGroup.IsAttachment) 3284 if (ParentGroup.IsAttachment)
@@ -2824,6 +3290,7 @@ namespace OpenSim.Region.Framework.Scenes
2824 SendFullUpdateToClient(remoteClient, AbsolutePosition); 3290 SendFullUpdateToClient(remoteClient, AbsolutePosition);
2825 } 3291 }
2826 } 3292 }
3293*/
2827 else 3294 else
2828 { 3295 {
2829 SendFullUpdateToClient(remoteClient); 3296 SendFullUpdateToClient(remoteClient);
@@ -2833,17 +3300,55 @@ namespace OpenSim.Region.Framework.Scenes
2833 /// <summary> 3300 /// <summary>
2834 /// Send a full update for this part to all clients. 3301 /// Send a full update for this part to all clients.
2835 /// </summary> 3302 /// </summary>
2836 public void SendFullUpdateToAllClients() 3303 public void SendFullUpdateToAllClientsInternal()
2837 { 3304 {
2838 if (ParentGroup == null) 3305 if (ParentGroup == null)
2839 return; 3306 return;
2840 3307
3308 // Update the "last" values
3309 m_lastPosition = OffsetPosition;
3310 m_lastRotation = RotationOffset;
3311 m_lastVelocity = Velocity;
3312 m_lastAcceleration = Acceleration;
3313 m_lastAngularVelocity = AngularVelocity;
3314 m_lastUpdateSentTime = Environment.TickCount;
3315
2841 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3316 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2842 { 3317 {
2843 SendFullUpdate(avatar.ControllingClient); 3318 SendFullUpdate(avatar.ControllingClient);
2844 }); 3319 });
2845 } 3320 }
2846 3321
3322 public void SendFullUpdateToAllClients()
3323 {
3324 if (ParentGroup == null)
3325 return;
3326
3327 // Update the "last" values
3328 m_lastPosition = OffsetPosition;
3329 m_lastRotation = RotationOffset;
3330 m_lastVelocity = Velocity;
3331 m_lastAcceleration = Acceleration;
3332 m_lastAngularVelocity = AngularVelocity;
3333 m_lastUpdateSentTime = Environment.TickCount;
3334
3335 if (ParentGroup.IsAttachment)
3336 {
3337 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3338 if (sp != null)
3339 {
3340 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3341 }
3342 }
3343 else
3344 {
3345 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3346 {
3347 SendFullUpdate(avatar.ControllingClient);
3348 });
3349 }
3350 }
3351
2847 /// <summary> 3352 /// <summary>
2848 /// Sends a full update to the client 3353 /// Sends a full update to the client
2849 /// </summary> 3354 /// </summary>
@@ -2864,9 +3369,9 @@ namespace OpenSim.Region.Framework.Scenes
2864 return; 3369 return;
2865 3370
2866 // Suppress full updates during attachment editing 3371 // Suppress full updates during attachment editing
2867 // 3372 // sl Does send them
2868 if (ParentGroup.IsSelected && ParentGroup.IsAttachment) 3373 // if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
2869 return; 3374 // return;
2870 3375
2871 if (ParentGroup.IsDeleted) 3376 if (ParentGroup.IsDeleted)
2872 return; 3377 return;
@@ -2896,8 +3401,8 @@ namespace OpenSim.Region.Framework.Scenes
2896 { 3401 {
2897 const float ROTATION_TOLERANCE = 0.01f; 3402 const float ROTATION_TOLERANCE = 0.01f;
2898 const float VELOCITY_TOLERANCE = 0.001f; 3403 const float VELOCITY_TOLERANCE = 0.001f;
2899 const float POSITION_TOLERANCE = 0.05f; 3404 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2900 const int TIME_MS_TOLERANCE = 3000; 3405 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2901 3406
2902 switch (UpdateFlag) 3407 switch (UpdateFlag)
2903 { 3408 {
@@ -2911,40 +3416,74 @@ namespace OpenSim.Region.Framework.Scenes
2911 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3416 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2912 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3417 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2913 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3418 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2914 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3419 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2915 { 3420 {
2916 SendTerseUpdateToAllClients(); 3421 SendTerseUpdateToAllClientsInternal();
2917
2918 // Update the "last" values
2919 m_lastPosition = OffsetPosition;
2920 m_lastRotation = RotationOffset;
2921 m_lastVelocity = Velocity;
2922 m_lastAcceleration = Acceleration;
2923 m_lastAngularVelocity = AngularVelocity;
2924 m_lastTerseSent = Environment.TickCount;
2925 } 3422 }
2926 break; 3423 break;
2927 } 3424 }
2928 case UpdateRequired.FULL: 3425 case UpdateRequired.FULL:
2929 { 3426 {
2930 ClearUpdateSchedule(); 3427 ClearUpdateSchedule();
2931 SendFullUpdateToAllClients(); 3428 SendFullUpdateToAllClientsInternal();
2932 break; 3429 break;
2933 } 3430 }
2934 } 3431 }
2935 } 3432 }
2936 3433
3434
2937 /// <summary> 3435 /// <summary>
2938 /// Send a terse update to all clients 3436 /// Send a terse update to all clients
2939 /// </summary> 3437 /// </summary>
2940 public void SendTerseUpdateToAllClients() 3438 public void SendTerseUpdateToAllClientsInternal()
2941 { 3439 {
3440 if (ParentGroup == null || ParentGroup.Scene == null)
3441 return;
3442
3443 // Update the "last" values
3444 m_lastPosition = OffsetPosition;
3445 m_lastRotation = RotationOffset;
3446 m_lastVelocity = Velocity;
3447 m_lastAcceleration = Acceleration;
3448 m_lastAngularVelocity = AngularVelocity;
3449 m_lastUpdateSentTime = Environment.TickCount;
3450
2942 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3451 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2943 { 3452 {
2944 SendTerseUpdateToClient(client); 3453 SendTerseUpdateToClient(client);
2945 }); 3454 });
2946 } 3455 }
2947 3456
3457 public void SendTerseUpdateToAllClients()
3458 {
3459 if (ParentGroup == null || ParentGroup.Scene == null)
3460 return;
3461
3462 // Update the "last" values
3463 m_lastPosition = OffsetPosition;
3464 m_lastRotation = RotationOffset;
3465 m_lastVelocity = Velocity;
3466 m_lastAcceleration = Acceleration;
3467 m_lastAngularVelocity = AngularVelocity;
3468 m_lastUpdateSentTime = Environment.TickCount;
3469
3470 if (ParentGroup.IsAttachment)
3471 {
3472 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3473 if (sp != null)
3474 {
3475 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3476 }
3477 }
3478 else
3479 {
3480 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3481 {
3482 SendTerseUpdateToClient(client);
3483 });
3484 }
3485 }
3486
2948 public void SetAxisRotation(int axis, int rotate) 3487 public void SetAxisRotation(int axis, int rotate)
2949 { 3488 {
2950 ParentGroup.SetAxisRotation(axis, rotate); 3489 ParentGroup.SetAxisRotation(axis, rotate);
@@ -2962,10 +3501,13 @@ namespace OpenSim.Region.Framework.Scenes
2962 3501
2963 public void SetBuoyancy(float fvalue) 3502 public void SetBuoyancy(float fvalue)
2964 { 3503 {
2965 PhysicsActor pa = PhysActor; 3504 Buoyancy = fvalue;
2966 3505/*
2967 if (pa != null) 3506 if (PhysActor != null)
2968 pa.Buoyancy = fvalue; 3507 {
3508 PhysActor.Buoyancy = fvalue;
3509 }
3510 */
2969 } 3511 }
2970 3512
2971 public void SetDieAtEdge(bool p) 3513 public void SetDieAtEdge(bool p)
@@ -2981,47 +3523,111 @@ namespace OpenSim.Region.Framework.Scenes
2981 PhysicsActor pa = PhysActor; 3523 PhysicsActor pa = PhysActor;
2982 3524
2983 if (pa != null) 3525 if (pa != null)
2984 pa.FloatOnWater = floatYN == 1; 3526 pa.FloatOnWater = (floatYN == 1);
2985 } 3527 }
2986 3528
2987 public void SetForce(Vector3 force) 3529 public void SetForce(Vector3 force)
2988 { 3530 {
2989 PhysicsActor pa = PhysActor; 3531 Force = force;
3532 }
2990 3533
2991 if (pa != null) 3534 public SOPVehicle VehicleParams
2992 pa.Force = force; 3535 {
3536 get
3537 {
3538 return m_vehicleParams;
3539 }
3540 set
3541 {
3542 m_vehicleParams = value;
3543 }
3544 }
3545
3546
3547 public int VehicleType
3548 {
3549 get
3550 {
3551 if (m_vehicleParams == null)
3552 return (int)Vehicle.TYPE_NONE;
3553 else
3554 return (int)m_vehicleParams.Type;
3555 }
3556 set
3557 {
3558 SetVehicleType(value);
3559 }
2993 } 3560 }
2994 3561
2995 public void SetVehicleType(int type) 3562 public void SetVehicleType(int type)
2996 { 3563 {
2997 PhysicsActor pa = PhysActor; 3564 m_vehicleParams = null;
3565
3566 if (type == (int)Vehicle.TYPE_NONE)
3567 {
3568 if (_parentID ==0 && PhysActor != null)
3569 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3570 return;
3571 }
3572 m_vehicleParams = new SOPVehicle();
3573 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3574 {
3575 if (_parentID ==0 && PhysActor != null)
3576 PhysActor.VehicleType = type;
3577 return;
3578 }
3579 }
2998 3580
2999 if (pa != null) 3581 public void SetVehicleFlags(int param, bool remove)
3000 pa.VehicleType = type; 3582 {
3583 if (m_vehicleParams == null)
3584 return;
3585
3586 m_vehicleParams.ProcessVehicleFlags(param, remove);
3587
3588 if (_parentID ==0 && PhysActor != null)
3589 {
3590 PhysActor.VehicleFlags(param, remove);
3591 }
3001 } 3592 }
3002 3593
3003 public void SetVehicleFloatParam(int param, float value) 3594 public void SetVehicleFloatParam(int param, float value)
3004 { 3595 {
3005 PhysicsActor pa = PhysActor; 3596 if (m_vehicleParams == null)
3597 return;
3006 3598
3007 if (pa != null) 3599 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
3008 pa.VehicleFloatParam(param, value); 3600
3601 if (_parentID == 0 && PhysActor != null)
3602 {
3603 PhysActor.VehicleFloatParam(param, value);
3604 }
3009 } 3605 }
3010 3606
3011 public void SetVehicleVectorParam(int param, Vector3 value) 3607 public void SetVehicleVectorParam(int param, Vector3 value)
3012 { 3608 {
3013 PhysicsActor pa = PhysActor; 3609 if (m_vehicleParams == null)
3610 return;
3014 3611
3015 if (pa != null) 3612 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
3016 pa.VehicleVectorParam(param, value); 3613
3614 if (_parentID == 0 && PhysActor != null)
3615 {
3616 PhysActor.VehicleVectorParam(param, value);
3617 }
3017 } 3618 }
3018 3619
3019 public void SetVehicleRotationParam(int param, Quaternion rotation) 3620 public void SetVehicleRotationParam(int param, Quaternion rotation)
3020 { 3621 {
3021 PhysicsActor pa = PhysActor; 3622 if (m_vehicleParams == null)
3623 return;
3022 3624
3023 if (pa != null) 3625 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
3024 pa.VehicleRotationParam(param, rotation); 3626
3627 if (_parentID == 0 && PhysActor != null)
3628 {
3629 PhysActor.VehicleRotationParam(param, rotation);
3630 }
3025 } 3631 }
3026 3632
3027 /// <summary> 3633 /// <summary>
@@ -3222,14 +3828,6 @@ namespace OpenSim.Region.Framework.Scenes
3222 hasProfileCut = hasDimple; // is it the same thing? 3828 hasProfileCut = hasDimple; // is it the same thing?
3223 } 3829 }
3224 3830
3225 public void SetVehicleFlags(int param, bool remove)
3226 {
3227 PhysicsActor pa = PhysActor;
3228
3229 if (pa != null)
3230 pa.VehicleFlags(param, remove);
3231 }
3232
3233 public void SetGroup(UUID groupID, IClientAPI client) 3831 public void SetGroup(UUID groupID, IClientAPI client)
3234 { 3832 {
3235 // Scene.AddNewPrims() calls with client == null so can't use this. 3833 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3238,8 +3836,8 @@ namespace OpenSim.Region.Framework.Scenes
3238// Name, groupID, OwnerID); 3836// Name, groupID, OwnerID);
3239 3837
3240 GroupID = groupID; 3838 GroupID = groupID;
3241 if (client != null) 3839// if (client != null)
3242 SendPropertiesToClient(client); 3840// SendPropertiesToClient(client);
3243 UpdateFlag = UpdateRequired.FULL; 3841 UpdateFlag = UpdateRequired.FULL;
3244 } 3842 }
3245 3843
@@ -3263,7 +3861,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 3861
3264 if (pa != null) 3862 if (pa != null)
3265 { 3863 {
3266 pa.LockAngularMotion(RotationAxis); 3864 pa.LockAngularMotion(RotationAxisLocks);
3267 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 3865 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
3268 } 3866 }
3269 } 3867 }
@@ -3334,67 +3932,16 @@ namespace OpenSim.Region.Framework.Scenes
3334 ParentGroup.StopMoveToTarget(); 3932 ParentGroup.StopMoveToTarget();
3335 } 3933 }
3336 3934
3337 public void StoreUndoState() 3935 public void StoreUndoState(ObjectChangeType change)
3338 { 3936 {
3339 StoreUndoState(false); 3937 if (m_UndoRedo == null)
3340 } 3938 m_UndoRedo = new UndoRedoState(5);
3341 3939
3342 public void StoreUndoState(bool forGroup) 3940 lock (m_UndoRedo)
3343 {
3344 if (ParentGroup == null || ParentGroup.Scene == null)
3345 return;
3346
3347 if (Undoing)
3348 {
3349// m_log.DebugFormat(
3350// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3351 return;
3352 }
3353
3354 if (IgnoreUndoUpdate)
3355 {
3356// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3357 return;
3358 }
3359
3360 lock (m_undo)
3361 { 3941 {
3362 if (m_undo.Count > 0) 3942 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3363 { 3943 {
3364 UndoState last = m_undo[m_undo.Count - 1]; 3944 m_UndoRedo.StoreUndo(this, change);
3365 if (last != null)
3366 {
3367 // TODO: May need to fix for group comparison
3368 if (last.Compare(this))
3369 {
3370// m_log.DebugFormat(
3371// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3372// Name, LocalId, m_undo.Count);
3373
3374 return;
3375 }
3376 }
3377 }
3378
3379// m_log.DebugFormat(
3380// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3381// Name, LocalId, forGroup, m_undo.Count);
3382
3383 if (ParentGroup.Scene.MaxUndoCount > 0)
3384 {
3385 UndoState nUndo = new UndoState(this, forGroup);
3386
3387 m_undo.Add(nUndo);
3388
3389 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3390 m_undo.RemoveAt(0);
3391
3392 if (m_redo.Count > 0)
3393 m_redo.Clear();
3394
3395// m_log.DebugFormat(
3396// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3397// Name, LocalId, forGroup, m_undo.Count);
3398 } 3945 }
3399 } 3946 }
3400 } 3947 }
@@ -3406,88 +3953,46 @@ namespace OpenSim.Region.Framework.Scenes
3406 { 3953 {
3407 get 3954 get
3408 { 3955 {
3409 lock (m_undo) 3956 if (m_UndoRedo == null)
3410 return m_undo.Count; 3957 return 0;
3958 return m_UndoRedo.Count;
3411 } 3959 }
3412 } 3960 }
3413 3961
3414 public void Undo() 3962 public void Undo()
3415 { 3963 {
3416 lock (m_undo) 3964 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3417 { 3965 return;
3418// m_log.DebugFormat(
3419// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3420// Name, LocalId, m_undo.Count);
3421
3422 if (m_undo.Count > 0)
3423 {
3424 UndoState goback = m_undo[m_undo.Count - 1];
3425 m_undo.RemoveAt(m_undo.Count - 1);
3426
3427 UndoState nUndo = null;
3428
3429 if (ParentGroup.Scene.MaxUndoCount > 0)
3430 {
3431 nUndo = new UndoState(this, goback.ForGroup);
3432 }
3433
3434 goback.PlaybackState(this);
3435
3436 if (nUndo != null)
3437 {
3438 m_redo.Add(nUndo);
3439
3440 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3441 m_redo.RemoveAt(0);
3442 }
3443 }
3444 3966
3445// m_log.DebugFormat( 3967 lock (m_UndoRedo)
3446// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3968 {
3447// Name, LocalId, m_undo.Count); 3969 Undoing = true;
3970 m_UndoRedo.Undo(this);
3971 Undoing = false;
3448 } 3972 }
3449 } 3973 }
3450 3974
3451 public void Redo() 3975 public void Redo()
3452 { 3976 {
3453 lock (m_undo) 3977 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3454 { 3978 return;
3455// m_log.DebugFormat(
3456// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3457// Name, LocalId, m_redo.Count);
3458
3459 if (m_redo.Count > 0)
3460 {
3461 UndoState gofwd = m_redo[m_redo.Count - 1];
3462 m_redo.RemoveAt(m_redo.Count - 1);
3463
3464 if (ParentGroup.Scene.MaxUndoCount > 0)
3465 {
3466 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3467
3468 m_undo.Add(nUndo);
3469
3470 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3471 m_undo.RemoveAt(0);
3472 }
3473
3474 gofwd.PlayfwdState(this);
3475 3979
3476// m_log.DebugFormat( 3980 lock (m_UndoRedo)
3477// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3981 {
3478// Name, LocalId, m_redo.Count); 3982 Undoing = true;
3479 } 3983 m_UndoRedo.Redo(this);
3984 Undoing = false;
3480 } 3985 }
3481 } 3986 }
3482 3987
3483 public void ClearUndoState() 3988 public void ClearUndoState()
3484 { 3989 {
3485// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3990 if (m_UndoRedo == null || Undoing)
3991 return;
3486 3992
3487 lock (m_undo) 3993 lock (m_UndoRedo)
3488 { 3994 {
3489 m_undo.Clear(); 3995 m_UndoRedo.Clear();
3490 m_redo.Clear();
3491 } 3996 }
3492 } 3997 }
3493 3998
@@ -4039,7 +4544,7 @@ namespace OpenSim.Region.Framework.Scenes
4039 if (god) 4544 if (god)
4040 { 4545 {
4041 BaseMask = ApplyMask(BaseMask, set, mask); 4546 BaseMask = ApplyMask(BaseMask, set, mask);
4042 Inventory.ApplyGodPermissions(_baseMask); 4547 Inventory.ApplyGodPermissions(BaseMask);
4043 } 4548 }
4044 4549
4045 break; 4550 break;
@@ -4070,7 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
4070 } 4575 }
4071 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4576 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
4072 baseMask; 4577 baseMask;
4073 // Prevent the client from creating no mod, no copy 4578 // Prevent the client from creating no copy, no transfer
4074 // objects 4579 // objects
4075 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4580 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
4076 NextOwnerMask |= (uint)PermissionMask.Transfer; 4581 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -4086,22 +4591,20 @@ namespace OpenSim.Region.Framework.Scenes
4086 4591
4087 public void ClonePermissions(SceneObjectPart source) 4592 public void ClonePermissions(SceneObjectPart source)
4088 { 4593 {
4089 bool update = false; 4594 uint prevOwnerMask = OwnerMask;
4595 uint prevGroupMask = GroupMask;
4596 uint prevEveryoneMask = EveryoneMask;
4597 uint prevNextOwnerMask = NextOwnerMask;
4090 4598
4091 if (BaseMask != source.BaseMask || 4599 OwnerMask = source.OwnerMask & BaseMask;
4092 OwnerMask != source.OwnerMask || 4600 GroupMask = source.GroupMask & BaseMask;
4093 GroupMask != source.GroupMask || 4601 EveryoneMask = source.EveryoneMask & BaseMask;
4094 EveryoneMask != source.EveryoneMask || 4602 NextOwnerMask = source.NextOwnerMask & BaseMask;
4095 NextOwnerMask != source.NextOwnerMask)
4096 update = true;
4097 4603
4098 BaseMask = source.BaseMask; 4604 if (OwnerMask != prevOwnerMask ||
4099 OwnerMask = source.OwnerMask; 4605 GroupMask != prevGroupMask ||
4100 GroupMask = source.GroupMask; 4606 EveryoneMask != prevEveryoneMask ||
4101 EveryoneMask = source.EveryoneMask; 4607 NextOwnerMask != prevNextOwnerMask)
4102 NextOwnerMask = source.NextOwnerMask;
4103
4104 if (update)
4105 SendFullUpdateToAllClients(); 4608 SendFullUpdateToAllClients();
4106 } 4609 }
4107 4610
@@ -4152,6 +4655,7 @@ namespace OpenSim.Region.Framework.Scenes
4152 } 4655 }
4153 } 4656 }
4154 4657
4658
4155 public void UpdateExtraPhysics(ExtraPhysicsData physdata) 4659 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4156 { 4660 {
4157 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4661 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
@@ -4179,7 +4683,7 @@ namespace OpenSim.Region.Framework.Scenes
4179 /// <param name="SetTemporary"></param> 4683 /// <param name="SetTemporary"></param>
4180 /// <param name="SetPhantom"></param> 4684 /// <param name="SetPhantom"></param>
4181 /// <param name="SetVD"></param> 4685 /// <param name="SetVD"></param>
4182 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4686 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4183 { 4687 {
4184 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4688 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4185 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4689 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4189,99 +4693,104 @@ namespace OpenSim.Region.Framework.Scenes
4189 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4693 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4190 return; 4694 return;
4191 4695
4192 PhysicsActor pa = PhysActor; 4696 VolumeDetectActive = SetVD;
4193
4194 // Special cases for VD. VD can only be called from a script
4195 // and can't be combined with changes to other states. So we can rely
4196 // that...
4197 // ... if VD is changed, all others are not.
4198 // ... if one of the others is changed, VD is not.
4199 if (SetVD) // VD is active, special logic applies
4200 {
4201 // State machine logic for VolumeDetect
4202 // More logic below
4203 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4204 4697
4205 if (phanReset) // Phantom changes from on to off switch VD off too 4698 // volume detector implies phantom
4206 { 4699 if (VolumeDetectActive)
4207 SetVD = false; // Switch it of for the course of this routine
4208 VolumeDetectActive = false; // and also permanently
4209
4210 if (pa != null)
4211 pa.SetVolumeDetect(0); // Let physics know about it too
4212 }
4213 else
4214 {
4215 // If volumedetect is active we don't want phantom to be applied.
4216 // If this is a new call to VD out of the state "phantom"
4217 // this will also cause the prim to be visible to physics
4218 SetPhantom = false;
4219 }
4220 }
4221
4222 if (UsePhysics && IsJoint())
4223 {
4224 SetPhantom = true; 4700 SetPhantom = true;
4225 }
4226 4701
4227 if (UsePhysics) 4702 if (UsePhysics)
4228 {
4229 AddFlag(PrimFlags.Physics); 4703 AddFlag(PrimFlags.Physics);
4230 if (!wasUsingPhysics)
4231 {
4232 DoPhysicsPropertyUpdate(UsePhysics, false);
4233 }
4234 }
4235 else 4704 else
4236 {
4237 RemFlag(PrimFlags.Physics); 4705 RemFlag(PrimFlags.Physics);
4238 if (wasUsingPhysics)
4239 {
4240 DoPhysicsPropertyUpdate(UsePhysics, false);
4241 }
4242 }
4243 4706
4244 if (SetPhantom 4707 if (SetPhantom)
4245 || ParentGroup.IsAttachmentCheckFull()
4246 || PhysicsShapeType == (byte)PhysShapeType.none
4247 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4248 {
4249 AddFlag(PrimFlags.Phantom); 4708 AddFlag(PrimFlags.Phantom);
4709 else
4710 RemFlag(PrimFlags.Phantom);
4250 4711
4251 if (PhysActor != null) 4712 if (SetTemporary)
4713 AddFlag(PrimFlags.TemporaryOnRez);
4714 else
4715 RemFlag(PrimFlags.TemporaryOnRez);
4716
4717
4718 if (ParentGroup.Scene == null)
4719 return;
4720
4721 PhysicsActor pa = PhysActor;
4722
4723 if (pa != null && building && pa.Building != building)
4724 pa.Building = building;
4725
4726 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4727 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4728 {
4729 if (pa != null)
4252 { 4730 {
4731 if(wasUsingPhysics)
4732 ParentGroup.Scene.RemovePhysicalPrim(1);
4253 RemoveFromPhysics(); 4733 RemoveFromPhysics();
4254 pa = null;
4255 } 4734 }
4735
4736 Velocity = new Vector3(0, 0, 0);
4737 Acceleration = new Vector3(0, 0, 0);
4738 if (ParentGroup.RootPart == this)
4739 AngularVelocity = new Vector3(0, 0, 0);
4256 } 4740 }
4257 else // Not phantom 4741
4742 else
4258 { 4743 {
4259 RemFlag(PrimFlags.Phantom); 4744 if (ParentGroup.Scene.CollidablePrims)
4260
4261 if (ParentGroup.Scene == null)
4262 return;
4263
4264 if (ParentGroup.Scene.CollidablePrims && pa == null)
4265 { 4745 {
4266 AddToPhysics(UsePhysics, SetPhantom, false); 4746 if (pa == null)
4267 pa = PhysActor; 4747 {
4268 4748 AddToPhysics(UsePhysics, SetPhantom, building, false);
4269 if (pa != null) 4749 pa = PhysActor;
4750/*
4751 if (pa != null)
4752 {
4753 if (
4754// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4755// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4756// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4757// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4758// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4759// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4760 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4761 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4762 (CollisionSound != UUID.Zero)
4763 )
4764 {
4765 pa.OnCollisionUpdate += PhysicsCollision;
4766 pa.SubscribeEvents(1000);
4767 }
4768 }
4769*/
4770 if (pa != null)
4771 {
4772 pa.SetMaterial(Material);
4773 DoPhysicsPropertyUpdate(UsePhysics, true);
4774 }
4775 }
4776 else // it already has a physical representation
4270 { 4777 {
4271 pa.SetMaterial(Material);
4272 pa.Position = GetWorldPosition();
4273 pa.Orientation = GetWorldRotation();
4274 DoPhysicsPropertyUpdate(UsePhysics, true);
4275 4778
4276 SubscribeForCollisionEvents(); 4779 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4780/* moved into DoPhysicsPropertyUpdate
4781 if(VolumeDetectActive)
4782 pa.SetVolumeDetect(1);
4783 else
4784 pa.SetVolumeDetect(0);
4785*/
4786
4787 if (pa.Building != building)
4788 pa.Building = building;
4277 } 4789 }
4278 }
4279 else // it already has a physical representation
4280 {
4281 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4282 }
4283 }
4284 4790
4791 UpdatePhysicsSubscribedEvents();
4792 }
4793 }
4285 if (SetVD) 4794 if (SetVD)
4286 { 4795 {
4287 // If the above logic worked (this is urgent candidate to unit tests!) 4796 // If the above logic worked (this is urgent candidate to unit tests!)
@@ -4295,6 +4804,7 @@ namespace OpenSim.Region.Framework.Scenes
4295 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4804 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4296 VolumeDetectActive = true; 4805 VolumeDetectActive = true;
4297 } 4806 }
4807 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4298 } 4808 }
4299 else if (SetVD != wasVD) 4809 else if (SetVD != wasVD)
4300 { 4810 {
@@ -4306,105 +4816,51 @@ namespace OpenSim.Region.Framework.Scenes
4306 RemFlag(PrimFlags.Phantom); 4816 RemFlag(PrimFlags.Phantom);
4307 VolumeDetectActive = false; 4817 VolumeDetectActive = false;
4308 } 4818 }
4309 4819 // and last in case we have a new actor and not building
4310 if (SetTemporary)
4311 {
4312 AddFlag(PrimFlags.TemporaryOnRez);
4313 }
4314 else
4315 {
4316 RemFlag(PrimFlags.TemporaryOnRez);
4317 }
4318
4319 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4320 4820
4321 if (ParentGroup != null) 4821 if (ParentGroup != null)
4322 { 4822 {
4323 ParentGroup.HasGroupChanged = true; 4823 ParentGroup.HasGroupChanged = true;
4324 ScheduleFullUpdate(); 4824 ScheduleFullUpdate();
4325 } 4825 }
4326 4826
4327// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4827// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4328 } 4828 }
4329 4829
4330 /// <summary> 4830 /// <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>
4375 /// Adds this part to the physics scene. 4831 /// Adds this part to the physics scene.
4832 /// and sets the PhysActor property
4376 /// </summary> 4833 /// </summary>
4377 /// <remarks>This method also sets the PhysActor property.</remarks> 4834 /// <param name="isPhysical">Add this prim as physical.</param>
4378 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4835 /// <param name="isPhantom">Add this prim as phantom.</param>
4379 /// <returns> 4836 /// <param name="building">tells physics to delay full construction of object</param>
4380 /// The physics actor. null if there was a failure. 4837 /// <param name="applyDynamics">applies velocities, force and torque</param>
4381 /// </returns> 4838 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4382 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics) 4839 {
4383 {
4384 PhysicsActor pa; 4840 PhysicsActor pa;
4385 4841
4386 Vector3 velocity = Velocity; 4842 Vector3 velocity = Velocity;
4387 Vector3 rotationalVelocity = AngularVelocity;; 4843 Vector3 rotationalVelocity = AngularVelocity;;
4388 4844
4389 try 4845 try
4390 { 4846 {
4391 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4847 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4392 string.Format("{0}/{1}", Name, UUID), 4848 string.Format("{0}/{1}", Name, UUID),
4393 Shape, 4849 Shape,
4394 AbsolutePosition, 4850 AbsolutePosition,
4395 Scale, 4851 Scale,
4396 GetWorldRotation(), 4852 GetWorldRotation(),
4397 isPhysical, 4853 isPhysical,
4398 isPhantom, 4854 isPhantom,
4399 PhysicsShapeType, 4855 PhysicsShapeType,
4400 m_localId); 4856 m_localId);
4401 } 4857 }
4402 catch (Exception e) 4858 catch (Exception e)
4403 { 4859 {
4404 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e); 4860 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4405 pa = null; 4861 pa = null;
4406 } 4862 }
4407 4863
4408 if (pa != null) 4864 if (pa != null)
4409 { 4865 {
4410 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4866 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
@@ -4415,11 +4871,23 @@ namespace OpenSim.Region.Framework.Scenes
4415 pa.Friction = Friction; 4871 pa.Friction = Friction;
4416 pa.Restitution = Restitution; 4872 pa.Restitution = Restitution;
4417 4873
4874 if(LocalId == ParentGroup.RootPart.LocalId)
4875 {
4876 pa.LockAngularMotion(RotationAxisLocks);
4877 }
4878
4418 if (VolumeDetectActive) // change if not the default only 4879 if (VolumeDetectActive) // change if not the default only
4419 pa.SetVolumeDetect(1); 4880 pa.SetVolumeDetect(1);
4881
4882 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4883 m_vehicleParams.SetVehicle(pa);
4884
4420 // we are going to tell rest of code about physics so better have this here 4885 // we are going to tell rest of code about physics so better have this here
4421 PhysActor = pa; 4886 PhysActor = pa;
4422 4887
4888 // DoPhysicsPropertyUpdate(isPhysical, true);
4889 // lets expand it here just with what it really needs to do
4890
4423 if (isPhysical) 4891 if (isPhysical)
4424 { 4892 {
4425 if (ParentGroup.RootPart.KeyframeMotion != null) 4893 if (ParentGroup.RootPart.KeyframeMotion != null)
@@ -4441,19 +4909,34 @@ namespace OpenSim.Region.Framework.Scenes
4441 } 4909 }
4442 } 4910 }
4443 4911
4444 if (applyDynamics) 4912 if (applyDynamics)
4445 // do independent of isphysical so parameters get setted (at least some) 4913 // do independent of isphysical so parameters get setted (at least some)
4446 { 4914 {
4447 Velocity = velocity; 4915 Velocity = velocity;
4448 AngularVelocity = rotationalVelocity; 4916 AngularVelocity = rotationalVelocity;
4449// pa.Velocity = velocity; 4917// pa.Velocity = velocity;
4450 pa.RotationalVelocity = rotationalVelocity; 4918 pa.RotationalVelocity = rotationalVelocity;
4919
4920 // if not vehicle and root part apply force and torque
4921 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4922 && LocalId == ParentGroup.RootPart.LocalId)
4923 {
4924 pa.Force = Force;
4925 pa.Torque = Torque;
4926 }
4451 } 4927 }
4452 4928
4453 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 4929// if (Shape.SculptEntry)
4930// CheckSculptAndLoad();
4931// else
4932 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4933
4934 if (!building)
4935 pa.Building = false;
4454 } 4936 }
4455 4937
4456 PhysActor = pa; 4938 PhysActor = pa;
4939
4457 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); 4940 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4458 } 4941 }
4459 4942
@@ -4462,14 +4945,21 @@ namespace OpenSim.Region.Framework.Scenes
4462 /// </summary> 4945 /// </summary>
4463 /// <remarks> 4946 /// <remarks>
4464 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4947 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4465 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4948 /// representation for collision detection.
4466 /// phantom.
4467 /// </remarks> 4949 /// </remarks>
4468 public void RemoveFromPhysics() 4950 public void RemoveFromPhysics()
4469 { 4951 {
4470 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); 4952 PhysicsActor pa = PhysActor;
4471 if (ParentGroup.Scene.PhysicsScene != null) 4953 if (pa != null)
4472 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4954 {
4955 pa.OnCollisionUpdate -= PhysicsCollision;
4956 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4957 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4958
4959 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4960
4961 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
4962 }
4473 PhysActor = null; 4963 PhysActor = null;
4474 } 4964 }
4475 4965
@@ -4601,6 +5091,8 @@ namespace OpenSim.Region.Framework.Scenes
4601 { 5091 {
4602// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 5092// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4603 5093
5094 return;
5095
4604 if (ParentGroup.IsDeleted) 5096 if (ParentGroup.IsDeleted)
4605 return; 5097 return;
4606 5098
@@ -4724,6 +5216,44 @@ namespace OpenSim.Region.Framework.Scenes
4724 } 5216 }
4725 } 5217 }
4726 5218
5219
5220 private void UpdatePhysicsSubscribedEvents()
5221 {
5222 PhysicsActor pa = PhysActor;
5223 if (pa == null)
5224 return;
5225
5226 pa.OnCollisionUpdate -= PhysicsCollision;
5227
5228 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5229
5230 scriptEvents CombinedEvents = AggregateScriptEvents;
5231
5232 // merge with root part
5233 if (ParentGroup != null && ParentGroup.RootPart != null)
5234 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5235
5236 // submit to this part case
5237 if (VolumeDetectActive)
5238 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5239 else if ((Flags & PrimFlags.Phantom) != 0)
5240 CombinedEvents &= PhyscicsPhantonSubsEvents;
5241 else
5242 CombinedEvents &= PhysicsNeededSubsEvents;
5243
5244 if (hassound || CombinedEvents != 0)
5245 {
5246 // subscribe to physics updates.
5247 pa.OnCollisionUpdate += PhysicsCollision;
5248 pa.SubscribeEvents(50); // 20 reports per second
5249 }
5250 else
5251 {
5252 pa.UnSubscribeEvents();
5253 }
5254 }
5255
5256
4727 public void aggregateScriptEvents() 5257 public void aggregateScriptEvents()
4728 { 5258 {
4729 if (ParentGroup == null || ParentGroup.RootPart == null) 5259 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4760,8 +5290,32 @@ namespace OpenSim.Region.Framework.Scenes
4760 { 5290 {
4761 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5291 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4762 } 5292 }
4763 5293/*
4764 SubscribeForCollisionEvents(); 5294 PhysicsActor pa = PhysActor;
5295 if (pa != null)
5296 {
5297 if (
5298// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5299// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5300// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5301// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5302// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5303// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5304 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5305 )
5306 {
5307 // subscribe to physics updates.
5308 pa.OnCollisionUpdate += PhysicsCollision;
5309 pa.SubscribeEvents(1000);
5310 }
5311 else
5312 {
5313 pa.UnSubscribeEvents();
5314 pa.OnCollisionUpdate -= PhysicsCollision;
5315 }
5316 }
5317 */
5318 UpdatePhysicsSubscribedEvents();
4765 5319
4766 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5320 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4767 //{ 5321 //{
@@ -4970,6 +5524,18 @@ namespace OpenSim.Region.Framework.Scenes
4970 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5524 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4971 } 5525 }
4972 5526
5527 public void ResetOwnerChangeFlag()
5528 {
5529 List<UUID> inv = Inventory.GetInventoryList();
5530
5531 foreach (UUID itemID in inv)
5532 {
5533 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5534 item.OwnerChanged = false;
5535 Inventory.UpdateInventoryItem(item, false, false);
5536 }
5537 }
5538
4973 /// <summary> 5539 /// <summary>
4974 /// Record an avatar sitting on this part. 5540 /// Record an avatar sitting on this part.
4975 /// </summary> 5541 /// </summary>
@@ -4990,7 +5556,8 @@ namespace OpenSim.Region.Framework.Scenes
4990 5556
4991 if (m_sittingAvatars.Add(sp)) 5557 if (m_sittingAvatars.Add(sp))
4992 { 5558 {
4993 ParentGroup.m_sittingAvatars.Add(sp); 5559 if(!ParentGroup.m_sittingAvatars.Contains(sp))
5560 ParentGroup.m_sittingAvatars.Add(sp);
4994 5561
4995 return true; 5562 return true;
4996 } 5563 }
@@ -5063,4 +5630,4 @@ namespace OpenSim.Region.Framework.Scenes
5063 } 5630 }
5064 } 5631 }
5065 } 5632 }
5066} \ No newline at end of file 5633}