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.cs1722
1 files changed, 1196 insertions, 526 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 3f10b34..a31a9ea 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>
@@ -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;
@@ -296,7 +320,19 @@ namespace OpenSim.Region.Framework.Scenes
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_lastTerseSent;
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)
@@ -769,7 +816,22 @@ namespace OpenSim.Region.Framework.Scenes
769 if (ParentGroup.Scene != null) 816 if (ParentGroup.Scene != 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,319 @@ 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.Cost;
1587
1588 if ((Flags & PrimFlags.Physics) != 0)
1589 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1590 return cost;
1591 }
1592 }
1593
1594 [XmlIgnore]
1595 public float StreamingCost
1596 {
1597 get
1598 {
1599
1600
1601 return 0.1f;
1602 }
1603 }
1604
1605 [XmlIgnore]
1606 public float SimulationCost
1607 {
1608 get
1609 {
1610 // ignoring scripts. Don't like considering them for this
1611 if((Flags & PrimFlags.Physics) != 0)
1612 return 1.0f;
1613
1614 return 0.5f;
1615 }
1616 }
1617
1618 public byte PhysicsShapeType
1619 {
1620 get { return m_physicsShapeType; }
1621 set
1622 {
1623 byte oldv = m_physicsShapeType;
1624
1625 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1626 {
1627 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1628 m_physicsShapeType = DefaultPhysicsShapeType();
1629 else
1630 m_physicsShapeType = value;
1631 }
1632 else
1633 m_physicsShapeType = DefaultPhysicsShapeType();
1634
1635 if (m_physicsShapeType != oldv && ParentGroup != null)
1636 {
1637 if (m_physicsShapeType == (byte)PhysShapeType.none)
1638 {
1639 if (PhysActor != null)
1640 {
1641 Velocity = new Vector3(0, 0, 0);
1642 Acceleration = new Vector3(0, 0, 0);
1643 if (ParentGroup.RootPart == this)
1644 AngularVelocity = new Vector3(0, 0, 0);
1645 ParentGroup.Scene.RemovePhysicalPrim(1);
1646 RemoveFromPhysics();
1647 }
1648 }
1649 else if (PhysActor == null)
1650 {
1651 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1652 UpdatePhysicsSubscribedEvents();
1653 }
1654 else
1655 {
1656 PhysActor.PhysicsShapeType = m_physicsShapeType;
1657 if (Shape.SculptEntry)
1658 CheckSculptAndLoad();
1659 }
1660
1661 if (ParentGroup != null)
1662 ParentGroup.HasGroupChanged = true;
1663 }
1664
1665 if (m_physicsShapeType != value)
1666 {
1667 UpdatePhysRequired = true;
1668 }
1669 }
1670 }
1671
1672 public float Density // in kg/m^3
1673 {
1674 get { return m_density; }
1675 set
1676 {
1677 if (value >=1 && value <= 22587.0)
1678 {
1679 m_density = value;
1680 UpdatePhysRequired = true;
1681 }
1682
1683 ScheduleFullUpdateIfNone();
1684
1685 if (ParentGroup != null)
1686 ParentGroup.HasGroupChanged = true;
1687 }
1688 }
1689
1690 public float GravityModifier
1691 {
1692 get { return m_gravitymod; }
1693 set
1694 {
1695 if( value >= -1 && value <=28.0f)
1696 {
1697 m_gravitymod = value;
1698 UpdatePhysRequired = true;
1699 }
1700
1701 ScheduleFullUpdateIfNone();
1702
1703 if (ParentGroup != null)
1704 ParentGroup.HasGroupChanged = true;
1705
1706 }
1707 }
1708
1709 public float Friction
1710 {
1711 get { return m_friction; }
1712 set
1713 {
1714 if (value >= 0 && value <= 255.0f)
1715 {
1716 m_friction = value;
1717 UpdatePhysRequired = true;
1718 }
1719
1720 ScheduleFullUpdateIfNone();
1721
1722 if (ParentGroup != null)
1723 ParentGroup.HasGroupChanged = true;
1724 }
1725 }
1726
1727 public float Bounciness
1728 {
1729 get { return m_bounce; }
1730 set
1731 {
1732 if (value >= 0 && value <= 1.0f)
1733 {
1734 m_bounce = value;
1735 UpdatePhysRequired = true;
1736 }
1737
1738 ScheduleFullUpdateIfNone();
1739
1740 if (ParentGroup != null)
1741 ParentGroup.HasGroupChanged = true;
1742 }
1743 }
1744
1745
1318 #endregion Public Properties with only Get 1746 #endregion Public Properties with only Get
1319 1747
1320 private uint ApplyMask(uint val, bool set, uint mask) 1748 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1460,6 +1888,61 @@ namespace OpenSim.Region.Framework.Scenes
1460 } 1888 }
1461 } 1889 }
1462 1890
1891 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1892 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1893 {
1894 if (ParentGroup == null || ParentGroup.IsDeleted)
1895 return;
1896
1897 if (ParentGroup.IsAttachment)
1898 return; // don't work on attachments (for now ??)
1899
1900 SceneObjectPart root = ParentGroup.RootPart;
1901
1902 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
1903 return;
1904
1905 PhysicsActor pa = root.PhysActor;
1906
1907 if (pa == null || !pa.IsPhysical)
1908 return;
1909
1910 if (localGlobalTF)
1911 {
1912 pVel = pVel * GetWorldRotation();
1913 }
1914
1915 ParentGroup.Velocity = pVel;
1916 }
1917
1918 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
1919 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
1920 {
1921 if (ParentGroup == null || ParentGroup.IsDeleted)
1922 return;
1923
1924 if (ParentGroup.IsAttachment)
1925 return; // don't work on attachments (for now ??)
1926
1927 SceneObjectPart root = ParentGroup.RootPart;
1928
1929 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
1930 return;
1931
1932 PhysicsActor pa = root.PhysActor;
1933
1934 if (pa == null || !pa.IsPhysical)
1935 return;
1936
1937 if (localGlobalTF)
1938 {
1939 pAngVel = pAngVel * GetWorldRotation();
1940 }
1941
1942 root.AngularVelocity = pAngVel;
1943 }
1944
1945
1463 /// <summary> 1946 /// <summary>
1464 /// hook to the physics scene to apply angular impulse 1947 /// hook to the physics scene to apply angular impulse
1465 /// This is sent up to the group, which then finds the root prim 1948 /// This is sent up to the group, which then finds the root prim
@@ -1480,7 +1963,7 @@ namespace OpenSim.Region.Framework.Scenes
1480 impulse = newimpulse; 1963 impulse = newimpulse;
1481 } 1964 }
1482 1965
1483 ParentGroup.applyAngularImpulse(impulse); 1966 ParentGroup.ApplyAngularImpulse(impulse);
1484 } 1967 }
1485 1968
1486 /// <summary> 1969 /// <summary>
@@ -1490,20 +1973,24 @@ namespace OpenSim.Region.Framework.Scenes
1490 /// </summary> 1973 /// </summary>
1491 /// <param name="impulsei">Vector force</param> 1974 /// <param name="impulsei">Vector force</param>
1492 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1975 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1493 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1976
1977 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1978 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1494 { 1979 {
1495 Vector3 impulse = impulsei; 1980 Vector3 torque = torquei;
1496 1981
1497 if (localGlobalTF) 1982 if (localGlobalTF)
1498 { 1983 {
1984/*
1499 Quaternion grot = GetWorldRotation(); 1985 Quaternion grot = GetWorldRotation();
1500 Quaternion AXgrot = grot; 1986 Quaternion AXgrot = grot;
1501 Vector3 AXimpulsei = impulsei; 1987 Vector3 AXimpulsei = impulsei;
1502 Vector3 newimpulse = AXimpulsei * AXgrot; 1988 Vector3 newimpulse = AXimpulsei * AXgrot;
1503 impulse = newimpulse; 1989 */
1990 torque *= GetWorldRotation();
1504 } 1991 }
1505 1992
1506 ParentGroup.setAngularImpulse(impulse); 1993 Torque = torque;
1507 } 1994 }
1508 1995
1509 /// <summary> 1996 /// <summary>
@@ -1511,17 +1998,23 @@ namespace OpenSim.Region.Framework.Scenes
1511 /// </summary> 1998 /// </summary>
1512 /// <param name="rootObjectFlags"></param> 1999 /// <param name="rootObjectFlags"></param>
1513 /// <param name="VolumeDetectActive"></param> 2000 /// <param name="VolumeDetectActive"></param>
1514 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 2001 /// <param name="building"></param>
2002
2003 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1515 { 2004 {
2005 VolumeDetectActive = _VolumeDetectActive;
2006
1516 if (!ParentGroup.Scene.CollidablePrims) 2007 if (!ParentGroup.Scene.CollidablePrims)
1517 return; 2008 return;
1518 2009
1519// m_log.DebugFormat( 2010 if (PhysicsShapeType == (byte)PhysShapeType.none)
1520// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 2011 return;
1521// Name, LocalId, UUID, m_physicalPrim); 2012
2013 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
2014 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1522 2015
1523 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2016 if (_VolumeDetectActive)
1524 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2017 isPhantom = true;
1525 2018
1526 if (IsJoint()) 2019 if (IsJoint())
1527 { 2020 {
@@ -1529,22 +2022,14 @@ namespace OpenSim.Region.Framework.Scenes
1529 } 2022 }
1530 else 2023 else
1531 { 2024 {
1532 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 2025 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1533 if (VolumeDetectActive) 2026 && !(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 { 2027 {
1540 // Added clarification.. since A rigid body is an object that you can kick around, etc. 2028 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1541 bool rigidBody = isPhysical && !isPhantom; 2029 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1542
1543 PhysicsActor pa = AddToPhysics(rigidBody);
1544
1545 if (pa != null)
1546 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1547 } 2030 }
2031 else
2032 PhysActor = null; // just to be sure
1548 } 2033 }
1549 } 2034 }
1550 2035
@@ -1596,6 +2081,12 @@ namespace OpenSim.Region.Framework.Scenes
1596 dupe.Category = Category; 2081 dupe.Category = Category;
1597 dupe.m_rezzed = m_rezzed; 2082 dupe.m_rezzed = m_rezzed;
1598 2083
2084 dupe.m_UndoRedo = null;
2085 dupe.m_isSelected = false;
2086
2087 dupe.IgnoreUndoUpdate = false;
2088 dupe.Undoing = false;
2089
1599 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2090 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1600 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2091 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1601 2092
@@ -1611,6 +2102,7 @@ namespace OpenSim.Region.Framework.Scenes
1611 2102
1612 // Move afterwards ResetIDs as it clears the localID 2103 // Move afterwards ResetIDs as it clears the localID
1613 dupe.LocalId = localID; 2104 dupe.LocalId = localID;
2105
1614 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2106 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1615 dupe.LastOwnerID = OwnerID; 2107 dupe.LastOwnerID = OwnerID;
1616 2108
@@ -1618,6 +2110,9 @@ namespace OpenSim.Region.Framework.Scenes
1618 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2110 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1619 dupe.Shape.ExtraParams = extraP; 2111 dupe.Shape.ExtraParams = extraP;
1620 2112
2113 // safeguard actual copy is done in sog.copy
2114 dupe.KeyframeMotion = null;
2115
1621 if (userExposed) 2116 if (userExposed)
1622 { 2117 {
1623 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) 2118 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
@@ -1628,8 +2123,12 @@ namespace OpenSim.Region.Framework.Scenes
1628 2123
1629 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2124 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1630 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2125 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2126// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1631 } 2127 }
1632 2128
2129 if (dupe.PhysActor != null)
2130 dupe.PhysActor.LocalID = localID;
2131
1633 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2132 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1634 2133
1635// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2134// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1647,10 +2146,10 @@ namespace OpenSim.Region.Framework.Scenes
1647 { 2146 {
1648 if (asset != null) 2147 if (asset != null)
1649 SculptTextureCallback(asset); 2148 SculptTextureCallback(asset);
1650 else 2149// else
1651 m_log.WarnFormat( 2150// m_log.WarnFormat(
1652 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2151// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1653 Name, UUID, id); 2152// Name, UUID, id);
1654 } 2153 }
1655 2154
1656 /// <summary> 2155 /// <summary>
@@ -1749,6 +2248,7 @@ namespace OpenSim.Region.Framework.Scenes
1749 2248
1750 /// <summary> 2249 /// <summary>
1751 /// Do a physics propery update for this part. 2250 /// Do a physics propery update for this part.
2251 /// now also updates phantom and volume detector
1752 /// </summary> 2252 /// </summary>
1753 /// <param name="UsePhysics"></param> 2253 /// <param name="UsePhysics"></param>
1754 /// <param name="isNew"></param> 2254 /// <param name="isNew"></param>
@@ -1774,61 +2274,69 @@ namespace OpenSim.Region.Framework.Scenes
1774 { 2274 {
1775 if (pa.IsPhysical) // implies UsePhysics==false for this block 2275 if (pa.IsPhysical) // implies UsePhysics==false for this block
1776 { 2276 {
1777 if (!isNew) 2277 if (!isNew) // implies UsePhysics==false for this block
2278 {
1778 ParentGroup.Scene.RemovePhysicalPrim(1); 2279 ParentGroup.Scene.RemovePhysicalPrim(1);
1779 2280
1780 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2281 Velocity = new Vector3(0, 0, 0);
1781 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2282 Acceleration = new Vector3(0, 0, 0);
1782 pa.delink(); 2283 if (ParentGroup.RootPart == this)
2284 AngularVelocity = new Vector3(0, 0, 0);
1783 2285
1784 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2286 if (pa.Phantom && !VolumeDetectActive)
1785 { 2287 {
1786 // destroy all joints connected to this now deactivated body 2288 RemoveFromPhysics();
1787 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2289 return;
1788 } 2290 }
1789 2291
1790 // stop client-side interpolation of all joint proxy objects that have just been deleted 2292 pa.IsPhysical = UsePhysics;
1791 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2293 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1792 // which stops client-side interpolation of deactivated joint proxy objects. 2294 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2295 pa.delink();
2296 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2297 {
2298 // destroy all joints connected to this now deactivated body
2299 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2300 }
2301 }
1793 } 2302 }
1794 2303
1795 if (!UsePhysics && !isNew) 2304 if (pa.IsPhysical != UsePhysics)
1796 { 2305 pa.IsPhysical = UsePhysics;
1797 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1798 // prim still has velocity and continues to interpolate its position along the old
1799 // velocity-vector.
1800 Velocity = new Vector3(0, 0, 0);
1801 Acceleration = new Vector3(0, 0, 0);
1802 AngularVelocity = new Vector3(0, 0, 0);
1803 //RotationalVelocity = new Vector3(0, 0, 0);
1804 }
1805 2306
1806 pa.IsPhysical = UsePhysics; 2307 if (UsePhysics)
2308 {
2309 if (ParentGroup.RootPart.KeyframeMotion != null)
2310 ParentGroup.RootPart.KeyframeMotion.Stop();
2311 ParentGroup.RootPart.KeyframeMotion = null;
2312 ParentGroup.Scene.AddPhysicalPrim(1);
1807 2313
1808 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2314 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1809 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2315 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1810 /// that's not wholesome. Had to make Scene public
1811 //PhysActor = null;
1812 2316
1813 if ((Flags & PrimFlags.Phantom) == 0) 2317 if (ParentID != 0 && ParentID != LocalId)
1814 {
1815 if (UsePhysics)
1816 { 2318 {
1817 ParentGroup.Scene.AddPhysicalPrim(1); 2319 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1818 2320
1819 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2321 if (parentPa != null)
1820 pa.OnOutOfBounds += PhysicsOutOfBounds;
1821 if (ParentID != 0 && ParentID != LocalId)
1822 { 2322 {
1823 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2323 pa.link(parentPa);
1824
1825 if (parentPa != null)
1826 {
1827 pa.link(parentPa);
1828 }
1829 } 2324 }
1830 } 2325 }
1831 } 2326 }
2327 }
2328
2329 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2330 if (pa.Phantom != phan)
2331 pa.Phantom = phan;
2332
2333// some engines dont' have this check still
2334// if (VolumeDetectActive != pa.IsVolumeDtc)
2335 {
2336 if (VolumeDetectActive)
2337 pa.SetVolumeDetect(1);
2338 else
2339 pa.SetVolumeDetect(0);
1832 } 2340 }
1833 2341
1834 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2342 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1947,12 +2455,26 @@ namespace OpenSim.Region.Framework.Scenes
1947 2455
1948 public Vector3 GetGeometricCenter() 2456 public Vector3 GetGeometricCenter()
1949 { 2457 {
1950 PhysicsActor pa = PhysActor; 2458 // this is not real geometric center but a average of positions relative to root prim acording to
1951 2459 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
1952 if (pa != null) 2460 // ignoring tortured prims details since sl also seems to ignore
1953 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2461 // so no real use in doing it on physics
1954 else 2462 if (ParentGroup.IsDeleted)
1955 return new Vector3(0, 0, 0); 2463 return new Vector3(0, 0, 0);
2464
2465 return ParentGroup.GetGeometricCenter();
2466
2467 /*
2468 PhysicsActor pa = PhysActor;
2469
2470 if (pa != null)
2471 {
2472 Vector3 vtmp = pa.CenterOfMass;
2473 return vtmp;
2474 }
2475 else
2476 return new Vector3(0, 0, 0);
2477 */
1956 } 2478 }
1957 2479
1958 public float GetMass() 2480 public float GetMass()
@@ -1965,14 +2487,43 @@ namespace OpenSim.Region.Framework.Scenes
1965 return 0; 2487 return 0;
1966 } 2488 }
1967 2489
1968 public Vector3 GetForce() 2490 public Vector3 GetCenterOfMass()
2491 {
2492 if (ParentGroup.RootPart == this)
2493 {
2494 if (ParentGroup.IsDeleted)
2495 return AbsolutePosition;
2496 return ParentGroup.GetCenterOfMass();
2497 }
2498
2499 PhysicsActor pa = PhysActor;
2500
2501 if (pa != null)
2502 {
2503 Vector3 tmp = pa.CenterOfMass;
2504 return tmp;
2505 }
2506 else
2507 return AbsolutePosition;
2508 }
2509
2510 public Vector3 GetPartCenterOfMass()
1969 { 2511 {
1970 PhysicsActor pa = PhysActor; 2512 PhysicsActor pa = PhysActor;
1971 2513
1972 if (pa != null) 2514 if (pa != null)
1973 return pa.Force; 2515 {
2516 Vector3 tmp = pa.CenterOfMass;
2517 return tmp;
2518 }
1974 else 2519 else
1975 return Vector3.Zero; 2520 return AbsolutePosition;
2521 }
2522
2523
2524 public Vector3 GetForce()
2525 {
2526 return Force;
1976 } 2527 }
1977 2528
1978 /// <summary> 2529 /// <summary>
@@ -2187,15 +2738,25 @@ namespace OpenSim.Region.Framework.Scenes
2187 2738
2188 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2739 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2189 { 2740 {
2190 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2741 bool sendToRoot = true;
2191 { 2742
2192 ColliderArgs LandCollidingMessage = new ColliderArgs(); 2743 ColliderArgs LandCollidingMessage = new ColliderArgs();
2193 List<DetectedObject> colliding = new List<DetectedObject>(); 2744 List<DetectedObject> colliding = new List<DetectedObject>();
2194 2745
2195 colliding.Add(CreateDetObjectForGround()); 2746 colliding.Add(CreateDetObjectForGround());
2196 LandCollidingMessage.Colliders = colliding; 2747 LandCollidingMessage.Colliders = colliding;
2197 2748
2749 if (Inventory.ContainsScripts())
2750 {
2751 if (!PassCollisions)
2752 sendToRoot = false;
2753 }
2754 if ((ScriptEvents & ev) != 0)
2198 notify(LocalId, LandCollidingMessage); 2755 notify(LocalId, LandCollidingMessage);
2756
2757 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2758 {
2759 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2199 } 2760 }
2200 } 2761 }
2201 2762
@@ -2211,45 +2772,87 @@ namespace OpenSim.Region.Framework.Scenes
2211 List<uint> endedColliders = new List<uint>(); 2772 List<uint> endedColliders = new List<uint>();
2212 List<uint> startedColliders = new List<uint>(); 2773 List<uint> startedColliders = new List<uint>();
2213 2774
2214 // calculate things that started colliding this time 2775 if (collissionswith.Count == 0)
2215 // and build up list of colliders this time
2216 foreach (uint localid in collissionswith.Keys)
2217 { 2776 {
2218 thisHitColliders.Add(localid); 2777 if (m_lastColliders.Count == 0)
2219 if (!m_lastColliders.Contains(localid)) 2778 return; // nothing to do
2220 startedColliders.Add(localid);
2221 }
2222 2779
2223 // calculate things that ended colliding 2780 foreach (uint localID in m_lastColliders)
2224 foreach (uint localID in m_lastColliders) 2781 {
2225 {
2226 if (!thisHitColliders.Contains(localID))
2227 endedColliders.Add(localID); 2782 endedColliders.Add(localID);
2783 }
2784 m_lastColliders.Clear();
2228 } 2785 }
2229 2786
2230 //add the items that started colliding this time to the last colliders list. 2787 else
2231 foreach (uint localID in startedColliders) 2788 {
2232 m_lastColliders.Add(localID); 2789 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2790
2791 // calculate things that started colliding this time
2792 // and build up list of colliders this time
2793 if (!VolumeDetectActive && CollisionSoundType >= 0)
2794 {
2795 CollisionForSoundInfo soundinfo;
2796 ContactPoint curcontact;
2797
2798 foreach (uint id in collissionswith.Keys)
2799 {
2800 thisHitColliders.Add(id);
2801 if (!m_lastColliders.Contains(id))
2802 {
2803 startedColliders.Add(id);
2233 2804
2234 // remove things that ended colliding from the last colliders list 2805 curcontact = collissionswith[id];
2235 foreach (uint localID in endedColliders) 2806 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2236 m_lastColliders.Remove(localID); 2807 {
2808 soundinfo = new CollisionForSoundInfo();
2809 soundinfo.colliderID = id;
2810 soundinfo.position = curcontact.Position;
2811 soundinfo.relativeVel = curcontact.RelativeSpeed;
2812 soundinfolist.Add(soundinfo);
2813 }
2814 }
2815 }
2816 }
2817 else
2818 {
2819 foreach (uint id in collissionswith.Keys)
2820 {
2821 thisHitColliders.Add(id);
2822 if (!m_lastColliders.Contains(id))
2823 startedColliders.Add(id);
2824 }
2825 }
2237 2826
2238 // play the sound. 2827 // calculate things that ended colliding
2239 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2828 foreach (uint localID in m_lastColliders)
2240 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); 2829 {
2830 if (!thisHitColliders.Contains(localID))
2831 endedColliders.Add(localID);
2832 }
2833
2834 //add the items that started colliding this time to the last colliders list.
2835 foreach (uint localID in startedColliders)
2836 m_lastColliders.Add(localID);
2837
2838 // remove things that ended colliding from the last colliders list
2839 foreach (uint localID in endedColliders)
2840 m_lastColliders.Remove(localID);
2841
2842 // play sounds.
2843 if (soundinfolist.Count > 0)
2844 CollisionSounds.PartCollisionSound(this, soundinfolist);
2845 }
2241 2846
2242 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2847 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2243 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2848 if (!VolumeDetectActive)
2849 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2244 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2850 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2245 2851
2246 if (startedColliders.Contains(0)) 2852 if (startedColliders.Contains(0))
2247 { 2853 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2248 if (m_lastColliders.Contains(0)) 2854 if (m_lastColliders.Contains(0))
2249 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2855 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2250 else
2251 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2252 }
2253 if (endedColliders.Contains(0)) 2856 if (endedColliders.Contains(0))
2254 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2857 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2255 } 2858 }
@@ -2272,9 +2875,9 @@ namespace OpenSim.Region.Framework.Scenes
2272 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2875 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2273 2876
2274 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2877 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2275 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2878 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2276 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2879 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2277 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2880 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2278 { 2881 {
2279 ParentGroup.AbsolutePosition = newpos; 2882 ParentGroup.AbsolutePosition = newpos;
2280 return; 2883 return;
@@ -2296,17 +2899,18 @@ namespace OpenSim.Region.Framework.Scenes
2296 //Trys to fetch sound id from prim's inventory. 2899 //Trys to fetch sound id from prim's inventory.
2297 //Prim's inventory doesn't support non script items yet 2900 //Prim's inventory doesn't support non script items yet
2298 2901
2299 lock (TaskInventory) 2902 TaskInventory.LockItemsForRead(true);
2903
2904 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2300 { 2905 {
2301 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2906 if (item.Value.Name == sound)
2302 { 2907 {
2303 if (item.Value.Name == sound) 2908 soundID = item.Value.ItemID;
2304 { 2909 break;
2305 soundID = item.Value.ItemID;
2306 break;
2307 }
2308 } 2910 }
2309 } 2911 }
2912
2913 TaskInventory.LockItemsForRead(false);
2310 } 2914 }
2311 2915
2312 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2916 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2432,6 +3036,19 @@ namespace OpenSim.Region.Framework.Scenes
2432 APIDTarget = Quaternion.Identity; 3036 APIDTarget = Quaternion.Identity;
2433 } 3037 }
2434 3038
3039
3040
3041 public void ScheduleFullUpdateIfNone()
3042 {
3043 if (ParentGroup == null)
3044 return;
3045
3046// ??? ParentGroup.HasGroupChanged = true;
3047
3048 if (UpdateFlag != UpdateRequired.FULL)
3049 ScheduleFullUpdate();
3050 }
3051
2435 /// <summary> 3052 /// <summary>
2436 /// Schedules this prim for a full update 3053 /// Schedules this prim for a full update
2437 /// </summary> 3054 /// </summary>
@@ -2634,8 +3251,8 @@ namespace OpenSim.Region.Framework.Scenes
2634 { 3251 {
2635 const float ROTATION_TOLERANCE = 0.01f; 3252 const float ROTATION_TOLERANCE = 0.01f;
2636 const float VELOCITY_TOLERANCE = 0.001f; 3253 const float VELOCITY_TOLERANCE = 0.001f;
2637 const float POSITION_TOLERANCE = 0.05f; 3254 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2638 const int TIME_MS_TOLERANCE = 3000; 3255 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2639 3256
2640 switch (UpdateFlag) 3257 switch (UpdateFlag)
2641 { 3258 {
@@ -2697,17 +3314,16 @@ namespace OpenSim.Region.Framework.Scenes
2697 if (!UUID.TryParse(sound, out soundID)) 3314 if (!UUID.TryParse(sound, out soundID))
2698 { 3315 {
2699 // search sound file from inventory 3316 // search sound file from inventory
2700 lock (TaskInventory) 3317 TaskInventory.LockItemsForRead(true);
3318 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2701 { 3319 {
2702 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3320 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2703 { 3321 {
2704 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3322 soundID = item.Value.ItemID;
2705 { 3323 break;
2706 soundID = item.Value.ItemID;
2707 break;
2708 }
2709 } 3324 }
2710 } 3325 }
3326 TaskInventory.LockItemsForRead(false);
2711 } 3327 }
2712 3328
2713 if (soundID == UUID.Zero) 3329 if (soundID == UUID.Zero)
@@ -2764,11 +3380,43 @@ namespace OpenSim.Region.Framework.Scenes
2764 } 3380 }
2765 } 3381 }
2766 3382
3383 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3384 {
3385 if (soundID == UUID.Zero)
3386 return;
3387
3388 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3389 if (soundModule == null)
3390 return;
3391
3392 if (volume > 1)
3393 volume = 1;
3394 if (volume < 0)
3395 volume = 0;
3396
3397 int now = Util.EnvironmentTickCount();
3398 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3399 return;
3400
3401 LastColSoundSentTime = now;
3402
3403 UUID ownerID = OwnerID;
3404 UUID objectID = ParentGroup.RootPart.UUID;
3405 UUID parentID = ParentGroup.UUID;
3406 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3407
3408 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3409 }
3410
3411
2767 /// <summary> 3412 /// <summary>
2768 /// Send a terse update to all clients 3413 /// Send a terse update to all clients
2769 /// </summary> 3414 /// </summary>
2770 public void SendTerseUpdateToAllClients() 3415 public void SendTerseUpdateToAllClients()
2771 { 3416 {
3417 if (ParentGroup == null || ParentGroup.Scene == null)
3418 return;
3419
2772 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3420 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2773 { 3421 {
2774 SendTerseUpdateToClient(client); 3422 SendTerseUpdateToClient(client);
@@ -2792,10 +3440,13 @@ namespace OpenSim.Region.Framework.Scenes
2792 3440
2793 public void SetBuoyancy(float fvalue) 3441 public void SetBuoyancy(float fvalue)
2794 { 3442 {
2795 PhysicsActor pa = PhysActor; 3443 Buoyancy = fvalue;
2796 3444/*
2797 if (pa != null) 3445 if (PhysActor != null)
2798 pa.Buoyancy = fvalue; 3446 {
3447 PhysActor.Buoyancy = fvalue;
3448 }
3449 */
2799 } 3450 }
2800 3451
2801 public void SetDieAtEdge(bool p) 3452 public void SetDieAtEdge(bool p)
@@ -2811,47 +3462,111 @@ namespace OpenSim.Region.Framework.Scenes
2811 PhysicsActor pa = PhysActor; 3462 PhysicsActor pa = PhysActor;
2812 3463
2813 if (pa != null) 3464 if (pa != null)
2814 pa.FloatOnWater = floatYN == 1; 3465 pa.FloatOnWater = (floatYN == 1);
2815 } 3466 }
2816 3467
2817 public void SetForce(Vector3 force) 3468 public void SetForce(Vector3 force)
2818 { 3469 {
2819 PhysicsActor pa = PhysActor; 3470 Force = force;
3471 }
2820 3472
2821 if (pa != null) 3473 public SOPVehicle VehicleParams
2822 pa.Force = force; 3474 {
3475 get
3476 {
3477 return m_vehicleParams;
3478 }
3479 set
3480 {
3481 m_vehicleParams = value;
3482 }
3483 }
3484
3485
3486 public int VehicleType
3487 {
3488 get
3489 {
3490 if (m_vehicleParams == null)
3491 return (int)Vehicle.TYPE_NONE;
3492 else
3493 return (int)m_vehicleParams.Type;
3494 }
3495 set
3496 {
3497 SetVehicleType(value);
3498 }
2823 } 3499 }
2824 3500
2825 public void SetVehicleType(int type) 3501 public void SetVehicleType(int type)
2826 { 3502 {
2827 PhysicsActor pa = PhysActor; 3503 m_vehicleParams = null;
3504
3505 if (type == (int)Vehicle.TYPE_NONE)
3506 {
3507 if (_parentID ==0 && PhysActor != null)
3508 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3509 return;
3510 }
3511 m_vehicleParams = new SOPVehicle();
3512 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3513 {
3514 if (_parentID ==0 && PhysActor != null)
3515 PhysActor.VehicleType = type;
3516 return;
3517 }
3518 }
2828 3519
2829 if (pa != null) 3520 public void SetVehicleFlags(int param, bool remove)
2830 pa.VehicleType = type; 3521 {
3522 if (m_vehicleParams == null)
3523 return;
3524
3525 m_vehicleParams.ProcessVehicleFlags(param, remove);
3526
3527 if (_parentID ==0 && PhysActor != null)
3528 {
3529 PhysActor.VehicleFlags(param, remove);
3530 }
2831 } 3531 }
2832 3532
2833 public void SetVehicleFloatParam(int param, float value) 3533 public void SetVehicleFloatParam(int param, float value)
2834 { 3534 {
2835 PhysicsActor pa = PhysActor; 3535 if (m_vehicleParams == null)
3536 return;
2836 3537
2837 if (pa != null) 3538 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
2838 pa.VehicleFloatParam(param, value); 3539
3540 if (_parentID == 0 && PhysActor != null)
3541 {
3542 PhysActor.VehicleFloatParam(param, value);
3543 }
2839 } 3544 }
2840 3545
2841 public void SetVehicleVectorParam(int param, Vector3 value) 3546 public void SetVehicleVectorParam(int param, Vector3 value)
2842 { 3547 {
2843 PhysicsActor pa = PhysActor; 3548 if (m_vehicleParams == null)
3549 return;
2844 3550
2845 if (pa != null) 3551 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
2846 pa.VehicleVectorParam(param, value); 3552
3553 if (_parentID == 0 && PhysActor != null)
3554 {
3555 PhysActor.VehicleVectorParam(param, value);
3556 }
2847 } 3557 }
2848 3558
2849 public void SetVehicleRotationParam(int param, Quaternion rotation) 3559 public void SetVehicleRotationParam(int param, Quaternion rotation)
2850 { 3560 {
2851 PhysicsActor pa = PhysActor; 3561 if (m_vehicleParams == null)
3562 return;
2852 3563
2853 if (pa != null) 3564 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
2854 pa.VehicleRotationParam(param, rotation); 3565
3566 if (_parentID == 0 && PhysActor != null)
3567 {
3568 PhysActor.VehicleRotationParam(param, rotation);
3569 }
2855 } 3570 }
2856 3571
2857 /// <summary> 3572 /// <summary>
@@ -3052,14 +3767,6 @@ namespace OpenSim.Region.Framework.Scenes
3052 hasProfileCut = hasDimple; // is it the same thing? 3767 hasProfileCut = hasDimple; // is it the same thing?
3053 } 3768 }
3054 3769
3055 public void SetVehicleFlags(int param, bool remove)
3056 {
3057 PhysicsActor pa = PhysActor;
3058
3059 if (pa != null)
3060 pa.VehicleFlags(param, remove);
3061 }
3062
3063 public void SetGroup(UUID groupID, IClientAPI client) 3770 public void SetGroup(UUID groupID, IClientAPI client)
3064 { 3771 {
3065 // Scene.AddNewPrims() calls with client == null so can't use this. 3772 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3163,67 +3870,16 @@ namespace OpenSim.Region.Framework.Scenes
3163 //ParentGroup.ScheduleGroupForFullUpdate(); 3870 //ParentGroup.ScheduleGroupForFullUpdate();
3164 } 3871 }
3165 3872
3166 public void StoreUndoState() 3873 public void StoreUndoState(ObjectChangeType change)
3167 { 3874 {
3168 StoreUndoState(false); 3875 if (m_UndoRedo == null)
3169 } 3876 m_UndoRedo = new UndoRedoState(5);
3170 3877
3171 public void StoreUndoState(bool forGroup) 3878 lock (m_UndoRedo)
3172 {
3173 if (ParentGroup == null || ParentGroup.Scene == null)
3174 return;
3175
3176 if (Undoing)
3177 {
3178// m_log.DebugFormat(
3179// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3180 return;
3181 }
3182
3183 if (IgnoreUndoUpdate)
3184 {
3185// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3186 return;
3187 }
3188
3189 lock (m_undo)
3190 { 3879 {
3191 if (m_undo.Count > 0) 3880 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3192 { 3881 {
3193 UndoState last = m_undo[m_undo.Count - 1]; 3882 m_UndoRedo.StoreUndo(this, change);
3194 if (last != null)
3195 {
3196 // TODO: May need to fix for group comparison
3197 if (last.Compare(this))
3198 {
3199// m_log.DebugFormat(
3200// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3201// Name, LocalId, m_undo.Count);
3202
3203 return;
3204 }
3205 }
3206 }
3207
3208// m_log.DebugFormat(
3209// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3210// Name, LocalId, forGroup, m_undo.Count);
3211
3212 if (ParentGroup.Scene.MaxUndoCount > 0)
3213 {
3214 UndoState nUndo = new UndoState(this, forGroup);
3215
3216 m_undo.Add(nUndo);
3217
3218 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3219 m_undo.RemoveAt(0);
3220
3221 if (m_redo.Count > 0)
3222 m_redo.Clear();
3223
3224// m_log.DebugFormat(
3225// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3226// Name, LocalId, forGroup, m_undo.Count);
3227 } 3883 }
3228 } 3884 }
3229 } 3885 }
@@ -3235,88 +3891,46 @@ namespace OpenSim.Region.Framework.Scenes
3235 { 3891 {
3236 get 3892 get
3237 { 3893 {
3238 lock (m_undo) 3894 if (m_UndoRedo == null)
3239 return m_undo.Count; 3895 return 0;
3896 return m_UndoRedo.Count;
3240 } 3897 }
3241 } 3898 }
3242 3899
3243 public void Undo() 3900 public void Undo()
3244 { 3901 {
3245 lock (m_undo) 3902 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3246 { 3903 return;
3247// m_log.DebugFormat(
3248// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3249// Name, LocalId, m_undo.Count);
3250
3251 if (m_undo.Count > 0)
3252 {
3253 UndoState goback = m_undo[m_undo.Count - 1];
3254 m_undo.RemoveAt(m_undo.Count - 1);
3255
3256 UndoState nUndo = null;
3257
3258 if (ParentGroup.Scene.MaxUndoCount > 0)
3259 {
3260 nUndo = new UndoState(this, goback.ForGroup);
3261 }
3262
3263 goback.PlaybackState(this);
3264
3265 if (nUndo != null)
3266 {
3267 m_redo.Add(nUndo);
3268
3269 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3270 m_redo.RemoveAt(0);
3271 }
3272 }
3273 3904
3274// m_log.DebugFormat( 3905 lock (m_UndoRedo)
3275// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3906 {
3276// Name, LocalId, m_undo.Count); 3907 Undoing = true;
3908 m_UndoRedo.Undo(this);
3909 Undoing = false;
3277 } 3910 }
3278 } 3911 }
3279 3912
3280 public void Redo() 3913 public void Redo()
3281 { 3914 {
3282 lock (m_undo) 3915 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3283 { 3916 return;
3284// m_log.DebugFormat(
3285// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3286// Name, LocalId, m_redo.Count);
3287
3288 if (m_redo.Count > 0)
3289 {
3290 UndoState gofwd = m_redo[m_redo.Count - 1];
3291 m_redo.RemoveAt(m_redo.Count - 1);
3292
3293 if (ParentGroup.Scene.MaxUndoCount > 0)
3294 {
3295 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3296
3297 m_undo.Add(nUndo);
3298
3299 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3300 m_undo.RemoveAt(0);
3301 }
3302
3303 gofwd.PlayfwdState(this);
3304 3917
3305// m_log.DebugFormat( 3918 lock (m_UndoRedo)
3306// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3919 {
3307// Name, LocalId, m_redo.Count); 3920 Undoing = true;
3308 } 3921 m_UndoRedo.Redo(this);
3922 Undoing = false;
3309 } 3923 }
3310 } 3924 }
3311 3925
3312 public void ClearUndoState() 3926 public void ClearUndoState()
3313 { 3927 {
3314// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3928 if (m_UndoRedo == null || Undoing)
3929 return;
3315 3930
3316 lock (m_undo) 3931 lock (m_UndoRedo)
3317 { 3932 {
3318 m_undo.Clear(); 3933 m_UndoRedo.Clear();
3319 m_redo.Clear();
3320 } 3934 }
3321 } 3935 }
3322 3936
@@ -3967,6 +4581,27 @@ namespace OpenSim.Region.Framework.Scenes
3967 } 4581 }
3968 } 4582 }
3969 4583
4584
4585 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4586 {
4587 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4588 return;
4589
4590 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4591 {
4592 PhysicsShapeType = (byte)physdata.PhysShapeType;
4593
4594 }
4595
4596 if(Density != physdata.Density)
4597 Density = physdata.Density;
4598 if(GravityModifier != physdata.GravitationModifier)
4599 GravityModifier = physdata.GravitationModifier;
4600 if(Friction != physdata.Friction)
4601 Friction = physdata.Friction;
4602 if(Bounciness != physdata.Bounce)
4603 Bounciness = physdata.Bounce;
4604 }
3970 /// <summary> 4605 /// <summary>
3971 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4606 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3972 /// </summary> 4607 /// </summary>
@@ -3974,7 +4609,7 @@ namespace OpenSim.Region.Framework.Scenes
3974 /// <param name="SetTemporary"></param> 4609 /// <param name="SetTemporary"></param>
3975 /// <param name="SetPhantom"></param> 4610 /// <param name="SetPhantom"></param>
3976 /// <param name="SetVD"></param> 4611 /// <param name="SetVD"></param>
3977 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4612 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3978 { 4613 {
3979 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4614 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3980 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4615 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3984,237 +4619,230 @@ namespace OpenSim.Region.Framework.Scenes
3984 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4619 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3985 return; 4620 return;
3986 4621
3987 PhysicsActor pa = PhysActor; 4622 VolumeDetectActive = SetVD;
3988
3989 // Special cases for VD. VD can only be called from a script
3990 // and can't be combined with changes to other states. So we can rely
3991 // that...
3992 // ... if VD is changed, all others are not.
3993 // ... if one of the others is changed, VD is not.
3994 if (SetVD) // VD is active, special logic applies
3995 {
3996 // State machine logic for VolumeDetect
3997 // More logic below
3998 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3999 4623
4000 if (phanReset) // Phantom changes from on to off switch VD off too 4624 // volume detector implies phantom
4001 { 4625 if (VolumeDetectActive)
4002 SetVD = false; // Switch it of for the course of this routine
4003 VolumeDetectActive = false; // and also permanently
4004
4005 if (pa != null)
4006 pa.SetVolumeDetect(0); // Let physics know about it too
4007 }
4008 else
4009 {
4010 // If volumedetect is active we don't want phantom to be applied.
4011 // If this is a new call to VD out of the state "phantom"
4012 // this will also cause the prim to be visible to physics
4013 SetPhantom = false;
4014 }
4015 }
4016
4017 if (UsePhysics && IsJoint())
4018 {
4019 SetPhantom = true; 4626 SetPhantom = true;
4020 }
4021 4627
4022 if (UsePhysics) 4628 if (UsePhysics)
4023 {
4024 AddFlag(PrimFlags.Physics); 4629 AddFlag(PrimFlags.Physics);
4025 if (!wasUsingPhysics)
4026 {
4027 DoPhysicsPropertyUpdate(UsePhysics, false);
4028
4029 if (!ParentGroup.IsDeleted)
4030 {
4031 if (LocalId == ParentGroup.RootPart.LocalId)
4032 {
4033 ParentGroup.CheckSculptAndLoad();
4034 }
4035 }
4036 }
4037 }
4038 else 4630 else
4039 {
4040 RemFlag(PrimFlags.Physics); 4631 RemFlag(PrimFlags.Physics);
4041 if (wasUsingPhysics)
4042 {
4043 DoPhysicsPropertyUpdate(UsePhysics, false);
4044 }
4045 }
4046 4632
4047 if (SetPhantom 4633 if (SetPhantom)
4048 || ParentGroup.IsAttachment
4049 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4050 {
4051 AddFlag(PrimFlags.Phantom); 4634 AddFlag(PrimFlags.Phantom);
4635 else
4636 RemFlag(PrimFlags.Phantom);
4052 4637
4053 if (PhysActor != null) 4638 if (SetTemporary)
4639 AddFlag(PrimFlags.TemporaryOnRez);
4640 else
4641 RemFlag(PrimFlags.TemporaryOnRez);
4642
4643
4644 if (ParentGroup.Scene == null)
4645 return;
4646
4647 PhysicsActor pa = PhysActor;
4648
4649 if (pa != null && building && pa.Building != building)
4650 pa.Building = building;
4651
4652 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4653 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4654 {
4655 if (pa != null)
4054 { 4656 {
4657 if(wasUsingPhysics)
4658 ParentGroup.Scene.RemovePhysicalPrim(1);
4055 RemoveFromPhysics(); 4659 RemoveFromPhysics();
4056 pa = null;
4057 } 4660 }
4661
4662 Velocity = new Vector3(0, 0, 0);
4663 Acceleration = new Vector3(0, 0, 0);
4664 if (ParentGroup.RootPart == this)
4665 AngularVelocity = new Vector3(0, 0, 0);
4058 } 4666 }
4059 else // Not phantom 4667 else
4060 { 4668 {
4061 RemFlag(PrimFlags.Phantom); 4669 if (ParentGroup.Scene.CollidablePrims)
4062
4063 if (ParentGroup.Scene == null)
4064 return;
4065
4066 if (ParentGroup.Scene.CollidablePrims && pa == null)
4067 { 4670 {
4068 pa = AddToPhysics(UsePhysics); 4671 if (pa == null)
4069
4070 if (pa != null)
4071 { 4672 {
4072 pa.SetMaterial(Material); 4673 AddToPhysics(UsePhysics, SetPhantom, building, false);
4073 DoPhysicsPropertyUpdate(UsePhysics, true); 4674 pa = PhysActor;
4074 4675/*
4075 if (!ParentGroup.IsDeleted) 4676 if (pa != null)
4076 { 4677 {
4077 if (LocalId == ParentGroup.RootPart.LocalId) 4678 if (
4679// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4680// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4681// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4682// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4683// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4684// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4685 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4686 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4687 (CollisionSound != UUID.Zero)
4688 )
4078 { 4689 {
4079 ParentGroup.CheckSculptAndLoad(); 4690 pa.OnCollisionUpdate += PhysicsCollision;
4691 pa.SubscribeEvents(1000);
4080 } 4692 }
4081 } 4693 }
4082 4694*/
4083 if (
4084 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4085 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4086 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4087 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4088 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4089 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4090 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4091 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4092 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4093 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4094 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4095 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4096 (CollisionSound != UUID.Zero)
4097 )
4098 {
4099 pa.OnCollisionUpdate += PhysicsCollision;
4100 pa.SubscribeEvents(1000);
4101 }
4102 } 4695 }
4103 } 4696 else // it already has a physical representation
4104 else // it already has a physical representation
4105 {
4106 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4107
4108 if (!ParentGroup.IsDeleted)
4109 { 4697 {
4110 if (LocalId == ParentGroup.RootPart.LocalId) 4698 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4111 { 4699/* moved into DoPhysicsPropertyUpdate
4112 ParentGroup.CheckSculptAndLoad(); 4700 if(VolumeDetectActive)
4113 } 4701 pa.SetVolumeDetect(1);
4702 else
4703 pa.SetVolumeDetect(0);
4704*/
4705
4706 if (pa.Building != building)
4707 pa.Building = building;
4114 } 4708 }
4115 }
4116 }
4117 4709
4118 if (SetVD) 4710 UpdatePhysicsSubscribedEvents();
4119 {
4120 // If the above logic worked (this is urgent candidate to unit tests!)
4121 // we now have a physicsactor.
4122 // Defensive programming calls for a check here.
4123 // Better would be throwing an exception that could be catched by a unit test as the internal
4124 // logic should make sure, this Physactor is always here.
4125 if (pa != null)
4126 {
4127 pa.SetVolumeDetect(1);
4128 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4129 VolumeDetectActive = true;
4130 } 4711 }
4131 } 4712 }
4132 else
4133 {
4134 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
4135 // (mumbles, well, at least if you have infinte CPU powers :-))
4136 if (pa != null)
4137 pa.SetVolumeDetect(0);
4138
4139 VolumeDetectActive = false;
4140 }
4141
4142 if (SetTemporary)
4143 {
4144 AddFlag(PrimFlags.TemporaryOnRez);
4145 }
4146 else
4147 {
4148 RemFlag(PrimFlags.TemporaryOnRez);
4149 }
4150 4713
4151 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4714 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4152 4715
4716 // and last in case we have a new actor and not building
4717
4153 if (ParentGroup != null) 4718 if (ParentGroup != null)
4154 { 4719 {
4155 ParentGroup.HasGroupChanged = true; 4720 ParentGroup.HasGroupChanged = true;
4156 ScheduleFullUpdate(); 4721 ScheduleFullUpdate();
4157 } 4722 }
4158 4723
4159// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4724// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4160 } 4725 }
4161 4726
4162 /// <summary> 4727 /// <summary>
4163 /// Adds this part to the physics scene. 4728 /// Adds this part to the physics scene.
4729 /// and sets the PhysActor property
4164 /// </summary> 4730 /// </summary>
4165 /// <remarks>This method also sets the PhysActor property.</remarks> 4731 /// <param name="isPhysical">Add this prim as physical.</param>
4166 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4732 /// <param name="isPhantom">Add this prim as phantom.</param>
4167 /// <returns> 4733 /// <param name="building">tells physics to delay full construction of object</param>
4168 /// The physics actor. null if there was a failure. 4734 /// <param name="applyDynamics">applies velocities, force and torque</param>
4169 /// </returns> 4735 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4170 private PhysicsActor AddToPhysics(bool rigidBody) 4736 {
4171 {
4172 PhysicsActor pa; 4737 PhysicsActor pa;
4173 4738
4739 Vector3 velocity = Velocity;
4740 Vector3 rotationalVelocity = AngularVelocity;;
4741
4174 try 4742 try
4175 { 4743 {
4176 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4744 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4177 string.Format("{0}/{1}", Name, UUID), 4745 string.Format("{0}/{1}", Name, UUID),
4178 Shape, 4746 Shape,
4179 AbsolutePosition, 4747 AbsolutePosition,
4180 Scale, 4748 Scale,
4181 RotationOffset, 4749 GetWorldRotation(),
4182 rigidBody, 4750 isPhysical,
4183 m_localId); 4751 isPhantom,
4752 PhysicsShapeType,
4753 m_localId);
4184 } 4754 }
4185 catch 4755 catch (Exception ex)
4186 { 4756 {
4187 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4757 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4188 pa = null; 4758 pa = null;
4189 } 4759 }
4190 4760
4191 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4192 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4193 // being set.
4194 PhysActor = pa;
4195
4196 // Basic Physics can also return null as well as an exception catch.
4197 if (pa != null) 4761 if (pa != null)
4198 { 4762 {
4199 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4763 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4200 pa.SetMaterial(Material); 4764 pa.SetMaterial(Material);
4201 DoPhysicsPropertyUpdate(rigidBody, true); 4765
4766 if (VolumeDetectActive) // change if not the default only
4767 pa.SetVolumeDetect(1);
4768
4769 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4770 m_vehicleParams.SetVehicle(pa);
4771
4772 // we are going to tell rest of code about physics so better have this here
4773 PhysActor = pa;
4774
4775 // DoPhysicsPropertyUpdate(isPhysical, true);
4776 // lets expand it here just with what it really needs to do
4777
4778 if (isPhysical)
4779 {
4780 if (ParentGroup.RootPart.KeyframeMotion != null)
4781 ParentGroup.RootPart.KeyframeMotion.Stop();
4782 ParentGroup.RootPart.KeyframeMotion = null;
4783 ParentGroup.Scene.AddPhysicalPrim(1);
4784
4785 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4786 pa.OnOutOfBounds += PhysicsOutOfBounds;
4787
4788 if (ParentID != 0 && ParentID != LocalId)
4789 {
4790 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4791
4792 if (parentPa != null)
4793 {
4794 pa.link(parentPa);
4795 }
4796 }
4797 }
4798
4799 if (applyDynamics)
4800 // do independent of isphysical so parameters get setted (at least some)
4801 {
4802 Velocity = velocity;
4803 AngularVelocity = rotationalVelocity;
4804// pa.Velocity = velocity;
4805 pa.RotationalVelocity = rotationalVelocity;
4806
4807 // if not vehicle and root part apply force and torque
4808 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4809 && LocalId == ParentGroup.RootPart.LocalId)
4810 {
4811 pa.Force = Force;
4812 pa.Torque = Torque;
4813 }
4814 }
4815
4816 if (Shape.SculptEntry)
4817 CheckSculptAndLoad();
4818 else
4819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4820
4821 if (!building)
4822 pa.Building = false;
4202 } 4823 }
4203 4824
4204 return pa; 4825 PhysActor = pa;
4205 } 4826 }
4206 4827
4207 /// <summary> 4828 /// <summary>
4208 /// This removes the part from the physics scene. 4829 /// This removes the part from the physics scene.
4209 /// </summary> 4830 /// </summary>
4210 /// <remarks> 4831 /// <remarks>
4211 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4832 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4212 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4833 /// representation for collision detection.
4213 /// phantom.
4214 /// </remarks> 4834 /// </remarks>
4215 public void RemoveFromPhysics() 4835 public void RemoveFromPhysics()
4216 { 4836 {
4217 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4837 PhysicsActor pa = PhysActor;
4838 if (pa != null)
4839 {
4840 pa.OnCollisionUpdate -= PhysicsCollision;
4841 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4842 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4843
4844 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4845 }
4218 PhysActor = null; 4846 PhysActor = null;
4219 } 4847 }
4220 4848
@@ -4425,6 +5053,44 @@ namespace OpenSim.Region.Framework.Scenes
4425 ScheduleFullUpdate(); 5053 ScheduleFullUpdate();
4426 } 5054 }
4427 5055
5056
5057 private void UpdatePhysicsSubscribedEvents()
5058 {
5059 PhysicsActor pa = PhysActor;
5060 if (pa == null)
5061 return;
5062
5063 pa.OnCollisionUpdate -= PhysicsCollision;
5064
5065 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5066
5067 scriptEvents CombinedEvents = AggregateScriptEvents;
5068
5069 // merge with root part
5070 if (ParentGroup != null && ParentGroup.RootPart != null)
5071 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5072
5073 // submit to this part case
5074 if (VolumeDetectActive)
5075 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5076 else if ((Flags & PrimFlags.Phantom) != 0)
5077 CombinedEvents &= PhyscicsPhantonSubsEvents;
5078 else
5079 CombinedEvents &= PhysicsNeededSubsEvents;
5080
5081 if (hassound || CombinedEvents != 0)
5082 {
5083 // subscribe to physics updates.
5084 pa.OnCollisionUpdate += PhysicsCollision;
5085 pa.SubscribeEvents(50); // 20 reports per second
5086 }
5087 else
5088 {
5089 pa.UnSubscribeEvents();
5090 }
5091 }
5092
5093
4428 public void aggregateScriptEvents() 5094 public void aggregateScriptEvents()
4429 { 5095 {
4430 if (ParentGroup == null || ParentGroup.RootPart == null) 5096 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4461,40 +5127,32 @@ namespace OpenSim.Region.Framework.Scenes
4461 { 5127 {
4462 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5128 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4463 } 5129 }
4464 5130/*
4465 PhysicsActor pa = PhysActor; 5131 PhysicsActor pa = PhysActor;
4466 5132 if (pa != null)
4467 if (
4468 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4469 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4470 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4471 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4472 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4473 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4474 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4475 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4476 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4477 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4478 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4479 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4480 (CollisionSound != UUID.Zero)
4481 )
4482 { 5133 {
4483 // subscribe to physics updates. 5134 if (
4484 if (pa != null) 5135// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5136// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5137// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5138// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5139// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5140// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5141 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5142 )
4485 { 5143 {
5144 // subscribe to physics updates.
4486 pa.OnCollisionUpdate += PhysicsCollision; 5145 pa.OnCollisionUpdate += PhysicsCollision;
4487 pa.SubscribeEvents(1000); 5146 pa.SubscribeEvents(1000);
4488 } 5147 }
4489 } 5148 else
4490 else
4491 {
4492 if (pa != null)
4493 { 5149 {
4494 pa.UnSubscribeEvents(); 5150 pa.UnSubscribeEvents();
4495 pa.OnCollisionUpdate -= PhysicsCollision; 5151 pa.OnCollisionUpdate -= PhysicsCollision;
4496 } 5152 }
4497 } 5153 }
5154 */
5155 UpdatePhysicsSubscribedEvents();
4498 5156
4499 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5157 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4500 //{ 5158 //{
@@ -4624,6 +5282,18 @@ namespace OpenSim.Region.Framework.Scenes
4624 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5282 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4625 } 5283 }
4626 5284
5285 public void ResetOwnerChangeFlag()
5286 {
5287 List<UUID> inv = Inventory.GetInventoryList();
5288
5289 foreach (UUID itemID in inv)
5290 {
5291 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5292 item.OwnerChanged = false;
5293 Inventory.UpdateInventoryItem(item, false, false);
5294 }
5295 }
5296
4627 /// <summary> 5297 /// <summary>
4628 /// Record an avatar sitting on this part. 5298 /// Record an avatar sitting on this part.
4629 /// </summary> 5299 /// </summary>