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.cs1733
1 files changed, 1206 insertions, 527 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index e0ea344..0fe9842 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -121,7 +122,18 @@ namespace OpenSim.Region.Framework.Scenes
121 /// Denote all sides of the prim 122 /// Denote all sides of the prim
122 /// </value> 123 /// </value>
123 public const int ALL_SIDES = -1; 124 public const int ALL_SIDES = -1;
124 125
126 private const scriptEvents PhysicsNeededSubsEvents = (
127 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
128 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
129 );
130 private const scriptEvents PhyscicsPhantonSubsEvents = (
131 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
132 );
133 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
134 scriptEvents.collision_start | scriptEvents.collision_end
135 );
136
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 138
127 /// <value> 139 /// <value>
@@ -132,7 +144,7 @@ namespace OpenSim.Region.Framework.Scenes
132 /// </remarks> 144 /// </remarks>
133 public bool IsRoot 145 public bool IsRoot
134 { 146 {
135 get { return ParentGroup.RootPart == this; } 147 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
136 } 148 }
137 149
138 /// <summary> 150 /// <summary>
@@ -191,12 +203,25 @@ namespace OpenSim.Region.Framework.Scenes
191 203
192 public double SoundRadius; 204 public double SoundRadius;
193 205
206
194 public uint TimeStampFull; 207 public uint TimeStampFull;
195 208
196 public uint TimeStampLastActivity; // Will be used for AutoReturn 209 public uint TimeStampLastActivity; // Will be used for AutoReturn
197 210
198 public uint TimeStampTerse; 211 public uint TimeStampTerse;
199 212
213 // The following two are to hold the attachment data
214 // while an object is inworld
215 [XmlIgnore]
216 public byte AttachPoint = 0;
217
218 [XmlIgnore]
219 public Vector3 AttachOffset = Vector3.Zero;
220
221 [XmlIgnore]
222 public Quaternion AttachRotation = Quaternion.Identity;
223
224 [XmlIgnore]
200 public int STATUS_ROTATE_X; 225 public int STATUS_ROTATE_X;
201 226
202 public int STATUS_ROTATE_Y; 227 public int STATUS_ROTATE_Y;
@@ -223,8 +248,7 @@ namespace OpenSim.Region.Framework.Scenes
223 248
224 public Vector3 RotationAxis = Vector3.One; 249 public Vector3 RotationAxis = Vector3.One;
225 250
226 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 251 public bool VolumeDetectActive;
227 // Certainly this must be a persistant setting finally
228 252
229 public bool IsWaitingForFirstSpinUpdatePacket; 253 public bool IsWaitingForFirstSpinUpdatePacket;
230 254
@@ -264,10 +288,10 @@ namespace OpenSim.Region.Framework.Scenes
264 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 288 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
265 private Vector3 m_sitTargetPosition; 289 private Vector3 m_sitTargetPosition;
266 private string m_sitAnimation = "SIT"; 290 private string m_sitAnimation = "SIT";
291 private bool m_occupied; // KF if any av is sitting on this prim
267 private string m_text = String.Empty; 292 private string m_text = String.Empty;
268 private string m_touchName = String.Empty; 293 private string m_touchName = String.Empty;
269 private readonly List<UndoState> m_undo = new List<UndoState>(5); 294 private UndoRedoState m_UndoRedo = null;
270 private readonly List<UndoState> m_redo = new List<UndoState>(5);
271 295
272 private bool m_passTouches = false; 296 private bool m_passTouches = false;
273 private bool m_passCollisions = false; 297 private bool m_passCollisions = false;
@@ -295,8 +319,20 @@ namespace OpenSim.Region.Framework.Scenes
295 protected Vector3 m_lastVelocity; 319 protected Vector3 m_lastVelocity;
296 protected Vector3 m_lastAcceleration; 320 protected Vector3 m_lastAcceleration;
297 protected Vector3 m_lastAngularVelocity; 321 protected Vector3 m_lastAngularVelocity;
298 protected int m_lastTerseSent; 322 protected int m_lastUpdateSentTime;
299 323 protected float m_buoyancy = 0.0f;
324 protected Vector3 m_force;
325 protected Vector3 m_torque;
326
327 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
328 protected float m_density = 1000.0f; // in kg/m^3
329 protected float m_gravitymod = 1.0f;
330 protected float m_friction = 0.6f; // wood
331 protected float m_bounce = 0.5f; // wood
332
333
334 protected bool m_isSelected = false;
335
300 /// <summary> 336 /// <summary>
301 /// Stores media texture data 337 /// Stores media texture data
302 /// </summary> 338 /// </summary>
@@ -308,10 +344,25 @@ namespace OpenSim.Region.Framework.Scenes
308 private Vector3 m_cameraAtOffset; 344 private Vector3 m_cameraAtOffset;
309 private bool m_forceMouselook; 345 private bool m_forceMouselook;
310 346
311 // TODO: Collision sound should have default. 347
348 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
349 private sbyte m_collisionSoundType;
312 private UUID m_collisionSound; 350 private UUID m_collisionSound;
313 private float m_collisionSoundVolume; 351 private float m_collisionSoundVolume;
314 352
353 private int LastColSoundSentTime;
354
355
356 private SOPVehicle m_vehicleParams = null;
357
358 private KeyframeMotion m_keyframeMotion = null;
359
360 public KeyframeMotion KeyframeMotion
361 {
362 get; set;
363 }
364
365
315 #endregion Fields 366 #endregion Fields
316 367
317// ~SceneObjectPart() 368// ~SceneObjectPart()
@@ -340,6 +391,7 @@ namespace OpenSim.Region.Framework.Scenes
340 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 391 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
341 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 392 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
342 m_inventory = new SceneObjectPartInventory(this); 393 m_inventory = new SceneObjectPartInventory(this);
394 LastColSoundSentTime = Util.EnvironmentTickCount();
343 } 395 }
344 396
345 /// <summary> 397 /// <summary>
@@ -354,7 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
354 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 406 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
355 Quaternion rotationOffset, Vector3 offsetPosition) : this() 407 Quaternion rotationOffset, Vector3 offsetPosition) : this()
356 { 408 {
357 m_name = "Primitive"; 409 m_name = "Object";
358 410
359 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 411 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
360 LastOwnerID = CreatorID = OwnerID = ownerID; 412 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -393,7 +445,7 @@ namespace OpenSim.Region.Framework.Scenes
393 private uint _ownerMask = (uint)PermissionMask.All; 445 private uint _ownerMask = (uint)PermissionMask.All;
394 private uint _groupMask = (uint)PermissionMask.None; 446 private uint _groupMask = (uint)PermissionMask.None;
395 private uint _everyoneMask = (uint)PermissionMask.None; 447 private uint _everyoneMask = (uint)PermissionMask.None;
396 private uint _nextOwnerMask = (uint)PermissionMask.All; 448 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
397 private PrimFlags _flags = PrimFlags.None; 449 private PrimFlags _flags = PrimFlags.None;
398 private DateTime m_expires; 450 private DateTime m_expires;
399 private DateTime m_rezzed; 451 private DateTime m_rezzed;
@@ -487,12 +539,16 @@ namespace OpenSim.Region.Framework.Scenes
487 } 539 }
488 540
489 /// <value> 541 /// <value>
490 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 542 /// Get the inventory list
491 /// </value> 543 /// </value>
492 public TaskInventoryDictionary TaskInventory 544 public TaskInventoryDictionary TaskInventory
493 { 545 {
494 get { return m_inventory.Items; } 546 get {
495 set { m_inventory.Items = value; } 547 return m_inventory.Items;
548 }
549 set {
550 m_inventory.Items = value;
551 }
496 } 552 }
497 553
498 /// <summary> 554 /// <summary>
@@ -542,20 +598,6 @@ namespace OpenSim.Region.Framework.Scenes
542 } 598 }
543 } 599 }
544 600
545 public byte Material
546 {
547 get { return (byte) m_material; }
548 set
549 {
550 m_material = (Material)value;
551
552 PhysicsActor pa = PhysActor;
553
554 if (pa != null)
555 pa.SetMaterial((int)value);
556 }
557 }
558
559 [XmlIgnore] 601 [XmlIgnore]
560 public bool PassTouches 602 public bool PassTouches
561 { 603 {
@@ -581,6 +623,18 @@ namespace OpenSim.Region.Framework.Scenes
581 } 623 }
582 } 624 }
583 625
626 public bool IsSelected
627 {
628 get { return m_isSelected; }
629 set
630 {
631 m_isSelected = value;
632 if (ParentGroup != null)
633 ParentGroup.PartSelectChanged(value);
634 }
635 }
636
637
584 public Dictionary<int, string> CollisionFilter 638 public Dictionary<int, string> CollisionFilter
585 { 639 {
586 get { return m_CollisionFilter; } 640 get { return m_CollisionFilter; }
@@ -649,14 +703,12 @@ namespace OpenSim.Region.Framework.Scenes
649 set { m_LoopSoundSlavePrims = value; } 703 set { m_LoopSoundSlavePrims = value; }
650 } 704 }
651 705
652
653 public Byte[] TextureAnimation 706 public Byte[] TextureAnimation
654 { 707 {
655 get { return m_TextureAnimation; } 708 get { return m_TextureAnimation; }
656 set { m_TextureAnimation = value; } 709 set { m_TextureAnimation = value; }
657 } 710 }
658 711
659
660 public Byte[] ParticleSystem 712 public Byte[] ParticleSystem
661 { 713 {
662 get { return m_particleSystem; } 714 get { return m_particleSystem; }
@@ -693,9 +745,12 @@ namespace OpenSim.Region.Framework.Scenes
693 { 745 {
694 // If this is a linkset, we don't want the physics engine mucking up our group position here. 746 // If this is a linkset, we don't want the physics engine mucking up our group position here.
695 PhysicsActor actor = PhysActor; 747 PhysicsActor actor = PhysActor;
696 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 748 if (ParentID == 0)
697 if (actor != null && ParentID == 0) 749 {
698 m_groupPosition = actor.Position; 750 if (actor != null)
751 m_groupPosition = actor.Position;
752 return m_groupPosition;
753 }
699 754
700 // If I'm an attachment, my position is reported as the position of who I'm attached to 755 // If I'm an attachment, my position is reported as the position of who I'm attached to
701 if (ParentGroup.IsAttachment) 756 if (ParentGroup.IsAttachment)
@@ -705,14 +760,16 @@ namespace OpenSim.Region.Framework.Scenes
705 return sp.AbsolutePosition; 760 return sp.AbsolutePosition;
706 } 761 }
707 762
763 // use root prim's group position. Physics may have updated it
764 if (ParentGroup.RootPart != this)
765 m_groupPosition = ParentGroup.RootPart.GroupPosition;
708 return m_groupPosition; 766 return m_groupPosition;
709 } 767 }
710 set 768 set
711 { 769 {
712 m_groupPosition = value; 770 m_groupPosition = value;
713
714 PhysicsActor actor = PhysActor; 771 PhysicsActor actor = PhysActor;
715 if (actor != null) 772 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
716 { 773 {
717 try 774 try
718 { 775 {
@@ -736,16 +793,6 @@ namespace OpenSim.Region.Framework.Scenes
736 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); 793 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
737 } 794 }
738 } 795 }
739
740 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
741 if (SitTargetAvatar != UUID.Zero)
742 {
743 ScenePresence avatar;
744 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
745 {
746 avatar.ParentPosition = GetWorldPosition();
747 }
748 }
749 } 796 }
750 } 797 }
751 798
@@ -754,7 +801,7 @@ namespace OpenSim.Region.Framework.Scenes
754 get { return m_offsetPosition; } 801 get { return m_offsetPosition; }
755 set 802 set
756 { 803 {
757// StoreUndoState(); 804 Vector3 oldpos = m_offsetPosition;
758 m_offsetPosition = value; 805 m_offsetPosition = value;
759 806
760 if (ParentGroup != null && !ParentGroup.IsDeleted) 807 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -766,10 +813,25 @@ namespace OpenSim.Region.Framework.Scenes
766 actor.Orientation = GetWorldRotation(); 813 actor.Orientation = GetWorldRotation();
767 814
768 // Tell the physics engines that this prim changed. 815 // Tell the physics engines that this prim changed.
769 if (ParentGroup.Scene != null) 816 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
770 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 817 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
771 } 818 }
819
820 if (!m_parentGroup.m_dupeInProgress)
821 {
822 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
823 foreach (ScenePresence av in avs)
824 {
825 if (av.ParentID == m_localId)
826 {
827 Vector3 offset = (m_offsetPosition - oldpos);
828 av.AbsolutePosition += offset;
829 av.SendAvatarDataToAllAgents();
830 }
831 }
832 }
772 } 833 }
834 TriggerScriptChangedEvent(Changed.POSITION);
773 } 835 }
774 } 836 }
775 837
@@ -820,7 +882,7 @@ namespace OpenSim.Region.Framework.Scenes
820 882
821 set 883 set
822 { 884 {
823 StoreUndoState(); 885// StoreUndoState();
824 m_rotationOffset = value; 886 m_rotationOffset = value;
825 887
826 PhysicsActor actor = PhysActor; 888 PhysicsActor actor = PhysActor;
@@ -908,19 +970,36 @@ namespace OpenSim.Region.Framework.Scenes
908 get 970 get
909 { 971 {
910 PhysicsActor actor = PhysActor; 972 PhysicsActor actor = PhysActor;
911 if ((actor != null) && actor.IsPhysical) 973 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
912 { 974 {
913 m_angularVelocity = actor.RotationalVelocity; 975 m_angularVelocity = actor.RotationalVelocity;
914 } 976 }
915 return m_angularVelocity; 977 return m_angularVelocity;
916 } 978 }
917 set { m_angularVelocity = value; } 979 set
980 {
981 m_angularVelocity = value;
982 PhysicsActor actor = PhysActor;
983 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE)
984 {
985 actor.RotationalVelocity = m_angularVelocity;
986 }
987 }
918 } 988 }
919 989
920 /// <summary></summary> 990 /// <summary></summary>
921 public Vector3 Acceleration 991 public Vector3 Acceleration
922 { 992 {
923 get { return m_acceleration; } 993 get
994 {
995 PhysicsActor actor = PhysActor;
996 if (actor != null)
997 {
998 m_acceleration = actor.Acceleration;
999 }
1000 return m_acceleration;
1001 }
1002
924 set { m_acceleration = value; } 1003 set { m_acceleration = value; }
925 } 1004 }
926 1005
@@ -988,7 +1067,10 @@ namespace OpenSim.Region.Framework.Scenes
988 public PrimitiveBaseShape Shape 1067 public PrimitiveBaseShape Shape
989 { 1068 {
990 get { return m_shape; } 1069 get { return m_shape; }
991 set { m_shape = value;} 1070 set
1071 {
1072 m_shape = value;
1073 }
992 } 1074 }
993 1075
994 /// <summary> 1076 /// <summary>
@@ -1001,7 +1083,6 @@ namespace OpenSim.Region.Framework.Scenes
1001 { 1083 {
1002 if (m_shape != null) 1084 if (m_shape != null)
1003 { 1085 {
1004 StoreUndoState();
1005 1086
1006 m_shape.Scale = value; 1087 m_shape.Scale = value;
1007 1088
@@ -1028,6 +1109,7 @@ namespace OpenSim.Region.Framework.Scenes
1028 } 1109 }
1029 1110
1030 public UpdateRequired UpdateFlag { get; set; } 1111 public UpdateRequired UpdateFlag { get; set; }
1112 public bool UpdatePhysRequired { get; set; }
1031 1113
1032 /// <summary> 1114 /// <summary>
1033 /// Used for media on a prim. 1115 /// Used for media on a prim.
@@ -1068,10 +1150,7 @@ namespace OpenSim.Region.Framework.Scenes
1068 { 1150 {
1069 get 1151 get
1070 { 1152 {
1071 if (ParentGroup.IsAttachment) 1153 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1072 return GroupPosition;
1073
1074 return m_offsetPosition + m_groupPosition;
1075 } 1154 }
1076 } 1155 }
1077 1156
@@ -1249,6 +1328,13 @@ namespace OpenSim.Region.Framework.Scenes
1249 _flags = value; 1328 _flags = value;
1250 } 1329 }
1251 } 1330 }
1331
1332 [XmlIgnore]
1333 public bool IsOccupied // KF If an av is sittingon this prim
1334 {
1335 get { return m_occupied; }
1336 set { m_occupied = value; }
1337 }
1252 1338
1253 /// <summary> 1339 /// <summary>
1254 /// 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 1340 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
@@ -1299,12 +1385,41 @@ namespace OpenSim.Region.Framework.Scenes
1299 set { m_sitAnimation = value; } 1385 set { m_sitAnimation = value; }
1300 } 1386 }
1301 1387
1388 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1389
1390 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1391 // runtime thing.. do not persist
1392 [XmlIgnore]
1393 public sbyte CollisionSoundType
1394 {
1395 get
1396 {
1397 return m_collisionSoundType;
1398 }
1399 set
1400 {
1401 m_collisionSoundType = value;
1402 if (value == -1)
1403 m_collisionSound = invalidCollisionSoundUUID;
1404 else if (value == 0)
1405 m_collisionSound = UUID.Zero;
1406 }
1407 }
1408
1302 public UUID CollisionSound 1409 public UUID CollisionSound
1303 { 1410 {
1304 get { return m_collisionSound; } 1411 get { return m_collisionSound; }
1305 set 1412 set
1306 { 1413 {
1307 m_collisionSound = value; 1414 m_collisionSound = value;
1415
1416 if (value == invalidCollisionSoundUUID)
1417 m_collisionSoundType = -1;
1418 else if (value == UUID.Zero)
1419 m_collisionSoundType = 0;
1420 else
1421 m_collisionSoundType = 1;
1422
1308 aggregateScriptEvents(); 1423 aggregateScriptEvents();
1309 } 1424 }
1310 } 1425 }
@@ -1315,6 +1430,324 @@ namespace OpenSim.Region.Framework.Scenes
1315 set { m_collisionSoundVolume = value; } 1430 set { m_collisionSoundVolume = value; }
1316 } 1431 }
1317 1432
1433 public float Buoyancy
1434 {
1435 get
1436 {
1437 if (ParentGroup.RootPart == this)
1438 return m_buoyancy;
1439
1440 return ParentGroup.RootPart.Buoyancy;
1441 }
1442 set
1443 {
1444 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1445 {
1446 ParentGroup.RootPart.Buoyancy = value;
1447 return;
1448 }
1449 m_buoyancy = value;
1450 if (PhysActor != null)
1451 PhysActor.Buoyancy = value;
1452 }
1453 }
1454
1455 public Vector3 Force
1456 {
1457 get
1458 {
1459 if (ParentGroup.RootPart == this)
1460 return m_force;
1461
1462 return ParentGroup.RootPart.Force;
1463 }
1464
1465 set
1466 {
1467 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1468 {
1469 ParentGroup.RootPart.Force = value;
1470 return;
1471 }
1472 m_force = value;
1473 if (PhysActor != null)
1474 PhysActor.Force = value;
1475 }
1476 }
1477
1478 public Vector3 Torque
1479 {
1480 get
1481 {
1482 if (ParentGroup.RootPart == this)
1483 return m_torque;
1484
1485 return ParentGroup.RootPart.Torque;
1486 }
1487
1488 set
1489 {
1490 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1491 {
1492 ParentGroup.RootPart.Torque = value;
1493 return;
1494 }
1495 m_torque = value;
1496 if (PhysActor != null)
1497 PhysActor.Torque = value;
1498 }
1499 }
1500
1501 public byte Material
1502 {
1503 get { return (byte)m_material; }
1504 set
1505 {
1506 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1507 {
1508 bool update = false;
1509
1510 if (m_material != (Material)value)
1511 {
1512 update = true;
1513 m_material = (Material)value;
1514 }
1515
1516 if (m_friction != SOPMaterialData.friction(m_material))
1517 {
1518 update = true;
1519 m_friction = SOPMaterialData.friction(m_material);
1520 }
1521
1522 if (m_bounce != SOPMaterialData.bounce(m_material))
1523 {
1524 update = true;
1525 m_bounce = SOPMaterialData.bounce(m_material);
1526 }
1527
1528 if (update)
1529 {
1530 if (PhysActor != null)
1531 {
1532 PhysActor.SetMaterial((int)value);
1533 }
1534 if(ParentGroup != null)
1535 ParentGroup.HasGroupChanged = true;
1536 ScheduleFullUpdateIfNone();
1537 UpdatePhysRequired = true;
1538 }
1539 }
1540 }
1541 }
1542
1543 // not a propriety to move to methods place later
1544 private bool HasMesh()
1545 {
1546 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1547 return true;
1548 return false;
1549 }
1550
1551 // not a propriety to move to methods place later
1552 public byte DefaultPhysicsShapeType()
1553 {
1554 byte type;
1555
1556 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1557 type = (byte)PhysShapeType.convex;
1558 else
1559 type = (byte)PhysShapeType.prim;
1560
1561 return type;
1562 }
1563
1564 [XmlIgnore]
1565 public bool UsesComplexCost
1566 {
1567 get
1568 {
1569 byte pst = PhysicsShapeType;
1570 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1571 return true;
1572 return false;
1573 }
1574 }
1575
1576 [XmlIgnore]
1577 public float PhysicsCost
1578 {
1579 get
1580 {
1581 if(PhysicsShapeType == (byte)PhysShapeType.none)
1582 return 0;
1583
1584 float cost = 0.1f;
1585 if (PhysActor != null)
1586 cost = PhysActor.PhysicsCost;
1587 else
1588 cost = 0.1f;
1589
1590 if ((Flags & PrimFlags.Physics) != 0)
1591 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1592 return cost;
1593 }
1594 }
1595
1596 [XmlIgnore]
1597 public float StreamingCost
1598 {
1599 get
1600 {
1601 float cost;
1602 if (PhysActor != null)
1603 cost = PhysActor.StreamCost;
1604 else
1605 cost = 1.0f;
1606 return 1.0f;
1607 }
1608 }
1609
1610 [XmlIgnore]
1611 public float SimulationCost
1612 {
1613 get
1614 {
1615 // ignoring scripts. Don't like considering them for this
1616 if((Flags & PrimFlags.Physics) != 0)
1617 return 1.0f;
1618
1619 return 0.5f;
1620 }
1621 }
1622
1623 public byte PhysicsShapeType
1624 {
1625 get { return m_physicsShapeType; }
1626 set
1627 {
1628 byte oldv = m_physicsShapeType;
1629
1630 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1631 {
1632 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1633 m_physicsShapeType = DefaultPhysicsShapeType();
1634 else
1635 m_physicsShapeType = value;
1636 }
1637 else
1638 m_physicsShapeType = DefaultPhysicsShapeType();
1639
1640 if (m_physicsShapeType != oldv && ParentGroup != null)
1641 {
1642 if (m_physicsShapeType == (byte)PhysShapeType.none)
1643 {
1644 if (PhysActor != null)
1645 {
1646 Velocity = new Vector3(0, 0, 0);
1647 Acceleration = new Vector3(0, 0, 0);
1648 if (ParentGroup.RootPart == this)
1649 AngularVelocity = new Vector3(0, 0, 0);
1650 ParentGroup.Scene.RemovePhysicalPrim(1);
1651 RemoveFromPhysics();
1652 }
1653 }
1654 else if (PhysActor == null)
1655 {
1656 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1657 UpdatePhysicsSubscribedEvents();
1658 }
1659 else
1660 {
1661 PhysActor.PhysicsShapeType = m_physicsShapeType;
1662// if (Shape.SculptEntry)
1663// CheckSculptAndLoad();
1664 }
1665
1666 if (ParentGroup != null)
1667 ParentGroup.HasGroupChanged = true;
1668 }
1669
1670 if (m_physicsShapeType != value)
1671 {
1672 UpdatePhysRequired = true;
1673 }
1674 }
1675 }
1676
1677 public float Density // in kg/m^3
1678 {
1679 get { return m_density; }
1680 set
1681 {
1682 if (value >=1 && value <= 22587.0)
1683 {
1684 m_density = value;
1685 UpdatePhysRequired = true;
1686 }
1687
1688 ScheduleFullUpdateIfNone();
1689
1690 if (ParentGroup != null)
1691 ParentGroup.HasGroupChanged = true;
1692 }
1693 }
1694
1695 public float GravityModifier
1696 {
1697 get { return m_gravitymod; }
1698 set
1699 {
1700 if( value >= -1 && value <=28.0f)
1701 {
1702 m_gravitymod = value;
1703 UpdatePhysRequired = true;
1704 }
1705
1706 ScheduleFullUpdateIfNone();
1707
1708 if (ParentGroup != null)
1709 ParentGroup.HasGroupChanged = true;
1710
1711 }
1712 }
1713
1714 public float Friction
1715 {
1716 get { return m_friction; }
1717 set
1718 {
1719 if (value >= 0 && value <= 255.0f)
1720 {
1721 m_friction = value;
1722 UpdatePhysRequired = true;
1723 }
1724
1725 ScheduleFullUpdateIfNone();
1726
1727 if (ParentGroup != null)
1728 ParentGroup.HasGroupChanged = true;
1729 }
1730 }
1731
1732 public float Bounciness
1733 {
1734 get { return m_bounce; }
1735 set
1736 {
1737 if (value >= 0 && value <= 1.0f)
1738 {
1739 m_bounce = value;
1740 UpdatePhysRequired = true;
1741 }
1742
1743 ScheduleFullUpdateIfNone();
1744
1745 if (ParentGroup != null)
1746 ParentGroup.HasGroupChanged = true;
1747 }
1748 }
1749
1750
1318 #endregion Public Properties with only Get 1751 #endregion Public Properties with only Get
1319 1752
1320 private uint ApplyMask(uint val, bool set, uint mask) 1753 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1460,6 +1893,61 @@ namespace OpenSim.Region.Framework.Scenes
1460 } 1893 }
1461 } 1894 }
1462 1895
1896 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1897 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1898 {
1899 if (ParentGroup == null || ParentGroup.IsDeleted)
1900 return;
1901
1902 if (ParentGroup.IsAttachment)
1903 return; // don't work on attachments (for now ??)
1904
1905 SceneObjectPart root = ParentGroup.RootPart;
1906
1907 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
1908 return;
1909
1910 PhysicsActor pa = root.PhysActor;
1911
1912 if (pa == null || !pa.IsPhysical)
1913 return;
1914
1915 if (localGlobalTF)
1916 {
1917 pVel = pVel * GetWorldRotation();
1918 }
1919
1920 ParentGroup.Velocity = pVel;
1921 }
1922
1923 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
1924 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
1925 {
1926 if (ParentGroup == null || ParentGroup.IsDeleted)
1927 return;
1928
1929 if (ParentGroup.IsAttachment)
1930 return; // don't work on attachments (for now ??)
1931
1932 SceneObjectPart root = ParentGroup.RootPart;
1933
1934 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
1935 return;
1936
1937 PhysicsActor pa = root.PhysActor;
1938
1939 if (pa == null || !pa.IsPhysical)
1940 return;
1941
1942 if (localGlobalTF)
1943 {
1944 pAngVel = pAngVel * GetWorldRotation();
1945 }
1946
1947 root.AngularVelocity = pAngVel;
1948 }
1949
1950
1463 /// <summary> 1951 /// <summary>
1464 /// hook to the physics scene to apply angular impulse 1952 /// hook to the physics scene to apply angular impulse
1465 /// This is sent up to the group, which then finds the root prim 1953 /// This is sent up to the group, which then finds the root prim
@@ -1480,7 +1968,7 @@ namespace OpenSim.Region.Framework.Scenes
1480 impulse = newimpulse; 1968 impulse = newimpulse;
1481 } 1969 }
1482 1970
1483 ParentGroup.applyAngularImpulse(impulse); 1971 ParentGroup.ApplyAngularImpulse(impulse);
1484 } 1972 }
1485 1973
1486 /// <summary> 1974 /// <summary>
@@ -1490,20 +1978,24 @@ namespace OpenSim.Region.Framework.Scenes
1490 /// </summary> 1978 /// </summary>
1491 /// <param name="impulsei">Vector force</param> 1979 /// <param name="impulsei">Vector force</param>
1492 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1980 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1493 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1981
1982 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1983 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1494 { 1984 {
1495 Vector3 impulse = impulsei; 1985 Vector3 torque = torquei;
1496 1986
1497 if (localGlobalTF) 1987 if (localGlobalTF)
1498 { 1988 {
1989/*
1499 Quaternion grot = GetWorldRotation(); 1990 Quaternion grot = GetWorldRotation();
1500 Quaternion AXgrot = grot; 1991 Quaternion AXgrot = grot;
1501 Vector3 AXimpulsei = impulsei; 1992 Vector3 AXimpulsei = impulsei;
1502 Vector3 newimpulse = AXimpulsei * AXgrot; 1993 Vector3 newimpulse = AXimpulsei * AXgrot;
1503 impulse = newimpulse; 1994 */
1995 torque *= GetWorldRotation();
1504 } 1996 }
1505 1997
1506 ParentGroup.setAngularImpulse(impulse); 1998 Torque = torque;
1507 } 1999 }
1508 2000
1509 /// <summary> 2001 /// <summary>
@@ -1511,17 +2003,23 @@ namespace OpenSim.Region.Framework.Scenes
1511 /// </summary> 2003 /// </summary>
1512 /// <param name="rootObjectFlags"></param> 2004 /// <param name="rootObjectFlags"></param>
1513 /// <param name="VolumeDetectActive"></param> 2005 /// <param name="VolumeDetectActive"></param>
1514 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 2006 /// <param name="building"></param>
2007
2008 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1515 { 2009 {
2010 VolumeDetectActive = _VolumeDetectActive;
2011
1516 if (!ParentGroup.Scene.CollidablePrims) 2012 if (!ParentGroup.Scene.CollidablePrims)
1517 return; 2013 return;
1518 2014
1519// m_log.DebugFormat( 2015 if (PhysicsShapeType == (byte)PhysShapeType.none)
1520// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 2016 return;
1521// Name, LocalId, UUID, m_physicalPrim); 2017
2018 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
2019 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1522 2020
1523 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2021 if (_VolumeDetectActive)
1524 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2022 isPhantom = true;
1525 2023
1526 if (IsJoint()) 2024 if (IsJoint())
1527 { 2025 {
@@ -1529,22 +2027,14 @@ namespace OpenSim.Region.Framework.Scenes
1529 } 2027 }
1530 else 2028 else
1531 { 2029 {
1532 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 2030 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1533 if (VolumeDetectActive) 2031 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1534 isPhantom = false;
1535
1536 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
1537 // or flexible
1538 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1539 { 2032 {
1540 // Added clarification.. since A rigid body is an object that you can kick around, etc. 2033 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1541 bool rigidBody = isPhysical && !isPhantom; 2034 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1542
1543 PhysicsActor pa = AddToPhysics(rigidBody);
1544
1545 if (pa != null)
1546 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1547 } 2035 }
2036 else
2037 PhysActor = null; // just to be sure
1548 } 2038 }
1549 } 2039 }
1550 2040
@@ -1596,6 +2086,12 @@ namespace OpenSim.Region.Framework.Scenes
1596 dupe.Category = Category; 2086 dupe.Category = Category;
1597 dupe.m_rezzed = m_rezzed; 2087 dupe.m_rezzed = m_rezzed;
1598 2088
2089 dupe.m_UndoRedo = null;
2090 dupe.m_isSelected = false;
2091
2092 dupe.IgnoreUndoUpdate = false;
2093 dupe.Undoing = false;
2094
1599 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2095 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1600 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2096 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1601 2097
@@ -1611,6 +2107,7 @@ namespace OpenSim.Region.Framework.Scenes
1611 2107
1612 // Move afterwards ResetIDs as it clears the localID 2108 // Move afterwards ResetIDs as it clears the localID
1613 dupe.LocalId = localID; 2109 dupe.LocalId = localID;
2110
1614 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2111 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1615 dupe.LastOwnerID = OwnerID; 2112 dupe.LastOwnerID = OwnerID;
1616 2113
@@ -1618,6 +2115,9 @@ namespace OpenSim.Region.Framework.Scenes
1618 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2115 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1619 dupe.Shape.ExtraParams = extraP; 2116 dupe.Shape.ExtraParams = extraP;
1620 2117
2118 // safeguard actual copy is done in sog.copy
2119 dupe.KeyframeMotion = null;
2120
1621 if (userExposed) 2121 if (userExposed)
1622 { 2122 {
1623/* 2123/*
@@ -1629,8 +2129,12 @@ namespace OpenSim.Region.Framework.Scenes
1629*/ 2129*/
1630 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2130 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1631 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2131 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2132// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1632 } 2133 }
1633 2134
2135 if (dupe.PhysActor != null)
2136 dupe.PhysActor.LocalID = localID;
2137
1634 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2138 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1635 2139
1636// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2140// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1649,10 +2153,10 @@ namespace OpenSim.Region.Framework.Scenes
1649 { 2153 {
1650 if (asset != null) 2154 if (asset != null)
1651 SculptTextureCallback(asset); 2155 SculptTextureCallback(asset);
1652 else 2156// else
1653 m_log.WarnFormat( 2157// m_log.WarnFormat(
1654 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2158// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1655 Name, UUID, id); 2159// Name, UUID, id);
1656 } 2160 }
1657*/ 2161*/
1658 /// <summary> 2162 /// <summary>
@@ -1751,6 +2255,7 @@ namespace OpenSim.Region.Framework.Scenes
1751 2255
1752 /// <summary> 2256 /// <summary>
1753 /// Do a physics propery update for this part. 2257 /// Do a physics propery update for this part.
2258 /// now also updates phantom and volume detector
1754 /// </summary> 2259 /// </summary>
1755 /// <param name="UsePhysics"></param> 2260 /// <param name="UsePhysics"></param>
1756 /// <param name="isNew"></param> 2261 /// <param name="isNew"></param>
@@ -1776,61 +2281,69 @@ namespace OpenSim.Region.Framework.Scenes
1776 { 2281 {
1777 if (pa.IsPhysical) // implies UsePhysics==false for this block 2282 if (pa.IsPhysical) // implies UsePhysics==false for this block
1778 { 2283 {
1779 if (!isNew) 2284 if (!isNew) // implies UsePhysics==false for this block
2285 {
1780 ParentGroup.Scene.RemovePhysicalPrim(1); 2286 ParentGroup.Scene.RemovePhysicalPrim(1);
1781 2287
1782 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2288 Velocity = new Vector3(0, 0, 0);
1783 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2289 Acceleration = new Vector3(0, 0, 0);
1784 pa.delink(); 2290 if (ParentGroup.RootPart == this)
2291 AngularVelocity = new Vector3(0, 0, 0);
1785 2292
1786 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2293 if (pa.Phantom && !VolumeDetectActive)
1787 { 2294 {
1788 // destroy all joints connected to this now deactivated body 2295 RemoveFromPhysics();
1789 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2296 return;
1790 } 2297 }
1791 2298
1792 // stop client-side interpolation of all joint proxy objects that have just been deleted 2299 pa.IsPhysical = UsePhysics;
1793 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2300 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1794 // which stops client-side interpolation of deactivated joint proxy objects. 2301 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2302 pa.delink();
2303 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2304 {
2305 // destroy all joints connected to this now deactivated body
2306 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2307 }
2308 }
1795 } 2309 }
1796 2310
1797 if (!UsePhysics && !isNew) 2311 if (pa.IsPhysical != UsePhysics)
1798 { 2312 pa.IsPhysical = UsePhysics;
1799 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1800 // prim still has velocity and continues to interpolate its position along the old
1801 // velocity-vector.
1802 Velocity = new Vector3(0, 0, 0);
1803 Acceleration = new Vector3(0, 0, 0);
1804 AngularVelocity = new Vector3(0, 0, 0);
1805 //RotationalVelocity = new Vector3(0, 0, 0);
1806 }
1807 2313
1808 pa.IsPhysical = UsePhysics; 2314 if (UsePhysics)
2315 {
2316 if (ParentGroup.RootPart.KeyframeMotion != null)
2317 ParentGroup.RootPart.KeyframeMotion.Stop();
2318 ParentGroup.RootPart.KeyframeMotion = null;
2319 ParentGroup.Scene.AddPhysicalPrim(1);
1809 2320
1810 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2321 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1811 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2322 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1812 /// that's not wholesome. Had to make Scene public
1813 //PhysActor = null;
1814 2323
1815 if ((Flags & PrimFlags.Phantom) == 0) 2324 if (ParentID != 0 && ParentID != LocalId)
1816 {
1817 if (UsePhysics)
1818 { 2325 {
1819 ParentGroup.Scene.AddPhysicalPrim(1); 2326 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1820 2327
1821 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2328 if (parentPa != null)
1822 pa.OnOutOfBounds += PhysicsOutOfBounds;
1823 if (ParentID != 0 && ParentID != LocalId)
1824 { 2329 {
1825 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2330 pa.link(parentPa);
1826
1827 if (parentPa != null)
1828 {
1829 pa.link(parentPa);
1830 }
1831 } 2331 }
1832 } 2332 }
1833 } 2333 }
2334 }
2335
2336 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2337 if (pa.Phantom != phan)
2338 pa.Phantom = phan;
2339
2340// some engines dont' have this check still
2341// if (VolumeDetectActive != pa.IsVolumeDtc)
2342 {
2343 if (VolumeDetectActive)
2344 pa.SetVolumeDetect(1);
2345 else
2346 pa.SetVolumeDetect(0);
1834 } 2347 }
1835 2348
1836 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2349 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1949,42 +2462,63 @@ namespace OpenSim.Region.Framework.Scenes
1949 2462
1950 public Vector3 GetGeometricCenter() 2463 public Vector3 GetGeometricCenter()
1951 { 2464 {
2465 // this is not real geometric center but a average of positions relative to root prim acording to
2466 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2467 // ignoring tortured prims details since sl also seems to ignore
2468 // so no real use in doing it on physics
2469 if (ParentGroup.IsDeleted)
2470 return new Vector3(0, 0, 0);
2471
2472 return ParentGroup.GetGeometricCenter();
2473 }
2474
2475 public float GetMass()
2476 {
1952 PhysicsActor pa = PhysActor; 2477 PhysicsActor pa = PhysActor;
1953 2478
1954 if (pa != null) 2479 if (pa != null)
1955 return new Vector3(pa.GeometricCenter.X, pa.GeometricCenter.Y, pa.GeometricCenter.Z); 2480 return pa.Mass;
1956 else 2481 else
1957 return new Vector3(0, 0, 0); 2482 return 0;
1958 } 2483 }
1959 2484
1960 public Vector3 GetCenterOfMass() 2485 public Vector3 GetCenterOfMass()
1961 { 2486 {
2487 if (ParentGroup.RootPart == this)
2488 {
2489 if (ParentGroup.IsDeleted)
2490 return AbsolutePosition;
2491 return ParentGroup.GetCenterOfMass();
2492 }
2493
1962 PhysicsActor pa = PhysActor; 2494 PhysicsActor pa = PhysActor;
1963 2495
1964 if (pa != null) 2496 if (pa != null)
1965 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2497 {
2498 Vector3 tmp = pa.CenterOfMass;
2499 return tmp;
2500 }
1966 else 2501 else
1967 return new Vector3(0, 0, 0); 2502 return AbsolutePosition;
1968 } 2503 }
1969 2504
1970 public float GetMass() 2505 public Vector3 GetPartCenterOfMass()
1971 { 2506 {
1972 PhysicsActor pa = PhysActor; 2507 PhysicsActor pa = PhysActor;
1973 2508
1974 if (pa != null) 2509 if (pa != null)
1975 return pa.Mass; 2510 {
2511 Vector3 tmp = pa.CenterOfMass;
2512 return tmp;
2513 }
1976 else 2514 else
1977 return 0; 2515 return AbsolutePosition;
1978 } 2516 }
1979 2517
2518
1980 public Vector3 GetForce() 2519 public Vector3 GetForce()
1981 { 2520 {
1982 PhysicsActor pa = PhysActor; 2521 return Force;
1983
1984 if (pa != null)
1985 return pa.Force;
1986 else
1987 return Vector3.Zero;
1988 } 2522 }
1989 2523
1990 /// <summary> 2524 /// <summary>
@@ -2199,15 +2733,25 @@ namespace OpenSim.Region.Framework.Scenes
2199 2733
2200 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2734 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2201 { 2735 {
2202 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2736 bool sendToRoot = true;
2203 {
2204 ColliderArgs LandCollidingMessage = new ColliderArgs();
2205 List<DetectedObject> colliding = new List<DetectedObject>();
2206
2207 colliding.Add(CreateDetObjectForGround());
2208 LandCollidingMessage.Colliders = colliding;
2209 2737
2738 ColliderArgs LandCollidingMessage = new ColliderArgs();
2739 List<DetectedObject> colliding = new List<DetectedObject>();
2740
2741 colliding.Add(CreateDetObjectForGround());
2742 LandCollidingMessage.Colliders = colliding;
2743
2744 if (Inventory.ContainsScripts())
2745 {
2746 if (!PassCollisions)
2747 sendToRoot = false;
2748 }
2749 if ((ScriptEvents & ev) != 0)
2210 notify(LocalId, LandCollidingMessage); 2750 notify(LocalId, LandCollidingMessage);
2751
2752 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2753 {
2754 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2211 } 2755 }
2212 } 2756 }
2213 2757
@@ -2223,57 +2767,120 @@ namespace OpenSim.Region.Framework.Scenes
2223 List<uint> endedColliders = new List<uint>(); 2767 List<uint> endedColliders = new List<uint>();
2224 List<uint> startedColliders = new List<uint>(); 2768 List<uint> startedColliders = new List<uint>();
2225 2769
2226 // calculate things that started colliding this time 2770 if (collissionswith.Count == 0)
2227 // and build up list of colliders this time
2228 foreach (uint localid in collissionswith.Keys)
2229 { 2771 {
2230 thisHitColliders.Add(localid); 2772 if (m_lastColliders.Count == 0)
2231 if (!m_lastColliders.Contains(localid)) 2773 return; // nothing to do
2232 startedColliders.Add(localid);
2233 }
2234 2774
2235 // calculate things that ended colliding 2775 foreach (uint localID in m_lastColliders)
2236 foreach (uint localID in m_lastColliders) 2776 {
2237 {
2238 if (!thisHitColliders.Contains(localID))
2239 endedColliders.Add(localID); 2777 endedColliders.Add(localID);
2778 }
2779 m_lastColliders.Clear();
2240 } 2780 }
2241 2781
2242 //add the items that started colliding this time to the last colliders list. 2782 else
2243 foreach (uint localID in startedColliders) 2783 {
2244 m_lastColliders.Add(localID); 2784 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2785
2786 // calculate things that started colliding this time
2787 // and build up list of colliders this time
2788 if (!VolumeDetectActive && CollisionSoundType >= 0)
2789 {
2790 CollisionForSoundInfo soundinfo;
2791 ContactPoint curcontact;
2245 2792
2246 // remove things that ended colliding from the last colliders list 2793 foreach (uint id in collissionswith.Keys)
2247 foreach (uint localID in endedColliders) 2794 {
2248 m_lastColliders.Remove(localID); 2795 thisHitColliders.Add(id);
2796 if (!m_lastColliders.Contains(id))
2797 {
2798 startedColliders.Add(id);
2249 2799
2250 // play the sound. 2800 curcontact = collissionswith[id];
2251 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2801 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2252 { 2802 {
2253 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2803 soundinfo = new CollisionForSoundInfo();
2254 if (soundModule != null) 2804 soundinfo.colliderID = id;
2805 soundinfo.position = curcontact.Position;
2806 soundinfo.relativeVel = curcontact.RelativeSpeed;
2807 soundinfolist.Add(soundinfo);
2808 }
2809 }
2810 }
2811 }
2812 else
2255 { 2813 {
2256 soundModule.SendSound(UUID, CollisionSound, 2814 foreach (uint id in collissionswith.Keys)
2257 CollisionSoundVolume, true, (byte)0, 0, false, 2815 {
2258 false); 2816 thisHitColliders.Add(id);
2817 if (!m_lastColliders.Contains(id))
2818 startedColliders.Add(id);
2819 }
2820 }
2821
2822 // calculate things that ended colliding
2823 foreach (uint localID in m_lastColliders)
2824 {
2825 if (!thisHitColliders.Contains(localID))
2826 endedColliders.Add(localID);
2259 } 2827 }
2828
2829 //add the items that started colliding this time to the last colliders list.
2830 foreach (uint localID in startedColliders)
2831 m_lastColliders.Add(localID);
2832
2833 // remove things that ended colliding from the last colliders list
2834 foreach (uint localID in endedColliders)
2835 m_lastColliders.Remove(localID);
2836
2837 // play sounds.
2838 if (soundinfolist.Count > 0)
2839 CollisionSounds.PartCollisionSound(this, soundinfolist);
2260 } 2840 }
2261 2841
2262 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2842 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2263 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2843 if (!VolumeDetectActive)
2844 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2264 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2845 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2265 2846
2266 if (startedColliders.Contains(0)) 2847 if (startedColliders.Contains(0))
2267 { 2848 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2268 if (m_lastColliders.Contains(0)) 2849 if (m_lastColliders.Contains(0))
2269 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2850 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2270 else
2271 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2272 }
2273 if (endedColliders.Contains(0)) 2851 if (endedColliders.Contains(0))
2274 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2852 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2275 } 2853 }
2276 2854
2855 // The Collision sounds code calls this
2856 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2857 {
2858 if (soundID == UUID.Zero)
2859 return;
2860
2861 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2862 if (soundModule == null)
2863 return;
2864
2865 if (volume > 1)
2866 volume = 1;
2867 if (volume < 0)
2868 volume = 0;
2869
2870 int now = Util.EnvironmentTickCount();
2871 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2872 return;
2873
2874 LastColSoundSentTime = now;
2875
2876 UUID ownerID = OwnerID;
2877 UUID objectID = ParentGroup.RootPart.UUID;
2878 UUID parentID = ParentGroup.UUID;
2879 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2880
2881 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2882 }
2883
2277 public void PhysicsOutOfBounds(Vector3 pos) 2884 public void PhysicsOutOfBounds(Vector3 pos)
2278 { 2885 {
2279 // Note: This is only being called on the root prim at this time. 2886 // Note: This is only being called on the root prim at this time.
@@ -2295,9 +2902,9 @@ namespace OpenSim.Region.Framework.Scenes
2295 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2902 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2296 2903
2297 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2904 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2298 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2905 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2299 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2906 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2300 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2907 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2301 { 2908 {
2302 ParentGroup.AbsolutePosition = newpos; 2909 ParentGroup.AbsolutePosition = newpos;
2303 return; 2910 return;
@@ -2424,6 +3031,19 @@ namespace OpenSim.Region.Framework.Scenes
2424 APIDTarget = Quaternion.Identity; 3031 APIDTarget = Quaternion.Identity;
2425 } 3032 }
2426 3033
3034
3035
3036 public void ScheduleFullUpdateIfNone()
3037 {
3038 if (ParentGroup == null)
3039 return;
3040
3041// ??? ParentGroup.HasGroupChanged = true;
3042
3043 if (UpdateFlag != UpdateRequired.FULL)
3044 ScheduleFullUpdate();
3045 }
3046
2427 /// <summary> 3047 /// <summary>
2428 /// Schedules this prim for a full update 3048 /// Schedules this prim for a full update
2429 /// </summary> 3049 /// </summary>
@@ -2569,6 +3189,14 @@ namespace OpenSim.Region.Framework.Scenes
2569 if (ParentGroup == null) 3189 if (ParentGroup == null)
2570 return; 3190 return;
2571 3191
3192 // Update the "last" values
3193 m_lastPosition = OffsetPosition;
3194 m_lastRotation = RotationOffset;
3195 m_lastVelocity = Velocity;
3196 m_lastAcceleration = Acceleration;
3197 m_lastAngularVelocity = AngularVelocity;
3198 m_lastUpdateSentTime = Environment.TickCount;
3199
2572 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3200 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2573 { 3201 {
2574 SendFullUpdate(avatar.ControllingClient); 3202 SendFullUpdate(avatar.ControllingClient);
@@ -2627,8 +3255,8 @@ namespace OpenSim.Region.Framework.Scenes
2627 { 3255 {
2628 const float ROTATION_TOLERANCE = 0.01f; 3256 const float ROTATION_TOLERANCE = 0.01f;
2629 const float VELOCITY_TOLERANCE = 0.001f; 3257 const float VELOCITY_TOLERANCE = 0.001f;
2630 const float POSITION_TOLERANCE = 0.05f; 3258 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2631 const int TIME_MS_TOLERANCE = 3000; 3259 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2632 3260
2633 switch (UpdateFlag) 3261 switch (UpdateFlag)
2634 { 3262 {
@@ -2642,17 +3270,10 @@ namespace OpenSim.Region.Framework.Scenes
2642 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3270 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2643 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3271 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2644 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3272 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2645 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3273 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2646 { 3274 {
2647 SendTerseUpdateToAllClients(); 3275 SendTerseUpdateToAllClients();
2648 3276
2649 // Update the "last" values
2650 m_lastPosition = OffsetPosition;
2651 m_lastRotation = RotationOffset;
2652 m_lastVelocity = Velocity;
2653 m_lastAcceleration = Acceleration;
2654 m_lastAngularVelocity = AngularVelocity;
2655 m_lastTerseSent = Environment.TickCount;
2656 } 3277 }
2657 break; 3278 break;
2658 } 3279 }
@@ -2670,6 +3291,17 @@ namespace OpenSim.Region.Framework.Scenes
2670 /// </summary> 3291 /// </summary>
2671 public void SendTerseUpdateToAllClients() 3292 public void SendTerseUpdateToAllClients()
2672 { 3293 {
3294 if (ParentGroup == null || ParentGroup.Scene == null)
3295 return;
3296
3297 // Update the "last" values
3298 m_lastPosition = OffsetPosition;
3299 m_lastRotation = RotationOffset;
3300 m_lastVelocity = Velocity;
3301 m_lastAcceleration = Acceleration;
3302 m_lastAngularVelocity = AngularVelocity;
3303 m_lastUpdateSentTime = Environment.TickCount;
3304
2673 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3305 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2674 { 3306 {
2675 SendTerseUpdateToClient(client); 3307 SendTerseUpdateToClient(client);
@@ -2693,10 +3325,13 @@ namespace OpenSim.Region.Framework.Scenes
2693 3325
2694 public void SetBuoyancy(float fvalue) 3326 public void SetBuoyancy(float fvalue)
2695 { 3327 {
2696 PhysicsActor pa = PhysActor; 3328 Buoyancy = fvalue;
2697 3329/*
2698 if (pa != null) 3330 if (PhysActor != null)
2699 pa.Buoyancy = fvalue; 3331 {
3332 PhysActor.Buoyancy = fvalue;
3333 }
3334 */
2700 } 3335 }
2701 3336
2702 public void SetDieAtEdge(bool p) 3337 public void SetDieAtEdge(bool p)
@@ -2712,47 +3347,111 @@ namespace OpenSim.Region.Framework.Scenes
2712 PhysicsActor pa = PhysActor; 3347 PhysicsActor pa = PhysActor;
2713 3348
2714 if (pa != null) 3349 if (pa != null)
2715 pa.FloatOnWater = floatYN == 1; 3350 pa.FloatOnWater = (floatYN == 1);
2716 } 3351 }
2717 3352
2718 public void SetForce(Vector3 force) 3353 public void SetForce(Vector3 force)
2719 { 3354 {
2720 PhysicsActor pa = PhysActor; 3355 Force = force;
3356 }
2721 3357
2722 if (pa != null) 3358 public SOPVehicle VehicleParams
2723 pa.Force = force; 3359 {
3360 get
3361 {
3362 return m_vehicleParams;
3363 }
3364 set
3365 {
3366 m_vehicleParams = value;
3367 }
3368 }
3369
3370
3371 public int VehicleType
3372 {
3373 get
3374 {
3375 if (m_vehicleParams == null)
3376 return (int)Vehicle.TYPE_NONE;
3377 else
3378 return (int)m_vehicleParams.Type;
3379 }
3380 set
3381 {
3382 SetVehicleType(value);
3383 }
2724 } 3384 }
2725 3385
2726 public void SetVehicleType(int type) 3386 public void SetVehicleType(int type)
2727 { 3387 {
2728 PhysicsActor pa = PhysActor; 3388 m_vehicleParams = null;
3389
3390 if (type == (int)Vehicle.TYPE_NONE)
3391 {
3392 if (_parentID ==0 && PhysActor != null)
3393 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3394 return;
3395 }
3396 m_vehicleParams = new SOPVehicle();
3397 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3398 {
3399 if (_parentID ==0 && PhysActor != null)
3400 PhysActor.VehicleType = type;
3401 return;
3402 }
3403 }
2729 3404
2730 if (pa != null) 3405 public void SetVehicleFlags(int param, bool remove)
2731 pa.VehicleType = type; 3406 {
3407 if (m_vehicleParams == null)
3408 return;
3409
3410 m_vehicleParams.ProcessVehicleFlags(param, remove);
3411
3412 if (_parentID ==0 && PhysActor != null)
3413 {
3414 PhysActor.VehicleFlags(param, remove);
3415 }
2732 } 3416 }
2733 3417
2734 public void SetVehicleFloatParam(int param, float value) 3418 public void SetVehicleFloatParam(int param, float value)
2735 { 3419 {
2736 PhysicsActor pa = PhysActor; 3420 if (m_vehicleParams == null)
3421 return;
2737 3422
2738 if (pa != null) 3423 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
2739 pa.VehicleFloatParam(param, value); 3424
3425 if (_parentID == 0 && PhysActor != null)
3426 {
3427 PhysActor.VehicleFloatParam(param, value);
3428 }
2740 } 3429 }
2741 3430
2742 public void SetVehicleVectorParam(int param, Vector3 value) 3431 public void SetVehicleVectorParam(int param, Vector3 value)
2743 { 3432 {
2744 PhysicsActor pa = PhysActor; 3433 if (m_vehicleParams == null)
3434 return;
2745 3435
2746 if (pa != null) 3436 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
2747 pa.VehicleVectorParam(param, value); 3437
3438 if (_parentID == 0 && PhysActor != null)
3439 {
3440 PhysActor.VehicleVectorParam(param, value);
3441 }
2748 } 3442 }
2749 3443
2750 public void SetVehicleRotationParam(int param, Quaternion rotation) 3444 public void SetVehicleRotationParam(int param, Quaternion rotation)
2751 { 3445 {
2752 PhysicsActor pa = PhysActor; 3446 if (m_vehicleParams == null)
3447 return;
2753 3448
2754 if (pa != null) 3449 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
2755 pa.VehicleRotationParam(param, rotation); 3450
3451 if (_parentID == 0 && PhysActor != null)
3452 {
3453 PhysActor.VehicleRotationParam(param, rotation);
3454 }
2756 } 3455 }
2757 3456
2758 /// <summary> 3457 /// <summary>
@@ -2953,14 +3652,6 @@ namespace OpenSim.Region.Framework.Scenes
2953 hasProfileCut = hasDimple; // is it the same thing? 3652 hasProfileCut = hasDimple; // is it the same thing?
2954 } 3653 }
2955 3654
2956 public void SetVehicleFlags(int param, bool remove)
2957 {
2958 PhysicsActor pa = PhysActor;
2959
2960 if (pa != null)
2961 pa.VehicleFlags(param, remove);
2962 }
2963
2964 public void SetGroup(UUID groupID, IClientAPI client) 3655 public void SetGroup(UUID groupID, IClientAPI client)
2965 { 3656 {
2966 // Scene.AddNewPrims() calls with client == null so can't use this. 3657 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3060,71 +3751,20 @@ namespace OpenSim.Region.Framework.Scenes
3060 { 3751 {
3061 ParentGroup.stopMoveToTarget(); 3752 ParentGroup.stopMoveToTarget();
3062 3753
3063 ParentGroup.ScheduleGroupForTerseUpdate(); 3754// ParentGroup.ScheduleGroupForTerseUpdate();
3064 //ParentGroup.ScheduleGroupForFullUpdate(); 3755 //ParentGroup.ScheduleGroupForFullUpdate();
3065 } 3756 }
3066 3757
3067 public void StoreUndoState() 3758 public void StoreUndoState(ObjectChangeType change)
3068 {
3069 StoreUndoState(false);
3070 }
3071
3072 public void StoreUndoState(bool forGroup)
3073 { 3759 {
3074 if (ParentGroup == null || ParentGroup.Scene == null) 3760 if (m_UndoRedo == null)
3075 return; 3761 m_UndoRedo = new UndoRedoState(5);
3076
3077 if (Undoing)
3078 {
3079// m_log.DebugFormat(
3080// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3081 return;
3082 }
3083
3084 if (IgnoreUndoUpdate)
3085 {
3086// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3087 return;
3088 }
3089 3762
3090 lock (m_undo) 3763 lock (m_UndoRedo)
3091 { 3764 {
3092 if (m_undo.Count > 0) 3765 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3093 {
3094 UndoState last = m_undo[m_undo.Count - 1];
3095 if (last != null)
3096 {
3097 // TODO: May need to fix for group comparison
3098 if (last.Compare(this))
3099 {
3100// m_log.DebugFormat(
3101// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3102// Name, LocalId, m_undo.Count);
3103
3104 return;
3105 }
3106 }
3107 }
3108
3109// m_log.DebugFormat(
3110// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3111// Name, LocalId, forGroup, m_undo.Count);
3112
3113 if (ParentGroup.Scene.MaxUndoCount > 0)
3114 { 3766 {
3115 UndoState nUndo = new UndoState(this, forGroup); 3767 m_UndoRedo.StoreUndo(this, change);
3116
3117 m_undo.Add(nUndo);
3118
3119 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3120 m_undo.RemoveAt(0);
3121
3122 if (m_redo.Count > 0)
3123 m_redo.Clear();
3124
3125// m_log.DebugFormat(
3126// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3127// Name, LocalId, forGroup, m_undo.Count);
3128 } 3768 }
3129 } 3769 }
3130 } 3770 }
@@ -3136,88 +3776,46 @@ namespace OpenSim.Region.Framework.Scenes
3136 { 3776 {
3137 get 3777 get
3138 { 3778 {
3139 lock (m_undo) 3779 if (m_UndoRedo == null)
3140 return m_undo.Count; 3780 return 0;
3781 return m_UndoRedo.Count;
3141 } 3782 }
3142 } 3783 }
3143 3784
3144 public void Undo() 3785 public void Undo()
3145 { 3786 {
3146 lock (m_undo) 3787 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3147 { 3788 return;
3148// m_log.DebugFormat(
3149// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3150// Name, LocalId, m_undo.Count);
3151
3152 if (m_undo.Count > 0)
3153 {
3154 UndoState goback = m_undo[m_undo.Count - 1];
3155 m_undo.RemoveAt(m_undo.Count - 1);
3156
3157 UndoState nUndo = null;
3158
3159 if (ParentGroup.Scene.MaxUndoCount > 0)
3160 {
3161 nUndo = new UndoState(this, goback.ForGroup);
3162 }
3163
3164 goback.PlaybackState(this);
3165
3166 if (nUndo != null)
3167 {
3168 m_redo.Add(nUndo);
3169
3170 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3171 m_redo.RemoveAt(0);
3172 }
3173 }
3174 3789
3175// m_log.DebugFormat( 3790 lock (m_UndoRedo)
3176// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3791 {
3177// Name, LocalId, m_undo.Count); 3792 Undoing = true;
3793 m_UndoRedo.Undo(this);
3794 Undoing = false;
3178 } 3795 }
3179 } 3796 }
3180 3797
3181 public void Redo() 3798 public void Redo()
3182 { 3799 {
3183 lock (m_undo) 3800 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3184 { 3801 return;
3185// m_log.DebugFormat(
3186// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3187// Name, LocalId, m_redo.Count);
3188
3189 if (m_redo.Count > 0)
3190 {
3191 UndoState gofwd = m_redo[m_redo.Count - 1];
3192 m_redo.RemoveAt(m_redo.Count - 1);
3193
3194 if (ParentGroup.Scene.MaxUndoCount > 0)
3195 {
3196 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3197
3198 m_undo.Add(nUndo);
3199
3200 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3201 m_undo.RemoveAt(0);
3202 }
3203
3204 gofwd.PlayfwdState(this);
3205 3802
3206// m_log.DebugFormat( 3803 lock (m_UndoRedo)
3207// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3804 {
3208// Name, LocalId, m_redo.Count); 3805 Undoing = true;
3209 } 3806 m_UndoRedo.Redo(this);
3807 Undoing = false;
3210 } 3808 }
3211 } 3809 }
3212 3810
3213 public void ClearUndoState() 3811 public void ClearUndoState()
3214 { 3812 {
3215// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3813 if (m_UndoRedo == null || Undoing)
3814 return;
3216 3815
3217 lock (m_undo) 3816 lock (m_UndoRedo)
3218 { 3817 {
3219 m_undo.Clear(); 3818 m_UndoRedo.Clear();
3220 m_redo.Clear();
3221 } 3819 }
3222 } 3820 }
3223 3821
@@ -3767,7 +4365,7 @@ namespace OpenSim.Region.Framework.Scenes
3767 if (god) 4365 if (god)
3768 { 4366 {
3769 BaseMask = ApplyMask(BaseMask, set, mask); 4367 BaseMask = ApplyMask(BaseMask, set, mask);
3770 Inventory.ApplyGodPermissions(_baseMask); 4368 Inventory.ApplyGodPermissions(BaseMask);
3771 } 4369 }
3772 4370
3773 break; 4371 break;
@@ -3786,7 +4384,7 @@ namespace OpenSim.Region.Framework.Scenes
3786 case 16: 4384 case 16:
3787 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4385 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
3788 baseMask; 4386 baseMask;
3789 // Prevent the client from creating no mod, no copy 4387 // Prevent the client from creating no copy, no transfer
3790 // objects 4388 // objects
3791 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4389 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
3792 NextOwnerMask |= (uint)PermissionMask.Transfer; 4390 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -3804,20 +4402,20 @@ namespace OpenSim.Region.Framework.Scenes
3804 { 4402 {
3805 bool update = false; 4403 bool update = false;
3806 4404
3807 if (BaseMask != source.BaseMask || 4405 uint prevOwnerMask = OwnerMask;
3808 OwnerMask != source.OwnerMask || 4406 uint prevGroupMask = GroupMask;
3809 GroupMask != source.GroupMask || 4407 uint prevEveryoneMask = EveryoneMask;
3810 EveryoneMask != source.EveryoneMask || 4408 uint prevNextOwnerMask = NextOwnerMask;
3811 NextOwnerMask != source.NextOwnerMask)
3812 update = true;
3813 4409
3814 BaseMask = source.BaseMask; 4410 OwnerMask = source.OwnerMask & BaseMask;
3815 OwnerMask = source.OwnerMask; 4411 GroupMask = source.GroupMask & BaseMask;
3816 GroupMask = source.GroupMask; 4412 EveryoneMask = source.EveryoneMask & BaseMask;
3817 EveryoneMask = source.EveryoneMask; 4413 NextOwnerMask = source.NextOwnerMask & BaseMask;
3818 NextOwnerMask = source.NextOwnerMask;
3819 4414
3820 if (update) 4415 if (OwnerMask != prevOwnerMask ||
4416 GroupMask != prevGroupMask ||
4417 EveryoneMask != prevEveryoneMask ||
4418 NextOwnerMask != prevNextOwnerMask)
3821 SendFullUpdateToAllClients(); 4419 SendFullUpdateToAllClients();
3822 } 4420 }
3823 4421
@@ -3868,6 +4466,27 @@ namespace OpenSim.Region.Framework.Scenes
3868 } 4466 }
3869 } 4467 }
3870 4468
4469
4470 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4471 {
4472 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4473 return;
4474
4475 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4476 {
4477 PhysicsShapeType = (byte)physdata.PhysShapeType;
4478
4479 }
4480
4481 if(Density != physdata.Density)
4482 Density = physdata.Density;
4483 if(GravityModifier != physdata.GravitationModifier)
4484 GravityModifier = physdata.GravitationModifier;
4485 if(Friction != physdata.Friction)
4486 Friction = physdata.Friction;
4487 if(Bounciness != physdata.Bounce)
4488 Bounciness = physdata.Bounce;
4489 }
3871 /// <summary> 4490 /// <summary>
3872 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4491 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3873 /// </summary> 4492 /// </summary>
@@ -3875,7 +4494,7 @@ namespace OpenSim.Region.Framework.Scenes
3875 /// <param name="SetTemporary"></param> 4494 /// <param name="SetTemporary"></param>
3876 /// <param name="SetPhantom"></param> 4495 /// <param name="SetPhantom"></param>
3877 /// <param name="SetVD"></param> 4496 /// <param name="SetVD"></param>
3878 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4497 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3879 { 4498 {
3880 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4499 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3881 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4500 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3885,214 +4504,230 @@ namespace OpenSim.Region.Framework.Scenes
3885 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4504 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3886 return; 4505 return;
3887 4506
3888 PhysicsActor pa = PhysActor; 4507 VolumeDetectActive = SetVD;
3889
3890 // Special cases for VD. VD can only be called from a script
3891 // and can't be combined with changes to other states. So we can rely
3892 // that...
3893 // ... if VD is changed, all others are not.
3894 // ... if one of the others is changed, VD is not.
3895 if (SetVD) // VD is active, special logic applies
3896 {
3897 // State machine logic for VolumeDetect
3898 // More logic below
3899 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3900
3901 if (phanReset) // Phantom changes from on to off switch VD off too
3902 {
3903 SetVD = false; // Switch it of for the course of this routine
3904 VolumeDetectActive = false; // and also permanently
3905
3906 if (pa != null)
3907 pa.SetVolumeDetect(0); // Let physics know about it too
3908 }
3909 else
3910 {
3911 // If volumedetect is active we don't want phantom to be applied.
3912 // If this is a new call to VD out of the state "phantom"
3913 // this will also cause the prim to be visible to physics
3914 SetPhantom = false;
3915 }
3916 }
3917 4508
3918 if (UsePhysics && IsJoint()) 4509 // volume detector implies phantom
3919 { 4510 if (VolumeDetectActive)
3920 SetPhantom = true; 4511 SetPhantom = true;
3921 }
3922 4512
3923 if (UsePhysics) 4513 if (UsePhysics)
3924 {
3925 AddFlag(PrimFlags.Physics); 4514 AddFlag(PrimFlags.Physics);
3926 if (!wasUsingPhysics)
3927 {
3928 DoPhysicsPropertyUpdate(UsePhysics, false);
3929 }
3930 }
3931 else 4515 else
3932 {
3933 RemFlag(PrimFlags.Physics); 4516 RemFlag(PrimFlags.Physics);
3934 if (wasUsingPhysics)
3935 {
3936 DoPhysicsPropertyUpdate(UsePhysics, false);
3937 }
3938 }
3939 4517
3940 if (SetPhantom 4518 if (SetPhantom)
3941 || ParentGroup.IsAttachment
3942 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3943 {
3944 AddFlag(PrimFlags.Phantom); 4519 AddFlag(PrimFlags.Phantom);
3945 4520 else
3946 if (PhysActor != null)
3947 {
3948 RemoveFromPhysics();
3949 pa = null;
3950 }
3951 }
3952 else // Not phantom
3953 {
3954 RemFlag(PrimFlags.Phantom); 4521 RemFlag(PrimFlags.Phantom);
3955 4522
3956 if (ParentGroup.Scene == null) 4523 if (SetTemporary)
3957 return; 4524 AddFlag(PrimFlags.TemporaryOnRez);
4525 else
4526 RemFlag(PrimFlags.TemporaryOnRez);
3958 4527
3959 if (ParentGroup.Scene.CollidablePrims && pa == null)
3960 {
3961 pa = AddToPhysics(UsePhysics);
3962 4528
3963 if (pa != null) 4529 if (ParentGroup.Scene == null)
3964 { 4530 return;
3965 pa.SetMaterial(Material); 4531
3966 DoPhysicsPropertyUpdate(UsePhysics, true); 4532 PhysicsActor pa = PhysActor;
3967
3968 if (
3969 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
3970 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3971 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3972 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
3973 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
3974 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
3975 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
3976 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3977 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3978 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
3979 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
3980 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
3981 (CollisionSound != UUID.Zero)
3982 )
3983 {
3984 pa.OnCollisionUpdate += PhysicsCollision;
3985 pa.SubscribeEvents(1000);
3986 }
3987 }
3988 }
3989 else // it already has a physical representation
3990 {
3991 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
3992 }
3993 }
3994 4533
3995 if (SetVD) 4534 if (pa != null && building && pa.Building != building)
4535 pa.Building = building;
4536
4537 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4538 || (Shape.PathCurve == (byte)Extrusion.Flexible))
3996 { 4539 {
3997 // If the above logic worked (this is urgent candidate to unit tests!)
3998 // we now have a physicsactor.
3999 // Defensive programming calls for a check here.
4000 // Better would be throwing an exception that could be catched by a unit test as the internal
4001 // logic should make sure, this Physactor is always here.
4002 if (pa != null) 4540 if (pa != null)
4003 { 4541 {
4004 pa.SetVolumeDetect(1); 4542 if(wasUsingPhysics)
4005 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4543 ParentGroup.Scene.RemovePhysicalPrim(1);
4006 VolumeDetectActive = true; 4544 RemoveFromPhysics();
4007 } 4545 }
4546
4547 Velocity = new Vector3(0, 0, 0);
4548 Acceleration = new Vector3(0, 0, 0);
4549 if (ParentGroup.RootPart == this)
4550 AngularVelocity = new Vector3(0, 0, 0);
4008 } 4551 }
4009 else if (SetVD != wasVD) 4552 else if (SetVD != wasVD)
4010 { 4553 {
4011 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4554 if (ParentGroup.Scene.CollidablePrims)
4012 // (mumbles, well, at least if you have infinte CPU powers :-)) 4555 {
4013 if (pa != null) 4556 if (pa == null)
4014 pa.SetVolumeDetect(0); 4557 {
4558 AddToPhysics(UsePhysics, SetPhantom, building, false);
4559 pa = PhysActor;
4560/*
4561 if (pa != null)
4562 {
4563 if (
4564// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4565// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4566// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4567// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4568// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4569// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4570 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4571 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4572 (CollisionSound != UUID.Zero)
4573 )
4574 {
4575 pa.OnCollisionUpdate += PhysicsCollision;
4576 pa.SubscribeEvents(1000);
4577 }
4578 }
4579*/
4580 }
4581 else // it already has a physical representation
4582 {
4583 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4584/* moved into DoPhysicsPropertyUpdate
4585 if(VolumeDetectActive)
4586 pa.SetVolumeDetect(1);
4587 else
4588 pa.SetVolumeDetect(0);
4589*/
4015 4590
4016 RemFlag(PrimFlags.Phantom); 4591 if (pa.Building != building)
4017 VolumeDetectActive = false; 4592 pa.Building = building;
4018 } 4593 }
4019 4594
4020 if (SetTemporary) 4595 UpdatePhysicsSubscribedEvents();
4021 { 4596 }
4022 AddFlag(PrimFlags.TemporaryOnRez); 4597 }
4023 }
4024 else
4025 {
4026 RemFlag(PrimFlags.TemporaryOnRez);
4027 }
4028 4598
4029 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4599 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4030 4600
4601 // and last in case we have a new actor and not building
4602
4031 if (ParentGroup != null) 4603 if (ParentGroup != null)
4032 { 4604 {
4033 ParentGroup.HasGroupChanged = true; 4605 ParentGroup.HasGroupChanged = true;
4034 ScheduleFullUpdate(); 4606 ScheduleFullUpdate();
4035 } 4607 }
4036 4608
4037// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4609// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4038 } 4610 }
4039 4611
4040 /// <summary> 4612 /// <summary>
4041 /// Adds this part to the physics scene. 4613 /// Adds this part to the physics scene.
4614 /// and sets the PhysActor property
4042 /// </summary> 4615 /// </summary>
4043 /// <remarks>This method also sets the PhysActor property.</remarks> 4616 /// <param name="isPhysical">Add this prim as physical.</param>
4044 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4617 /// <param name="isPhantom">Add this prim as phantom.</param>
4045 /// <returns> 4618 /// <param name="building">tells physics to delay full construction of object</param>
4046 /// The physics actor. null if there was a failure. 4619 /// <param name="applyDynamics">applies velocities, force and torque</param>
4047 /// </returns> 4620 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4048 private PhysicsActor AddToPhysics(bool rigidBody) 4621 {
4049 {
4050 PhysicsActor pa; 4622 PhysicsActor pa;
4051 4623
4624 Vector3 velocity = Velocity;
4625 Vector3 rotationalVelocity = AngularVelocity;;
4626
4052 try 4627 try
4053 { 4628 {
4054 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4629 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4055 string.Format("{0}/{1}", Name, UUID), 4630 string.Format("{0}/{1}", Name, UUID),
4056 Shape, 4631 Shape,
4057 AbsolutePosition, 4632 AbsolutePosition,
4058 Scale, 4633 Scale,
4059 RotationOffset, 4634 GetWorldRotation(),
4060 rigidBody, 4635 isPhysical,
4061 m_localId); 4636 isPhantom,
4637 PhysicsShapeType,
4638 m_localId);
4062 } 4639 }
4063 catch (Exception e) 4640 catch (Exception e)
4064 { 4641 {
4065 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e); 4642 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4066 pa = null; 4643 pa = null;
4067 } 4644 }
4068 4645
4069 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4070 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4071 // being set.
4072 PhysActor = pa;
4073
4074 // Basic Physics can also return null as well as an exception catch.
4075 if (pa != null) 4646 if (pa != null)
4076 { 4647 {
4077 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4648 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4078 pa.SetMaterial(Material); 4649 pa.SetMaterial(Material);
4079 DoPhysicsPropertyUpdate(rigidBody, true); 4650
4651 if (VolumeDetectActive) // change if not the default only
4652 pa.SetVolumeDetect(1);
4653
4654 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4655 m_vehicleParams.SetVehicle(pa);
4656
4657 // we are going to tell rest of code about physics so better have this here
4658 PhysActor = pa;
4659
4660 // DoPhysicsPropertyUpdate(isPhysical, true);
4661 // lets expand it here just with what it really needs to do
4662
4663 if (isPhysical)
4664 {
4665 if (ParentGroup.RootPart.KeyframeMotion != null)
4666 ParentGroup.RootPart.KeyframeMotion.Stop();
4667 ParentGroup.RootPart.KeyframeMotion = null;
4668 ParentGroup.Scene.AddPhysicalPrim(1);
4669
4670 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4671 pa.OnOutOfBounds += PhysicsOutOfBounds;
4672
4673 if (ParentID != 0 && ParentID != LocalId)
4674 {
4675 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4676
4677 if (parentPa != null)
4678 {
4679 pa.link(parentPa);
4680 }
4681 }
4682 }
4683
4684 if (applyDynamics)
4685 // do independent of isphysical so parameters get setted (at least some)
4686 {
4687 Velocity = velocity;
4688 AngularVelocity = rotationalVelocity;
4689// pa.Velocity = velocity;
4690 pa.RotationalVelocity = rotationalVelocity;
4691
4692 // if not vehicle and root part apply force and torque
4693 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4694 && LocalId == ParentGroup.RootPart.LocalId)
4695 {
4696 pa.Force = Force;
4697 pa.Torque = Torque;
4698 }
4699 }
4700
4701// if (Shape.SculptEntry)
4702// CheckSculptAndLoad();
4703// else
4704 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4705
4706 if (!building)
4707 pa.Building = false;
4080 } 4708 }
4081 4709
4082 return pa; 4710 PhysActor = pa;
4083 } 4711 }
4084 4712
4085 /// <summary> 4713 /// <summary>
4086 /// This removes the part from the physics scene. 4714 /// This removes the part from the physics scene.
4087 /// </summary> 4715 /// </summary>
4088 /// <remarks> 4716 /// <remarks>
4089 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4717 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4090 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4718 /// representation for collision detection.
4091 /// phantom.
4092 /// </remarks> 4719 /// </remarks>
4093 public void RemoveFromPhysics() 4720 public void RemoveFromPhysics()
4094 { 4721 {
4095 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4722 PhysicsActor pa = PhysActor;
4723 if (pa != null)
4724 {
4725 pa.OnCollisionUpdate -= PhysicsCollision;
4726 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4727 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4728
4729 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4730 }
4096 PhysActor = null; 4731 PhysActor = null;
4097 } 4732 }
4098 4733
@@ -4224,6 +4859,8 @@ namespace OpenSim.Region.Framework.Scenes
4224 { 4859 {
4225// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 4860// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4226 4861
4862 return;
4863
4227 if (ParentGroup.IsDeleted) 4864 if (ParentGroup.IsDeleted)
4228 return; 4865 return;
4229 4866
@@ -4304,6 +4941,44 @@ namespace OpenSim.Region.Framework.Scenes
4304 ScheduleFullUpdate(); 4941 ScheduleFullUpdate();
4305 } 4942 }
4306 4943
4944
4945 private void UpdatePhysicsSubscribedEvents()
4946 {
4947 PhysicsActor pa = PhysActor;
4948 if (pa == null)
4949 return;
4950
4951 pa.OnCollisionUpdate -= PhysicsCollision;
4952
4953 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
4954
4955 scriptEvents CombinedEvents = AggregateScriptEvents;
4956
4957 // merge with root part
4958 if (ParentGroup != null && ParentGroup.RootPart != null)
4959 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4960
4961 // submit to this part case
4962 if (VolumeDetectActive)
4963 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4964 else if ((Flags & PrimFlags.Phantom) != 0)
4965 CombinedEvents &= PhyscicsPhantonSubsEvents;
4966 else
4967 CombinedEvents &= PhysicsNeededSubsEvents;
4968
4969 if (hassound || CombinedEvents != 0)
4970 {
4971 // subscribe to physics updates.
4972 pa.OnCollisionUpdate += PhysicsCollision;
4973 pa.SubscribeEvents(50); // 20 reports per second
4974 }
4975 else
4976 {
4977 pa.UnSubscribeEvents();
4978 }
4979 }
4980
4981
4307 public void aggregateScriptEvents() 4982 public void aggregateScriptEvents()
4308 { 4983 {
4309 if (ParentGroup == null || ParentGroup.RootPart == null) 4984 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4340,40 +5015,32 @@ namespace OpenSim.Region.Framework.Scenes
4340 { 5015 {
4341 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5016 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4342 } 5017 }
4343 5018/*
4344 PhysicsActor pa = PhysActor; 5019 PhysicsActor pa = PhysActor;
4345 5020 if (pa != null)
4346 if (
4347 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4348 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4349 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4350 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4351 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4352 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4353 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4354 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4355 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4356 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4357 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4358 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4359 (CollisionSound != UUID.Zero)
4360 )
4361 { 5021 {
4362 // subscribe to physics updates. 5022 if (
4363 if (pa != null) 5023// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5024// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5025// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5026// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5027// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5028// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5029 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5030 )
4364 { 5031 {
5032 // subscribe to physics updates.
4365 pa.OnCollisionUpdate += PhysicsCollision; 5033 pa.OnCollisionUpdate += PhysicsCollision;
4366 pa.SubscribeEvents(1000); 5034 pa.SubscribeEvents(1000);
4367 } 5035 }
4368 } 5036 else
4369 else
4370 {
4371 if (pa != null)
4372 { 5037 {
4373 pa.UnSubscribeEvents(); 5038 pa.UnSubscribeEvents();
4374 pa.OnCollisionUpdate -= PhysicsCollision; 5039 pa.OnCollisionUpdate -= PhysicsCollision;
4375 } 5040 }
4376 } 5041 }
5042 */
5043 UpdatePhysicsSubscribedEvents();
4377 5044
4378 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5045 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4379 //{ 5046 //{
@@ -4504,6 +5171,18 @@ namespace OpenSim.Region.Framework.Scenes
4504 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5171 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4505 } 5172 }
4506 5173
5174 public void ResetOwnerChangeFlag()
5175 {
5176 List<UUID> inv = Inventory.GetInventoryList();
5177
5178 foreach (UUID itemID in inv)
5179 {
5180 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5181 item.OwnerChanged = false;
5182 Inventory.UpdateInventoryItem(item, false, false);
5183 }
5184 }
5185
4507 /// <summary> 5186 /// <summary>
4508 /// Record an avatar sitting on this part. 5187 /// Record an avatar sitting on this part.
4509 /// </summary> 5188 /// </summary>
@@ -4597,4 +5276,4 @@ namespace OpenSim.Region.Framework.Scenes
4597 } 5276 }
4598 } 5277 }
4599 } 5278 }
4600} \ No newline at end of file 5279}