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.cs1659
1 files changed, 1124 insertions, 535 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b00f388..415a82b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -63,7 +63,8 @@ namespace OpenSim.Region.Framework.Scenes
63 TELEPORT = 512, 63 TELEPORT = 512,
64 REGION_RESTART = 1024, 64 REGION_RESTART = 1024,
65 MEDIA = 2048, 65 MEDIA = 2048,
66 ANIMATION = 16384 66 ANIMATION = 16384,
67 POSITION = 32768
67 } 68 }
68 69
69 // I don't really know where to put this except here. 70 // I don't really know where to put this except here.
@@ -122,7 +123,18 @@ namespace OpenSim.Region.Framework.Scenes
122 /// Denote all sides of the prim 123 /// Denote all sides of the prim
123 /// </value> 124 /// </value>
124 public const int ALL_SIDES = -1; 125 public const int ALL_SIDES = -1;
125 126
127 private const scriptEvents PhysicsNeededSubsEvents = (
128 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
129 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
130 );
131 private const scriptEvents PhyscicsPhantonSubsEvents = (
132 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
133 );
134 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
135 scriptEvents.collision_start | scriptEvents.collision_end
136 );
137
126 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 138 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
127 139
128 /// <summary> 140 /// <summary>
@@ -138,7 +150,7 @@ namespace OpenSim.Region.Framework.Scenes
138 /// </remarks> 150 /// </remarks>
139 public bool IsRoot 151 public bool IsRoot
140 { 152 {
141 get { return ParentGroup.RootPart == this; } 153 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
142 } 154 }
143 155
144 /// <summary> 156 /// <summary>
@@ -197,12 +209,25 @@ namespace OpenSim.Region.Framework.Scenes
197 209
198 public double SoundRadius; 210 public double SoundRadius;
199 211
212
200 public uint TimeStampFull; 213 public uint TimeStampFull;
201 214
202 public uint TimeStampLastActivity; // Will be used for AutoReturn 215 public uint TimeStampLastActivity; // Will be used for AutoReturn
203 216
204 public uint TimeStampTerse; 217 public uint TimeStampTerse;
205 218
219 // The following two are to hold the attachment data
220 // while an object is inworld
221 [XmlIgnore]
222 public byte AttachPoint = 0;
223
224 [XmlIgnore]
225 public Vector3 AttachOffset = Vector3.Zero;
226
227 [XmlIgnore]
228 public Quaternion AttachRotation = Quaternion.Identity;
229
230 [XmlIgnore]
206 public int STATUS_ROTATE_X; 231 public int STATUS_ROTATE_X;
207 232
208 public int STATUS_ROTATE_Y; 233 public int STATUS_ROTATE_Y;
@@ -229,8 +254,7 @@ namespace OpenSim.Region.Framework.Scenes
229 254
230 public Vector3 RotationAxis = Vector3.One; 255 public Vector3 RotationAxis = Vector3.One;
231 256
232 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 257 public bool VolumeDetectActive;
233 // Certainly this must be a persistant setting finally
234 258
235 public bool IsWaitingForFirstSpinUpdatePacket; 259 public bool IsWaitingForFirstSpinUpdatePacket;
236 260
@@ -270,10 +294,10 @@ namespace OpenSim.Region.Framework.Scenes
270 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 294 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
271 private Vector3 m_sitTargetPosition; 295 private Vector3 m_sitTargetPosition;
272 private string m_sitAnimation = "SIT"; 296 private string m_sitAnimation = "SIT";
297 private bool m_occupied; // KF if any av is sitting on this prim
273 private string m_text = String.Empty; 298 private string m_text = String.Empty;
274 private string m_touchName = String.Empty; 299 private string m_touchName = String.Empty;
275 private readonly List<UndoState> m_undo = new List<UndoState>(5); 300 private UndoRedoState m_UndoRedo = null;
276 private readonly List<UndoState> m_redo = new List<UndoState>(5);
277 301
278 private bool m_passTouches = false; 302 private bool m_passTouches = false;
279 private bool m_passCollisions = false; 303 private bool m_passCollisions = false;
@@ -301,15 +325,20 @@ namespace OpenSim.Region.Framework.Scenes
301 protected Vector3 m_lastVelocity; 325 protected Vector3 m_lastVelocity;
302 protected Vector3 m_lastAcceleration; 326 protected Vector3 m_lastAcceleration;
303 protected Vector3 m_lastAngularVelocity; 327 protected Vector3 m_lastAngularVelocity;
304 protected int m_lastTerseSent; 328 protected int m_lastUpdateSentTime;
329 protected float m_buoyancy = 0.0f;
330 protected Vector3 m_force;
331 protected Vector3 m_torque;
305 332
306 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 333 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
307 // TODO: Implement these 334 protected float m_density = 1000.0f; // in kg/m^3
308 //protected float m_density = 1000.0f; // in kg/m^3 335 protected float m_gravitymod = 1.0f;
309 //protected float m_gravitymod = 1.0f; 336 protected float m_friction = 0.6f; // wood
310 //protected float m_friction = 0.6f; // wood 337 protected float m_bounce = 0.5f; // wood
311 //protected float m_bounce = 0.5f; // wood 338
312 339
340 protected bool m_isSelected = false;
341
313 /// <summary> 342 /// <summary>
314 /// Stores media texture data 343 /// Stores media texture data
315 /// </summary> 344 /// </summary>
@@ -321,10 +350,25 @@ namespace OpenSim.Region.Framework.Scenes
321 private Vector3 m_cameraAtOffset; 350 private Vector3 m_cameraAtOffset;
322 private bool m_forceMouselook; 351 private bool m_forceMouselook;
323 352
324 // TODO: Collision sound should have default. 353
354 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
355 private sbyte m_collisionSoundType;
325 private UUID m_collisionSound; 356 private UUID m_collisionSound;
326 private float m_collisionSoundVolume; 357 private float m_collisionSoundVolume;
327 358
359 private int LastColSoundSentTime;
360
361
362 private SOPVehicle m_vehicleParams = null;
363
364 private KeyframeMotion m_keyframeMotion = null;
365
366 public KeyframeMotion KeyframeMotion
367 {
368 get; set;
369 }
370
371
328 #endregion Fields 372 #endregion Fields
329 373
330// ~SceneObjectPart() 374// ~SceneObjectPart()
@@ -354,6 +398,7 @@ namespace OpenSim.Region.Framework.Scenes
354 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 398 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
355 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 399 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
356 m_inventory = new SceneObjectPartInventory(this); 400 m_inventory = new SceneObjectPartInventory(this);
401 LastColSoundSentTime = Util.EnvironmentTickCount();
357 } 402 }
358 403
359 /// <summary> 404 /// <summary>
@@ -368,7 +413,7 @@ namespace OpenSim.Region.Framework.Scenes
368 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 413 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
369 Quaternion rotationOffset, Vector3 offsetPosition) : this() 414 Quaternion rotationOffset, Vector3 offsetPosition) : this()
370 { 415 {
371 m_name = "Primitive"; 416 m_name = "Object";
372 417
373 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 418 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
374 LastOwnerID = CreatorID = OwnerID = ownerID; 419 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -407,7 +452,7 @@ namespace OpenSim.Region.Framework.Scenes
407 private uint _ownerMask = (uint)PermissionMask.All; 452 private uint _ownerMask = (uint)PermissionMask.All;
408 private uint _groupMask = (uint)PermissionMask.None; 453 private uint _groupMask = (uint)PermissionMask.None;
409 private uint _everyoneMask = (uint)PermissionMask.None; 454 private uint _everyoneMask = (uint)PermissionMask.None;
410 private uint _nextOwnerMask = (uint)PermissionMask.All; 455 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
411 private PrimFlags _flags = PrimFlags.None; 456 private PrimFlags _flags = PrimFlags.None;
412 private DateTime m_expires; 457 private DateTime m_expires;
413 private DateTime m_rezzed; 458 private DateTime m_rezzed;
@@ -501,12 +546,16 @@ namespace OpenSim.Region.Framework.Scenes
501 } 546 }
502 547
503 /// <value> 548 /// <value>
504 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 549 /// Get the inventory list
505 /// </value> 550 /// </value>
506 public TaskInventoryDictionary TaskInventory 551 public TaskInventoryDictionary TaskInventory
507 { 552 {
508 get { return m_inventory.Items; } 553 get {
509 set { m_inventory.Items = value; } 554 return m_inventory.Items;
555 }
556 set {
557 m_inventory.Items = value;
558 }
510 } 559 }
511 560
512 /// <summary> 561 /// <summary>
@@ -556,20 +605,6 @@ namespace OpenSim.Region.Framework.Scenes
556 } 605 }
557 } 606 }
558 607
559 public byte Material
560 {
561 get { return (byte) m_material; }
562 set
563 {
564 m_material = (Material)value;
565
566 PhysicsActor pa = PhysActor;
567
568 if (pa != null)
569 pa.SetMaterial((int)value);
570 }
571 }
572
573 [XmlIgnore] 608 [XmlIgnore]
574 public bool PassTouches 609 public bool PassTouches
575 { 610 {
@@ -595,6 +630,18 @@ namespace OpenSim.Region.Framework.Scenes
595 } 630 }
596 } 631 }
597 632
633 public bool IsSelected
634 {
635 get { return m_isSelected; }
636 set
637 {
638 m_isSelected = value;
639 if (ParentGroup != null)
640 ParentGroup.PartSelectChanged(value);
641 }
642 }
643
644
598 public Dictionary<int, string> CollisionFilter 645 public Dictionary<int, string> CollisionFilter
599 { 646 {
600 get { return m_CollisionFilter; } 647 get { return m_CollisionFilter; }
@@ -663,14 +710,12 @@ namespace OpenSim.Region.Framework.Scenes
663 set { m_LoopSoundSlavePrims = value; } 710 set { m_LoopSoundSlavePrims = value; }
664 } 711 }
665 712
666
667 public Byte[] TextureAnimation 713 public Byte[] TextureAnimation
668 { 714 {
669 get { return m_TextureAnimation; } 715 get { return m_TextureAnimation; }
670 set { m_TextureAnimation = value; } 716 set { m_TextureAnimation = value; }
671 } 717 }
672 718
673
674 public Byte[] ParticleSystem 719 public Byte[] ParticleSystem
675 { 720 {
676 get { return m_particleSystem; } 721 get { return m_particleSystem; }
@@ -707,9 +752,12 @@ namespace OpenSim.Region.Framework.Scenes
707 { 752 {
708 // If this is a linkset, we don't want the physics engine mucking up our group position here. 753 // If this is a linkset, we don't want the physics engine mucking up our group position here.
709 PhysicsActor actor = PhysActor; 754 PhysicsActor actor = PhysActor;
710 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 755 if (ParentID == 0)
711 if (actor != null && ParentID == 0) 756 {
712 m_groupPosition = actor.Position; 757 if (actor != null)
758 m_groupPosition = actor.Position;
759 return m_groupPosition;
760 }
713 761
714 // If I'm an attachment, my position is reported as the position of who I'm attached to 762 // If I'm an attachment, my position is reported as the position of who I'm attached to
715 if (ParentGroup.IsAttachment) 763 if (ParentGroup.IsAttachment)
@@ -719,14 +767,16 @@ namespace OpenSim.Region.Framework.Scenes
719 return sp.AbsolutePosition; 767 return sp.AbsolutePosition;
720 } 768 }
721 769
770 // use root prim's group position. Physics may have updated it
771 if (ParentGroup.RootPart != this)
772 m_groupPosition = ParentGroup.RootPart.GroupPosition;
722 return m_groupPosition; 773 return m_groupPosition;
723 } 774 }
724 set 775 set
725 { 776 {
726 m_groupPosition = value; 777 m_groupPosition = value;
727
728 PhysicsActor actor = PhysActor; 778 PhysicsActor actor = PhysActor;
729 if (actor != null) 779 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
730 { 780 {
731 try 781 try
732 { 782 {
@@ -750,16 +800,6 @@ namespace OpenSim.Region.Framework.Scenes
750 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); 800 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
751 } 801 }
752 } 802 }
753
754 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
755 if (SitTargetAvatar != UUID.Zero)
756 {
757 ScenePresence avatar;
758 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
759 {
760 avatar.ParentPosition = GetWorldPosition();
761 }
762 }
763 } 803 }
764 } 804 }
765 805
@@ -768,7 +808,7 @@ namespace OpenSim.Region.Framework.Scenes
768 get { return m_offsetPosition; } 808 get { return m_offsetPosition; }
769 set 809 set
770 { 810 {
771// StoreUndoState(); 811 Vector3 oldpos = m_offsetPosition;
772 m_offsetPosition = value; 812 m_offsetPosition = value;
773 813
774 if (ParentGroup != null && !ParentGroup.IsDeleted) 814 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -780,10 +820,25 @@ namespace OpenSim.Region.Framework.Scenes
780 actor.Orientation = GetWorldRotation(); 820 actor.Orientation = GetWorldRotation();
781 821
782 // Tell the physics engines that this prim changed. 822 // Tell the physics engines that this prim changed.
783 if (ParentGroup.Scene != null) 823 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
784 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 824 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
785 } 825 }
826
827 if (!m_parentGroup.m_dupeInProgress)
828 {
829 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
830 foreach (ScenePresence av in avs)
831 {
832 if (av.ParentID == m_localId)
833 {
834 Vector3 offset = (m_offsetPosition - oldpos);
835 av.AbsolutePosition += offset;
836 av.SendAvatarDataToAllAgents();
837 }
838 }
839 }
786 } 840 }
841 TriggerScriptChangedEvent(Changed.POSITION);
787 } 842 }
788 } 843 }
789 844
@@ -834,7 +889,7 @@ namespace OpenSim.Region.Framework.Scenes
834 889
835 set 890 set
836 { 891 {
837 StoreUndoState(); 892// StoreUndoState();
838 m_rotationOffset = value; 893 m_rotationOffset = value;
839 894
840 PhysicsActor actor = PhysActor; 895 PhysicsActor actor = PhysActor;
@@ -922,19 +977,36 @@ namespace OpenSim.Region.Framework.Scenes
922 get 977 get
923 { 978 {
924 PhysicsActor actor = PhysActor; 979 PhysicsActor actor = PhysActor;
925 if ((actor != null) && actor.IsPhysical) 980 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
926 { 981 {
927 m_angularVelocity = actor.RotationalVelocity; 982 m_angularVelocity = actor.RotationalVelocity;
928 } 983 }
929 return m_angularVelocity; 984 return m_angularVelocity;
930 } 985 }
931 set { m_angularVelocity = value; } 986 set
987 {
988 m_angularVelocity = value;
989 PhysicsActor actor = PhysActor;
990 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE)
991 {
992 actor.RotationalVelocity = m_angularVelocity;
993 }
994 }
932 } 995 }
933 996
934 /// <summary></summary> 997 /// <summary></summary>
935 public Vector3 Acceleration 998 public Vector3 Acceleration
936 { 999 {
937 get { return m_acceleration; } 1000 get
1001 {
1002 PhysicsActor actor = PhysActor;
1003 if (actor != null)
1004 {
1005 m_acceleration = actor.Acceleration;
1006 }
1007 return m_acceleration;
1008 }
1009
938 set { m_acceleration = value; } 1010 set { m_acceleration = value; }
939 } 1011 }
940 1012
@@ -1002,7 +1074,10 @@ namespace OpenSim.Region.Framework.Scenes
1002 public PrimitiveBaseShape Shape 1074 public PrimitiveBaseShape Shape
1003 { 1075 {
1004 get { return m_shape; } 1076 get { return m_shape; }
1005 set { m_shape = value;} 1077 set
1078 {
1079 m_shape = value;
1080 }
1006 } 1081 }
1007 1082
1008 /// <summary> 1083 /// <summary>
@@ -1015,7 +1090,6 @@ namespace OpenSim.Region.Framework.Scenes
1015 { 1090 {
1016 if (m_shape != null) 1091 if (m_shape != null)
1017 { 1092 {
1018 StoreUndoState();
1019 1093
1020 m_shape.Scale = value; 1094 m_shape.Scale = value;
1021 1095
@@ -1042,6 +1116,7 @@ namespace OpenSim.Region.Framework.Scenes
1042 } 1116 }
1043 1117
1044 public UpdateRequired UpdateFlag { get; set; } 1118 public UpdateRequired UpdateFlag { get; set; }
1119 public bool UpdatePhysRequired { get; set; }
1045 1120
1046 /// <summary> 1121 /// <summary>
1047 /// Used for media on a prim. 1122 /// Used for media on a prim.
@@ -1082,10 +1157,7 @@ namespace OpenSim.Region.Framework.Scenes
1082 { 1157 {
1083 get 1158 get
1084 { 1159 {
1085 if (ParentGroup.IsAttachment) 1160 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1086 return GroupPosition;
1087
1088 return m_offsetPosition + m_groupPosition;
1089 } 1161 }
1090 } 1162 }
1091 1163
@@ -1263,6 +1335,13 @@ namespace OpenSim.Region.Framework.Scenes
1263 _flags = value; 1335 _flags = value;
1264 } 1336 }
1265 } 1337 }
1338
1339 [XmlIgnore]
1340 public bool IsOccupied // KF If an av is sittingon this prim
1341 {
1342 get { return m_occupied; }
1343 set { m_occupied = value; }
1344 }
1266 1345
1267 /// <summary> 1346 /// <summary>
1268 /// 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 1347 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
@@ -1313,12 +1392,41 @@ namespace OpenSim.Region.Framework.Scenes
1313 set { m_sitAnimation = value; } 1392 set { m_sitAnimation = value; }
1314 } 1393 }
1315 1394
1395 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1396
1397 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1398 // runtime thing.. do not persist
1399 [XmlIgnore]
1400 public sbyte CollisionSoundType
1401 {
1402 get
1403 {
1404 return m_collisionSoundType;
1405 }
1406 set
1407 {
1408 m_collisionSoundType = value;
1409 if (value == -1)
1410 m_collisionSound = invalidCollisionSoundUUID;
1411 else if (value == 0)
1412 m_collisionSound = UUID.Zero;
1413 }
1414 }
1415
1316 public UUID CollisionSound 1416 public UUID CollisionSound
1317 { 1417 {
1318 get { return m_collisionSound; } 1418 get { return m_collisionSound; }
1319 set 1419 set
1320 { 1420 {
1321 m_collisionSound = value; 1421 m_collisionSound = value;
1422
1423 if (value == invalidCollisionSoundUUID)
1424 m_collisionSoundType = -1;
1425 else if (value == UUID.Zero)
1426 m_collisionSoundType = 0;
1427 else
1428 m_collisionSoundType = 1;
1429
1322 aggregateScriptEvents(); 1430 aggregateScriptEvents();
1323 } 1431 }
1324 } 1432 }
@@ -1329,6 +1437,125 @@ namespace OpenSim.Region.Framework.Scenes
1329 set { m_collisionSoundVolume = value; } 1437 set { m_collisionSoundVolume = value; }
1330 } 1438 }
1331 1439
1440 public float Buoyancy
1441 {
1442 get
1443 {
1444 if (ParentGroup.RootPart == this)
1445 return m_buoyancy;
1446
1447 return ParentGroup.RootPart.Buoyancy;
1448 }
1449 set
1450 {
1451 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1452 {
1453 ParentGroup.RootPart.Buoyancy = value;
1454 return;
1455 }
1456 m_buoyancy = value;
1457 if (PhysActor != null)
1458 PhysActor.Buoyancy = value;
1459 }
1460 }
1461
1462 public Vector3 Force
1463 {
1464 get
1465 {
1466 if (ParentGroup.RootPart == this)
1467 return m_force;
1468
1469 return ParentGroup.RootPart.Force;
1470 }
1471
1472 set
1473 {
1474 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1475 {
1476 ParentGroup.RootPart.Force = value;
1477 return;
1478 }
1479 m_force = value;
1480 if (PhysActor != null)
1481 PhysActor.Force = value;
1482 }
1483 }
1484
1485 public Vector3 Torque
1486 {
1487 get
1488 {
1489 if (ParentGroup.RootPart == this)
1490 return m_torque;
1491
1492 return ParentGroup.RootPart.Torque;
1493 }
1494
1495 set
1496 {
1497 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1498 {
1499 ParentGroup.RootPart.Torque = value;
1500 return;
1501 }
1502 m_torque = value;
1503 if (PhysActor != null)
1504 PhysActor.Torque = value;
1505 }
1506 }
1507
1508 public byte Material
1509 {
1510 get { return (byte)m_material; }
1511 set
1512 {
1513 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1514 {
1515 bool update = false;
1516
1517 if (m_material != (Material)value)
1518 {
1519 update = true;
1520 m_material = (Material)value;
1521 }
1522
1523 if (m_friction != SOPMaterialData.friction(m_material))
1524 {
1525 update = true;
1526 m_friction = SOPMaterialData.friction(m_material);
1527 }
1528
1529 if (m_bounce != SOPMaterialData.bounce(m_material))
1530 {
1531 update = true;
1532 m_bounce = SOPMaterialData.bounce(m_material);
1533 }
1534
1535 if (update)
1536 {
1537 if (PhysActor != null)
1538 {
1539 PhysActor.SetMaterial((int)value);
1540 }
1541 if(ParentGroup != null)
1542 ParentGroup.HasGroupChanged = true;
1543 ScheduleFullUpdateIfNone();
1544 UpdatePhysRequired = true;
1545 }
1546 }
1547 }
1548 }
1549
1550 // not a propriety to move to methods place later
1551 private bool HasMesh()
1552 {
1553 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1554 return true;
1555 return false;
1556 }
1557
1558 // not a propriety to move to methods place later
1332 public byte DefaultPhysicsShapeType() 1559 public byte DefaultPhysicsShapeType()
1333 { 1560 {
1334 byte type; 1561 byte type;
@@ -1341,6 +1568,65 @@ namespace OpenSim.Region.Framework.Scenes
1341 return type; 1568 return type;
1342 } 1569 }
1343 1570
1571 [XmlIgnore]
1572 public bool UsesComplexCost
1573 {
1574 get
1575 {
1576 byte pst = PhysicsShapeType;
1577 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1578 return true;
1579 return false;
1580 }
1581 }
1582
1583 [XmlIgnore]
1584 public float PhysicsCost
1585 {
1586 get
1587 {
1588 if(PhysicsShapeType == (byte)PhysShapeType.none)
1589 return 0;
1590
1591 float cost = 0.1f;
1592 if (PhysActor != null)
1593 cost = PhysActor.PhysicsCost;
1594 else
1595 cost = 0.1f;
1596
1597 if ((Flags & PrimFlags.Physics) != 0)
1598 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1599 return cost;
1600 }
1601 }
1602
1603 [XmlIgnore]
1604 public float StreamingCost
1605 {
1606 get
1607 {
1608 float cost;
1609 if (PhysActor != null)
1610 cost = PhysActor.StreamCost;
1611 else
1612 cost = 1.0f;
1613 return 1.0f;
1614 }
1615 }
1616
1617 [XmlIgnore]
1618 public float SimulationCost
1619 {
1620 get
1621 {
1622 // ignoring scripts. Don't like considering them for this
1623 if((Flags & PrimFlags.Physics) != 0)
1624 return 1.0f;
1625
1626 return 0.5f;
1627 }
1628 }
1629
1344 public byte PhysicsShapeType 1630 public byte PhysicsShapeType
1345 { 1631 {
1346 get { return m_physicsShapeType; } 1632 get { return m_physicsShapeType; }
@@ -1374,23 +1660,100 @@ namespace OpenSim.Region.Framework.Scenes
1374 } 1660 }
1375 else if (PhysActor == null) 1661 else if (PhysActor == null)
1376 { 1662 {
1377 ApplyPhysics((uint)Flags, VolumeDetectActive); 1663 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1664 UpdatePhysicsSubscribedEvents();
1378 } 1665 }
1379 else 1666 else
1380 { 1667 {
1381 // TODO: Update physics actor 1668 PhysActor.PhysicsShapeType = m_physicsShapeType;
1669// if (Shape.SculptEntry)
1670// CheckSculptAndLoad();
1382 } 1671 }
1383 1672
1384 if (ParentGroup != null) 1673 if (ParentGroup != null)
1385 ParentGroup.HasGroupChanged = true; 1674 ParentGroup.HasGroupChanged = true;
1386 } 1675 }
1676
1677 if (m_physicsShapeType != value)
1678 {
1679 UpdatePhysRequired = true;
1680 }
1681 }
1682 }
1683
1684 public float Density // in kg/m^3
1685 {
1686 get { return m_density; }
1687 set
1688 {
1689 if (value >=1 && value <= 22587.0)
1690 {
1691 m_density = value;
1692 UpdatePhysRequired = true;
1693 }
1694
1695 ScheduleFullUpdateIfNone();
1696
1697 if (ParentGroup != null)
1698 ParentGroup.HasGroupChanged = true;
1699 }
1700 }
1701
1702 public float GravityModifier
1703 {
1704 get { return m_gravitymod; }
1705 set
1706 {
1707 if( value >= -1 && value <=28.0f)
1708 {
1709 m_gravitymod = value;
1710 UpdatePhysRequired = true;
1711 }
1712
1713 ScheduleFullUpdateIfNone();
1714
1715 if (ParentGroup != null)
1716 ParentGroup.HasGroupChanged = true;
1717
1718 }
1719 }
1720
1721 public float Friction
1722 {
1723 get { return m_friction; }
1724 set
1725 {
1726 if (value >= 0 && value <= 255.0f)
1727 {
1728 m_friction = value;
1729 UpdatePhysRequired = true;
1730 }
1731
1732 ScheduleFullUpdateIfNone();
1733
1734 if (ParentGroup != null)
1735 ParentGroup.HasGroupChanged = true;
1736 }
1737 }
1738
1739 public float Restitution
1740 {
1741 get { return m_bounce; }
1742 set
1743 {
1744 if (value >= 0 && value <= 1.0f)
1745 {
1746 m_bounce = value;
1747 UpdatePhysRequired = true;
1748 }
1749
1750 ScheduleFullUpdateIfNone();
1751
1752 if (ParentGroup != null)
1753 ParentGroup.HasGroupChanged = true;
1387 } 1754 }
1388 } 1755 }
1389 1756
1390 public float Density { get; set; }
1391 public float GravityModifier { get; set; }
1392 public float Friction { get; set; }
1393 public float Restitution { get; set; }
1394 1757
1395 #endregion Public Properties with only Get 1758 #endregion Public Properties with only Get
1396 1759
@@ -1537,6 +1900,61 @@ namespace OpenSim.Region.Framework.Scenes
1537 } 1900 }
1538 } 1901 }
1539 1902
1903 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1904 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1905 {
1906 if (ParentGroup == null || ParentGroup.IsDeleted)
1907 return;
1908
1909 if (ParentGroup.IsAttachment)
1910 return; // don't work on attachments (for now ??)
1911
1912 SceneObjectPart root = ParentGroup.RootPart;
1913
1914 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
1915 return;
1916
1917 PhysicsActor pa = root.PhysActor;
1918
1919 if (pa == null || !pa.IsPhysical)
1920 return;
1921
1922 if (localGlobalTF)
1923 {
1924 pVel = pVel * GetWorldRotation();
1925 }
1926
1927 ParentGroup.Velocity = pVel;
1928 }
1929
1930 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
1931 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
1932 {
1933 if (ParentGroup == null || ParentGroup.IsDeleted)
1934 return;
1935
1936 if (ParentGroup.IsAttachment)
1937 return; // don't work on attachments (for now ??)
1938
1939 SceneObjectPart root = ParentGroup.RootPart;
1940
1941 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
1942 return;
1943
1944 PhysicsActor pa = root.PhysActor;
1945
1946 if (pa == null || !pa.IsPhysical)
1947 return;
1948
1949 if (localGlobalTF)
1950 {
1951 pAngVel = pAngVel * GetWorldRotation();
1952 }
1953
1954 root.AngularVelocity = pAngVel;
1955 }
1956
1957
1540 /// <summary> 1958 /// <summary>
1541 /// hook to the physics scene to apply angular impulse 1959 /// hook to the physics scene to apply angular impulse
1542 /// This is sent up to the group, which then finds the root prim 1960 /// This is sent up to the group, which then finds the root prim
@@ -1557,7 +1975,7 @@ namespace OpenSim.Region.Framework.Scenes
1557 impulse = newimpulse; 1975 impulse = newimpulse;
1558 } 1976 }
1559 1977
1560 ParentGroup.applyAngularImpulse(impulse); 1978 ParentGroup.ApplyAngularImpulse(impulse);
1561 } 1979 }
1562 1980
1563 /// <summary> 1981 /// <summary>
@@ -1567,20 +1985,24 @@ namespace OpenSim.Region.Framework.Scenes
1567 /// </summary> 1985 /// </summary>
1568 /// <param name="impulsei">Vector force</param> 1986 /// <param name="impulsei">Vector force</param>
1569 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1987 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1570 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1988
1989 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1990 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1571 { 1991 {
1572 Vector3 impulse = impulsei; 1992 Vector3 torque = torquei;
1573 1993
1574 if (localGlobalTF) 1994 if (localGlobalTF)
1575 { 1995 {
1996/*
1576 Quaternion grot = GetWorldRotation(); 1997 Quaternion grot = GetWorldRotation();
1577 Quaternion AXgrot = grot; 1998 Quaternion AXgrot = grot;
1578 Vector3 AXimpulsei = impulsei; 1999 Vector3 AXimpulsei = impulsei;
1579 Vector3 newimpulse = AXimpulsei * AXgrot; 2000 Vector3 newimpulse = AXimpulsei * AXgrot;
1580 impulse = newimpulse; 2001 */
2002 torque *= GetWorldRotation();
1581 } 2003 }
1582 2004
1583 ParentGroup.setAngularImpulse(impulse); 2005 Torque = torque;
1584 } 2006 }
1585 2007
1586 /// <summary> 2008 /// <summary>
@@ -1588,16 +2010,23 @@ namespace OpenSim.Region.Framework.Scenes
1588 /// </summary> 2010 /// </summary>
1589 /// <param name="rootObjectFlags"></param> 2011 /// <param name="rootObjectFlags"></param>
1590 /// <param name="VolumeDetectActive"></param> 2012 /// <param name="VolumeDetectActive"></param>
1591 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 2013 /// <param name="building"></param>
2014
2015 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1592 { 2016 {
2017 VolumeDetectActive = _VolumeDetectActive;
2018
1593 if (!ParentGroup.Scene.CollidablePrims) 2019 if (!ParentGroup.Scene.CollidablePrims)
1594 return; 2020 return;
1595 2021
1596 if (PhysicsShapeType == (byte)PhysShapeType.none) 2022 if (PhysicsShapeType == (byte)PhysShapeType.none)
1597 return; 2023 return;
1598 2024
1599 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2025 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1600 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2026 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
2027
2028 if (_VolumeDetectActive)
2029 isPhantom = true;
1601 2030
1602 if (IsJoint()) 2031 if (IsJoint())
1603 { 2032 {
@@ -1605,22 +2034,14 @@ namespace OpenSim.Region.Framework.Scenes
1605 } 2034 }
1606 else 2035 else
1607 { 2036 {
1608 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 2037 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1609 if (VolumeDetectActive) 2038 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1610 isPhantom = false;
1611
1612 // 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
1613 // or flexible
1614 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1615 { 2039 {
1616 // Added clarification.. since A rigid body is an object that you can kick around, etc. 2040 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1617 bool rigidBody = isPhysical && !isPhantom; 2041 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1618
1619 PhysicsActor pa = AddToPhysics(rigidBody);
1620
1621 if (pa != null)
1622 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1623 } 2042 }
2043 else
2044 PhysActor = null; // just to be sure
1624 } 2045 }
1625 } 2046 }
1626 2047
@@ -1672,6 +2093,12 @@ namespace OpenSim.Region.Framework.Scenes
1672 dupe.Category = Category; 2093 dupe.Category = Category;
1673 dupe.m_rezzed = m_rezzed; 2094 dupe.m_rezzed = m_rezzed;
1674 2095
2096 dupe.m_UndoRedo = null;
2097 dupe.m_isSelected = false;
2098
2099 dupe.IgnoreUndoUpdate = false;
2100 dupe.Undoing = false;
2101
1675 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2102 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1676 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2103 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1677 2104
@@ -1687,6 +2114,7 @@ namespace OpenSim.Region.Framework.Scenes
1687 2114
1688 // Move afterwards ResetIDs as it clears the localID 2115 // Move afterwards ResetIDs as it clears the localID
1689 dupe.LocalId = localID; 2116 dupe.LocalId = localID;
2117
1690 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2118 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1691 dupe.LastOwnerID = OwnerID; 2119 dupe.LastOwnerID = OwnerID;
1692 2120
@@ -1694,6 +2122,9 @@ namespace OpenSim.Region.Framework.Scenes
1694 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2122 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1695 dupe.Shape.ExtraParams = extraP; 2123 dupe.Shape.ExtraParams = extraP;
1696 2124
2125 // safeguard actual copy is done in sog.copy
2126 dupe.KeyframeMotion = null;
2127
1697 dupe.DynAttrs.CopyFrom(DynAttrs); 2128 dupe.DynAttrs.CopyFrom(DynAttrs);
1698 2129
1699 if (userExposed) 2130 if (userExposed)
@@ -1707,8 +2138,12 @@ namespace OpenSim.Region.Framework.Scenes
1707*/ 2138*/
1708 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2139 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1709 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2140 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2141// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1710 } 2142 }
1711 2143
2144 if (dupe.PhysActor != null)
2145 dupe.PhysActor.LocalID = localID;
2146
1712 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2147 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1713 2148
1714// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2149// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1727,10 +2162,10 @@ namespace OpenSim.Region.Framework.Scenes
1727 { 2162 {
1728 if (asset != null) 2163 if (asset != null)
1729 SculptTextureCallback(asset); 2164 SculptTextureCallback(asset);
1730 else 2165// else
1731 m_log.WarnFormat( 2166// m_log.WarnFormat(
1732 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2167// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1733 Name, UUID, id); 2168// Name, UUID, id);
1734 } 2169 }
1735*/ 2170*/
1736 /// <summary> 2171 /// <summary>
@@ -1829,6 +2264,7 @@ namespace OpenSim.Region.Framework.Scenes
1829 2264
1830 /// <summary> 2265 /// <summary>
1831 /// Do a physics propery update for this part. 2266 /// Do a physics propery update for this part.
2267 /// now also updates phantom and volume detector
1832 /// </summary> 2268 /// </summary>
1833 /// <param name="UsePhysics"></param> 2269 /// <param name="UsePhysics"></param>
1834 /// <param name="isNew"></param> 2270 /// <param name="isNew"></param>
@@ -1854,61 +2290,69 @@ namespace OpenSim.Region.Framework.Scenes
1854 { 2290 {
1855 if (pa.IsPhysical) // implies UsePhysics==false for this block 2291 if (pa.IsPhysical) // implies UsePhysics==false for this block
1856 { 2292 {
1857 if (!isNew) 2293 if (!isNew) // implies UsePhysics==false for this block
2294 {
1858 ParentGroup.Scene.RemovePhysicalPrim(1); 2295 ParentGroup.Scene.RemovePhysicalPrim(1);
1859 2296
1860 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2297 Velocity = new Vector3(0, 0, 0);
1861 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2298 Acceleration = new Vector3(0, 0, 0);
1862 pa.delink(); 2299 if (ParentGroup.RootPart == this)
2300 AngularVelocity = new Vector3(0, 0, 0);
1863 2301
1864 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2302 if (pa.Phantom && !VolumeDetectActive)
1865 { 2303 {
1866 // destroy all joints connected to this now deactivated body 2304 RemoveFromPhysics();
1867 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2305 return;
1868 } 2306 }
1869 2307
1870 // stop client-side interpolation of all joint proxy objects that have just been deleted 2308 pa.IsPhysical = UsePhysics;
1871 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2309 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1872 // which stops client-side interpolation of deactivated joint proxy objects. 2310 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2311 pa.delink();
2312 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2313 {
2314 // destroy all joints connected to this now deactivated body
2315 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2316 }
2317 }
1873 } 2318 }
1874 2319
1875 if (!UsePhysics && !isNew) 2320 if (pa.IsPhysical != UsePhysics)
1876 { 2321 pa.IsPhysical = UsePhysics;
1877 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1878 // prim still has velocity and continues to interpolate its position along the old
1879 // velocity-vector.
1880 Velocity = new Vector3(0, 0, 0);
1881 Acceleration = new Vector3(0, 0, 0);
1882 AngularVelocity = new Vector3(0, 0, 0);
1883 //RotationalVelocity = new Vector3(0, 0, 0);
1884 }
1885 2322
1886 pa.IsPhysical = UsePhysics; 2323 if (UsePhysics)
2324 {
2325 if (ParentGroup.RootPart.KeyframeMotion != null)
2326 ParentGroup.RootPart.KeyframeMotion.Stop();
2327 ParentGroup.RootPart.KeyframeMotion = null;
2328 ParentGroup.Scene.AddPhysicalPrim(1);
1887 2329
1888 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2330 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1889 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2331 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1890 /// that's not wholesome. Had to make Scene public
1891 //PhysActor = null;
1892 2332
1893 if ((Flags & PrimFlags.Phantom) == 0) 2333 if (ParentID != 0 && ParentID != LocalId)
1894 {
1895 if (UsePhysics)
1896 { 2334 {
1897 ParentGroup.Scene.AddPhysicalPrim(1); 2335 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1898 2336
1899 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2337 if (parentPa != null)
1900 pa.OnOutOfBounds += PhysicsOutOfBounds;
1901 if (ParentID != 0 && ParentID != LocalId)
1902 { 2338 {
1903 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2339 pa.link(parentPa);
1904
1905 if (parentPa != null)
1906 {
1907 pa.link(parentPa);
1908 }
1909 } 2340 }
1910 } 2341 }
1911 } 2342 }
2343 }
2344
2345 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2346 if (pa.Phantom != phan)
2347 pa.Phantom = phan;
2348
2349// some engines dont' have this check still
2350// if (VolumeDetectActive != pa.IsVolumeDtc)
2351 {
2352 if (VolumeDetectActive)
2353 pa.SetVolumeDetect(1);
2354 else
2355 pa.SetVolumeDetect(0);
1912 } 2356 }
1913 2357
1914 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2358 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -2027,42 +2471,63 @@ namespace OpenSim.Region.Framework.Scenes
2027 2471
2028 public Vector3 GetGeometricCenter() 2472 public Vector3 GetGeometricCenter()
2029 { 2473 {
2474 // this is not real geometric center but a average of positions relative to root prim acording to
2475 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2476 // ignoring tortured prims details since sl also seems to ignore
2477 // so no real use in doing it on physics
2478 if (ParentGroup.IsDeleted)
2479 return new Vector3(0, 0, 0);
2480
2481 return ParentGroup.GetGeometricCenter();
2482 }
2483
2484 public float GetMass()
2485 {
2030 PhysicsActor pa = PhysActor; 2486 PhysicsActor pa = PhysActor;
2031 2487
2032 if (pa != null) 2488 if (pa != null)
2033 return new Vector3(pa.GeometricCenter.X, pa.GeometricCenter.Y, pa.GeometricCenter.Z); 2489 return pa.Mass;
2034 else 2490 else
2035 return new Vector3(0, 0, 0); 2491 return 0;
2036 } 2492 }
2037 2493
2038 public Vector3 GetCenterOfMass() 2494 public Vector3 GetCenterOfMass()
2039 { 2495 {
2496 if (ParentGroup.RootPart == this)
2497 {
2498 if (ParentGroup.IsDeleted)
2499 return AbsolutePosition;
2500 return ParentGroup.GetCenterOfMass();
2501 }
2502
2040 PhysicsActor pa = PhysActor; 2503 PhysicsActor pa = PhysActor;
2041 2504
2042 if (pa != null) 2505 if (pa != null)
2043 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2506 {
2507 Vector3 tmp = pa.CenterOfMass;
2508 return tmp;
2509 }
2044 else 2510 else
2045 return new Vector3(0, 0, 0); 2511 return AbsolutePosition;
2046 } 2512 }
2047 2513
2048 public float GetMass() 2514 public Vector3 GetPartCenterOfMass()
2049 { 2515 {
2050 PhysicsActor pa = PhysActor; 2516 PhysicsActor pa = PhysActor;
2051 2517
2052 if (pa != null) 2518 if (pa != null)
2053 return pa.Mass; 2519 {
2520 Vector3 tmp = pa.CenterOfMass;
2521 return tmp;
2522 }
2054 else 2523 else
2055 return 0; 2524 return AbsolutePosition;
2056 } 2525 }
2057 2526
2527
2058 public Vector3 GetForce() 2528 public Vector3 GetForce()
2059 { 2529 {
2060 PhysicsActor pa = PhysActor; 2530 return Force;
2061
2062 if (pa != null)
2063 return pa.Force;
2064 else
2065 return Vector3.Zero;
2066 } 2531 }
2067 2532
2068 /// <summary> 2533 /// <summary>
@@ -2277,15 +2742,25 @@ namespace OpenSim.Region.Framework.Scenes
2277 2742
2278 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2743 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2279 { 2744 {
2280 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2745 bool sendToRoot = true;
2281 { 2746
2282 ColliderArgs LandCollidingMessage = new ColliderArgs(); 2747 ColliderArgs LandCollidingMessage = new ColliderArgs();
2283 List<DetectedObject> colliding = new List<DetectedObject>(); 2748 List<DetectedObject> colliding = new List<DetectedObject>();
2284 2749
2285 colliding.Add(CreateDetObjectForGround()); 2750 colliding.Add(CreateDetObjectForGround());
2286 LandCollidingMessage.Colliders = colliding; 2751 LandCollidingMessage.Colliders = colliding;
2287 2752
2753 if (Inventory.ContainsScripts())
2754 {
2755 if (!PassCollisions)
2756 sendToRoot = false;
2757 }
2758 if ((ScriptEvents & ev) != 0)
2288 notify(LocalId, LandCollidingMessage); 2759 notify(LocalId, LandCollidingMessage);
2760
2761 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2762 {
2763 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2289 } 2764 }
2290 } 2765 }
2291 2766
@@ -2301,57 +2776,120 @@ namespace OpenSim.Region.Framework.Scenes
2301 List<uint> endedColliders = new List<uint>(); 2776 List<uint> endedColliders = new List<uint>();
2302 List<uint> startedColliders = new List<uint>(); 2777 List<uint> startedColliders = new List<uint>();
2303 2778
2304 // calculate things that started colliding this time 2779 if (collissionswith.Count == 0)
2305 // and build up list of colliders this time
2306 foreach (uint localid in collissionswith.Keys)
2307 { 2780 {
2308 thisHitColliders.Add(localid); 2781 if (m_lastColliders.Count == 0)
2309 if (!m_lastColliders.Contains(localid)) 2782 return; // nothing to do
2310 startedColliders.Add(localid);
2311 }
2312 2783
2313 // calculate things that ended colliding 2784 foreach (uint localID in m_lastColliders)
2314 foreach (uint localID in m_lastColliders) 2785 {
2315 {
2316 if (!thisHitColliders.Contains(localID))
2317 endedColliders.Add(localID); 2786 endedColliders.Add(localID);
2787 }
2788 m_lastColliders.Clear();
2318 } 2789 }
2319 2790
2320 //add the items that started colliding this time to the last colliders list. 2791 else
2321 foreach (uint localID in startedColliders) 2792 {
2322 m_lastColliders.Add(localID); 2793 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2323 2794
2324 // remove things that ended colliding from the last colliders list 2795 // calculate things that started colliding this time
2325 foreach (uint localID in endedColliders) 2796 // and build up list of colliders this time
2326 m_lastColliders.Remove(localID); 2797 if (!VolumeDetectActive && CollisionSoundType >= 0)
2798 {
2799 CollisionForSoundInfo soundinfo;
2800 ContactPoint curcontact;
2327 2801
2328 // play the sound. 2802 foreach (uint id in collissionswith.Keys)
2329 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2803 {
2330 { 2804 thisHitColliders.Add(id);
2331 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2805 if (!m_lastColliders.Contains(id))
2332 if (soundModule != null) 2806 {
2807 startedColliders.Add(id);
2808
2809 curcontact = collissionswith[id];
2810 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2811 {
2812 soundinfo = new CollisionForSoundInfo();
2813 soundinfo.colliderID = id;
2814 soundinfo.position = curcontact.Position;
2815 soundinfo.relativeVel = curcontact.RelativeSpeed;
2816 soundinfolist.Add(soundinfo);
2817 }
2818 }
2819 }
2820 }
2821 else
2333 { 2822 {
2334 soundModule.SendSound(UUID, CollisionSound, 2823 foreach (uint id in collissionswith.Keys)
2335 CollisionSoundVolume, true, (byte)0, 0, false, 2824 {
2336 false); 2825 thisHitColliders.Add(id);
2826 if (!m_lastColliders.Contains(id))
2827 startedColliders.Add(id);
2828 }
2829 }
2830
2831 // calculate things that ended colliding
2832 foreach (uint localID in m_lastColliders)
2833 {
2834 if (!thisHitColliders.Contains(localID))
2835 endedColliders.Add(localID);
2337 } 2836 }
2837
2838 //add the items that started colliding this time to the last colliders list.
2839 foreach (uint localID in startedColliders)
2840 m_lastColliders.Add(localID);
2841
2842 // remove things that ended colliding from the last colliders list
2843 foreach (uint localID in endedColliders)
2844 m_lastColliders.Remove(localID);
2845
2846 // play sounds.
2847 if (soundinfolist.Count > 0)
2848 CollisionSounds.PartCollisionSound(this, soundinfolist);
2338 } 2849 }
2339 2850
2340 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2851 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2341 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2852 if (!VolumeDetectActive)
2853 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2342 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2854 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2343 2855
2344 if (startedColliders.Contains(0)) 2856 if (startedColliders.Contains(0))
2345 { 2857 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2346 if (m_lastColliders.Contains(0)) 2858 if (m_lastColliders.Contains(0))
2347 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2859 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2348 else
2349 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2350 }
2351 if (endedColliders.Contains(0)) 2860 if (endedColliders.Contains(0))
2352 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2861 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2353 } 2862 }
2354 2863
2864 // The Collision sounds code calls this
2865 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2866 {
2867 if (soundID == UUID.Zero)
2868 return;
2869
2870 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2871 if (soundModule == null)
2872 return;
2873
2874 if (volume > 1)
2875 volume = 1;
2876 if (volume < 0)
2877 volume = 0;
2878
2879 int now = Util.EnvironmentTickCount();
2880 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2881 return;
2882
2883 LastColSoundSentTime = now;
2884
2885 UUID ownerID = OwnerID;
2886 UUID objectID = ParentGroup.RootPart.UUID;
2887 UUID parentID = ParentGroup.UUID;
2888 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2889
2890 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2891 }
2892
2355 public void PhysicsOutOfBounds(Vector3 pos) 2893 public void PhysicsOutOfBounds(Vector3 pos)
2356 { 2894 {
2357 // Note: This is only being called on the root prim at this time. 2895 // Note: This is only being called on the root prim at this time.
@@ -2373,9 +2911,9 @@ namespace OpenSim.Region.Framework.Scenes
2373 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2911 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2374 2912
2375 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2913 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2376 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2914 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2377 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2915 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2378 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2916 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2379 { 2917 {
2380 ParentGroup.AbsolutePosition = newpos; 2918 ParentGroup.AbsolutePosition = newpos;
2381 return; 2919 return;
@@ -2502,6 +3040,19 @@ namespace OpenSim.Region.Framework.Scenes
2502 APIDTarget = Quaternion.Identity; 3040 APIDTarget = Quaternion.Identity;
2503 } 3041 }
2504 3042
3043
3044
3045 public void ScheduleFullUpdateIfNone()
3046 {
3047 if (ParentGroup == null)
3048 return;
3049
3050// ??? ParentGroup.HasGroupChanged = true;
3051
3052 if (UpdateFlag != UpdateRequired.FULL)
3053 ScheduleFullUpdate();
3054 }
3055
2505 /// <summary> 3056 /// <summary>
2506 /// Schedules this prim for a full update 3057 /// Schedules this prim for a full update
2507 /// </summary> 3058 /// </summary>
@@ -2647,6 +3198,14 @@ namespace OpenSim.Region.Framework.Scenes
2647 if (ParentGroup == null) 3198 if (ParentGroup == null)
2648 return; 3199 return;
2649 3200
3201 // Update the "last" values
3202 m_lastPosition = OffsetPosition;
3203 m_lastRotation = RotationOffset;
3204 m_lastVelocity = Velocity;
3205 m_lastAcceleration = Acceleration;
3206 m_lastAngularVelocity = AngularVelocity;
3207 m_lastUpdateSentTime = Environment.TickCount;
3208
2650 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3209 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2651 { 3210 {
2652 SendFullUpdate(avatar.ControllingClient); 3211 SendFullUpdate(avatar.ControllingClient);
@@ -2705,8 +3264,8 @@ namespace OpenSim.Region.Framework.Scenes
2705 { 3264 {
2706 const float ROTATION_TOLERANCE = 0.01f; 3265 const float ROTATION_TOLERANCE = 0.01f;
2707 const float VELOCITY_TOLERANCE = 0.001f; 3266 const float VELOCITY_TOLERANCE = 0.001f;
2708 const float POSITION_TOLERANCE = 0.05f; 3267 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2709 const int TIME_MS_TOLERANCE = 3000; 3268 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2710 3269
2711 switch (UpdateFlag) 3270 switch (UpdateFlag)
2712 { 3271 {
@@ -2720,17 +3279,10 @@ namespace OpenSim.Region.Framework.Scenes
2720 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3279 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2721 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3280 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2722 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3281 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2723 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3282 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2724 { 3283 {
2725 SendTerseUpdateToAllClients(); 3284 SendTerseUpdateToAllClients();
2726 3285
2727 // Update the "last" values
2728 m_lastPosition = OffsetPosition;
2729 m_lastRotation = RotationOffset;
2730 m_lastVelocity = Velocity;
2731 m_lastAcceleration = Acceleration;
2732 m_lastAngularVelocity = AngularVelocity;
2733 m_lastTerseSent = Environment.TickCount;
2734 } 3286 }
2735 break; 3287 break;
2736 } 3288 }
@@ -2748,6 +3300,17 @@ namespace OpenSim.Region.Framework.Scenes
2748 /// </summary> 3300 /// </summary>
2749 public void SendTerseUpdateToAllClients() 3301 public void SendTerseUpdateToAllClients()
2750 { 3302 {
3303 if (ParentGroup == null || ParentGroup.Scene == null)
3304 return;
3305
3306 // Update the "last" values
3307 m_lastPosition = OffsetPosition;
3308 m_lastRotation = RotationOffset;
3309 m_lastVelocity = Velocity;
3310 m_lastAcceleration = Acceleration;
3311 m_lastAngularVelocity = AngularVelocity;
3312 m_lastUpdateSentTime = Environment.TickCount;
3313
2751 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3314 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2752 { 3315 {
2753 SendTerseUpdateToClient(client); 3316 SendTerseUpdateToClient(client);
@@ -2771,10 +3334,13 @@ namespace OpenSim.Region.Framework.Scenes
2771 3334
2772 public void SetBuoyancy(float fvalue) 3335 public void SetBuoyancy(float fvalue)
2773 { 3336 {
2774 PhysicsActor pa = PhysActor; 3337 Buoyancy = fvalue;
2775 3338/*
2776 if (pa != null) 3339 if (PhysActor != null)
2777 pa.Buoyancy = fvalue; 3340 {
3341 PhysActor.Buoyancy = fvalue;
3342 }
3343 */
2778 } 3344 }
2779 3345
2780 public void SetDieAtEdge(bool p) 3346 public void SetDieAtEdge(bool p)
@@ -2790,47 +3356,111 @@ namespace OpenSim.Region.Framework.Scenes
2790 PhysicsActor pa = PhysActor; 3356 PhysicsActor pa = PhysActor;
2791 3357
2792 if (pa != null) 3358 if (pa != null)
2793 pa.FloatOnWater = floatYN == 1; 3359 pa.FloatOnWater = (floatYN == 1);
2794 } 3360 }
2795 3361
2796 public void SetForce(Vector3 force) 3362 public void SetForce(Vector3 force)
2797 { 3363 {
2798 PhysicsActor pa = PhysActor; 3364 Force = force;
3365 }
2799 3366
2800 if (pa != null) 3367 public SOPVehicle VehicleParams
2801 pa.Force = force; 3368 {
3369 get
3370 {
3371 return m_vehicleParams;
3372 }
3373 set
3374 {
3375 m_vehicleParams = value;
3376 }
3377 }
3378
3379
3380 public int VehicleType
3381 {
3382 get
3383 {
3384 if (m_vehicleParams == null)
3385 return (int)Vehicle.TYPE_NONE;
3386 else
3387 return (int)m_vehicleParams.Type;
3388 }
3389 set
3390 {
3391 SetVehicleType(value);
3392 }
2802 } 3393 }
2803 3394
2804 public void SetVehicleType(int type) 3395 public void SetVehicleType(int type)
2805 { 3396 {
2806 PhysicsActor pa = PhysActor; 3397 m_vehicleParams = null;
3398
3399 if (type == (int)Vehicle.TYPE_NONE)
3400 {
3401 if (_parentID ==0 && PhysActor != null)
3402 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3403 return;
3404 }
3405 m_vehicleParams = new SOPVehicle();
3406 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3407 {
3408 if (_parentID ==0 && PhysActor != null)
3409 PhysActor.VehicleType = type;
3410 return;
3411 }
3412 }
2807 3413
2808 if (pa != null) 3414 public void SetVehicleFlags(int param, bool remove)
2809 pa.VehicleType = type; 3415 {
3416 if (m_vehicleParams == null)
3417 return;
3418
3419 m_vehicleParams.ProcessVehicleFlags(param, remove);
3420
3421 if (_parentID ==0 && PhysActor != null)
3422 {
3423 PhysActor.VehicleFlags(param, remove);
3424 }
2810 } 3425 }
2811 3426
2812 public void SetVehicleFloatParam(int param, float value) 3427 public void SetVehicleFloatParam(int param, float value)
2813 { 3428 {
2814 PhysicsActor pa = PhysActor; 3429 if (m_vehicleParams == null)
3430 return;
2815 3431
2816 if (pa != null) 3432 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
2817 pa.VehicleFloatParam(param, value); 3433
3434 if (_parentID == 0 && PhysActor != null)
3435 {
3436 PhysActor.VehicleFloatParam(param, value);
3437 }
2818 } 3438 }
2819 3439
2820 public void SetVehicleVectorParam(int param, Vector3 value) 3440 public void SetVehicleVectorParam(int param, Vector3 value)
2821 { 3441 {
2822 PhysicsActor pa = PhysActor; 3442 if (m_vehicleParams == null)
3443 return;
2823 3444
2824 if (pa != null) 3445 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
2825 pa.VehicleVectorParam(param, value); 3446
3447 if (_parentID == 0 && PhysActor != null)
3448 {
3449 PhysActor.VehicleVectorParam(param, value);
3450 }
2826 } 3451 }
2827 3452
2828 public void SetVehicleRotationParam(int param, Quaternion rotation) 3453 public void SetVehicleRotationParam(int param, Quaternion rotation)
2829 { 3454 {
2830 PhysicsActor pa = PhysActor; 3455 if (m_vehicleParams == null)
3456 return;
2831 3457
2832 if (pa != null) 3458 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
2833 pa.VehicleRotationParam(param, rotation); 3459
3460 if (_parentID == 0 && PhysActor != null)
3461 {
3462 PhysActor.VehicleRotationParam(param, rotation);
3463 }
2834 } 3464 }
2835 3465
2836 /// <summary> 3466 /// <summary>
@@ -3031,14 +3661,6 @@ namespace OpenSim.Region.Framework.Scenes
3031 hasProfileCut = hasDimple; // is it the same thing? 3661 hasProfileCut = hasDimple; // is it the same thing?
3032 } 3662 }
3033 3663
3034 public void SetVehicleFlags(int param, bool remove)
3035 {
3036 PhysicsActor pa = PhysActor;
3037
3038 if (pa != null)
3039 pa.VehicleFlags(param, remove);
3040 }
3041
3042 public void SetGroup(UUID groupID, IClientAPI client) 3664 public void SetGroup(UUID groupID, IClientAPI client)
3043 { 3665 {
3044 // Scene.AddNewPrims() calls with client == null so can't use this. 3666 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3138,71 +3760,20 @@ namespace OpenSim.Region.Framework.Scenes
3138 { 3760 {
3139 ParentGroup.stopMoveToTarget(); 3761 ParentGroup.stopMoveToTarget();
3140 3762
3141 ParentGroup.ScheduleGroupForTerseUpdate(); 3763// ParentGroup.ScheduleGroupForTerseUpdate();
3142 //ParentGroup.ScheduleGroupForFullUpdate(); 3764 //ParentGroup.ScheduleGroupForFullUpdate();
3143 } 3765 }
3144 3766
3145 public void StoreUndoState() 3767 public void StoreUndoState(ObjectChangeType change)
3146 {
3147 StoreUndoState(false);
3148 }
3149
3150 public void StoreUndoState(bool forGroup)
3151 { 3768 {
3152 if (ParentGroup == null || ParentGroup.Scene == null) 3769 if (m_UndoRedo == null)
3153 return; 3770 m_UndoRedo = new UndoRedoState(5);
3154 3771
3155 if (Undoing) 3772 lock (m_UndoRedo)
3156 { 3773 {
3157// m_log.DebugFormat( 3774 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3158// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3159 return;
3160 }
3161
3162 if (IgnoreUndoUpdate)
3163 {
3164// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3165 return;
3166 }
3167
3168 lock (m_undo)
3169 {
3170 if (m_undo.Count > 0)
3171 { 3775 {
3172 UndoState last = m_undo[m_undo.Count - 1]; 3776 m_UndoRedo.StoreUndo(this, change);
3173 if (last != null)
3174 {
3175 // TODO: May need to fix for group comparison
3176 if (last.Compare(this))
3177 {
3178// m_log.DebugFormat(
3179// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3180// Name, LocalId, m_undo.Count);
3181
3182 return;
3183 }
3184 }
3185 }
3186
3187// m_log.DebugFormat(
3188// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3189// Name, LocalId, forGroup, m_undo.Count);
3190
3191 if (ParentGroup.Scene.MaxUndoCount > 0)
3192 {
3193 UndoState nUndo = new UndoState(this, forGroup);
3194
3195 m_undo.Add(nUndo);
3196
3197 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3198 m_undo.RemoveAt(0);
3199
3200 if (m_redo.Count > 0)
3201 m_redo.Clear();
3202
3203// m_log.DebugFormat(
3204// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3205// Name, LocalId, forGroup, m_undo.Count);
3206 } 3777 }
3207 } 3778 }
3208 } 3779 }
@@ -3214,88 +3785,46 @@ namespace OpenSim.Region.Framework.Scenes
3214 { 3785 {
3215 get 3786 get
3216 { 3787 {
3217 lock (m_undo) 3788 if (m_UndoRedo == null)
3218 return m_undo.Count; 3789 return 0;
3790 return m_UndoRedo.Count;
3219 } 3791 }
3220 } 3792 }
3221 3793
3222 public void Undo() 3794 public void Undo()
3223 { 3795 {
3224 lock (m_undo) 3796 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3225 { 3797 return;
3226// m_log.DebugFormat(
3227// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3228// Name, LocalId, m_undo.Count);
3229
3230 if (m_undo.Count > 0)
3231 {
3232 UndoState goback = m_undo[m_undo.Count - 1];
3233 m_undo.RemoveAt(m_undo.Count - 1);
3234
3235 UndoState nUndo = null;
3236
3237 if (ParentGroup.Scene.MaxUndoCount > 0)
3238 {
3239 nUndo = new UndoState(this, goback.ForGroup);
3240 }
3241
3242 goback.PlaybackState(this);
3243
3244 if (nUndo != null)
3245 {
3246 m_redo.Add(nUndo);
3247
3248 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3249 m_redo.RemoveAt(0);
3250 }
3251 }
3252 3798
3253// m_log.DebugFormat( 3799 lock (m_UndoRedo)
3254// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3800 {
3255// Name, LocalId, m_undo.Count); 3801 Undoing = true;
3802 m_UndoRedo.Undo(this);
3803 Undoing = false;
3256 } 3804 }
3257 } 3805 }
3258 3806
3259 public void Redo() 3807 public void Redo()
3260 { 3808 {
3261 lock (m_undo) 3809 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3262 { 3810 return;
3263// m_log.DebugFormat(
3264// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3265// Name, LocalId, m_redo.Count);
3266
3267 if (m_redo.Count > 0)
3268 {
3269 UndoState gofwd = m_redo[m_redo.Count - 1];
3270 m_redo.RemoveAt(m_redo.Count - 1);
3271
3272 if (ParentGroup.Scene.MaxUndoCount > 0)
3273 {
3274 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3275
3276 m_undo.Add(nUndo);
3277
3278 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3279 m_undo.RemoveAt(0);
3280 }
3281
3282 gofwd.PlayfwdState(this);
3283 3811
3284// m_log.DebugFormat( 3812 lock (m_UndoRedo)
3285// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3813 {
3286// Name, LocalId, m_redo.Count); 3814 Undoing = true;
3287 } 3815 m_UndoRedo.Redo(this);
3816 Undoing = false;
3288 } 3817 }
3289 } 3818 }
3290 3819
3291 public void ClearUndoState() 3820 public void ClearUndoState()
3292 { 3821 {
3293// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3822 if (m_UndoRedo == null || Undoing)
3823 return;
3294 3824
3295 lock (m_undo) 3825 lock (m_UndoRedo)
3296 { 3826 {
3297 m_undo.Clear(); 3827 m_UndoRedo.Clear();
3298 m_redo.Clear();
3299 } 3828 }
3300 } 3829 }
3301 3830
@@ -3846,7 +4375,7 @@ namespace OpenSim.Region.Framework.Scenes
3846 if (god) 4375 if (god)
3847 { 4376 {
3848 BaseMask = ApplyMask(BaseMask, set, mask); 4377 BaseMask = ApplyMask(BaseMask, set, mask);
3849 Inventory.ApplyGodPermissions(_baseMask); 4378 Inventory.ApplyGodPermissions(BaseMask);
3850 } 4379 }
3851 4380
3852 break; 4381 break;
@@ -3865,7 +4394,7 @@ namespace OpenSim.Region.Framework.Scenes
3865 case 16: 4394 case 16:
3866 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4395 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
3867 baseMask; 4396 baseMask;
3868 // Prevent the client from creating no mod, no copy 4397 // Prevent the client from creating no copy, no transfer
3869 // objects 4398 // objects
3870 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4399 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
3871 NextOwnerMask |= (uint)PermissionMask.Transfer; 4400 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -3883,20 +4412,20 @@ namespace OpenSim.Region.Framework.Scenes
3883 { 4412 {
3884 bool update = false; 4413 bool update = false;
3885 4414
3886 if (BaseMask != source.BaseMask || 4415 uint prevOwnerMask = OwnerMask;
3887 OwnerMask != source.OwnerMask || 4416 uint prevGroupMask = GroupMask;
3888 GroupMask != source.GroupMask || 4417 uint prevEveryoneMask = EveryoneMask;
3889 EveryoneMask != source.EveryoneMask || 4418 uint prevNextOwnerMask = NextOwnerMask;
3890 NextOwnerMask != source.NextOwnerMask)
3891 update = true;
3892 4419
3893 BaseMask = source.BaseMask; 4420 OwnerMask = source.OwnerMask & BaseMask;
3894 OwnerMask = source.OwnerMask; 4421 GroupMask = source.GroupMask & BaseMask;
3895 GroupMask = source.GroupMask; 4422 EveryoneMask = source.EveryoneMask & BaseMask;
3896 EveryoneMask = source.EveryoneMask; 4423 NextOwnerMask = source.NextOwnerMask & BaseMask;
3897 NextOwnerMask = source.NextOwnerMask;
3898 4424
3899 if (update) 4425 if (OwnerMask != prevOwnerMask ||
4426 GroupMask != prevGroupMask ||
4427 EveryoneMask != prevEveryoneMask ||
4428 NextOwnerMask != prevNextOwnerMask)
3900 SendFullUpdateToAllClients(); 4429 SendFullUpdateToAllClients();
3901 } 4430 }
3902 4431
@@ -3947,6 +4476,7 @@ namespace OpenSim.Region.Framework.Scenes
3947 } 4476 }
3948 } 4477 }
3949 4478
4479
3950 public void UpdateExtraPhysics(ExtraPhysicsData physdata) 4480 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
3951 { 4481 {
3952 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4482 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
@@ -3974,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
3974 /// <param name="SetTemporary"></param> 4504 /// <param name="SetTemporary"></param>
3975 /// <param name="SetPhantom"></param> 4505 /// <param name="SetPhantom"></param>
3976 /// <param name="SetVD"></param> 4506 /// <param name="SetVD"></param>
3977 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4507 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3978 { 4508 {
3979 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4509 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3980 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4510 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3984,215 +4514,230 @@ namespace OpenSim.Region.Framework.Scenes
3984 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4514 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3985 return; 4515 return;
3986 4516
3987 PhysicsActor pa = PhysActor; 4517 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
4000 if (phanReset) // Phantom changes from on to off switch VD off too
4001 {
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 4518
4017 if (UsePhysics && IsJoint()) 4519 // volume detector implies phantom
4018 { 4520 if (VolumeDetectActive)
4019 SetPhantom = true; 4521 SetPhantom = true;
4020 }
4021 4522
4022 if (UsePhysics) 4523 if (UsePhysics)
4023 {
4024 AddFlag(PrimFlags.Physics); 4524 AddFlag(PrimFlags.Physics);
4025 if (!wasUsingPhysics)
4026 {
4027 DoPhysicsPropertyUpdate(UsePhysics, false);
4028 }
4029 }
4030 else 4525 else
4031 {
4032 RemFlag(PrimFlags.Physics); 4526 RemFlag(PrimFlags.Physics);
4033 if (wasUsingPhysics)
4034 {
4035 DoPhysicsPropertyUpdate(UsePhysics, false);
4036 }
4037 }
4038 4527
4039 if (SetPhantom 4528 if (SetPhantom)
4040 || ParentGroup.IsAttachment
4041 || PhysicsShapeType == (byte)PhysShapeType.none
4042 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4043 {
4044 AddFlag(PrimFlags.Phantom); 4529 AddFlag(PrimFlags.Phantom);
4045 4530 else
4046 if (PhysActor != null)
4047 {
4048 RemoveFromPhysics();
4049 pa = null;
4050 }
4051 }
4052 else // Not phantom
4053 {
4054 RemFlag(PrimFlags.Phantom); 4531 RemFlag(PrimFlags.Phantom);
4055 4532
4056 if (ParentGroup.Scene == null) 4533 if (SetTemporary)
4057 return; 4534 AddFlag(PrimFlags.TemporaryOnRez);
4535 else
4536 RemFlag(PrimFlags.TemporaryOnRez);
4058 4537
4059 if (ParentGroup.Scene.CollidablePrims && pa == null)
4060 {
4061 pa = AddToPhysics(UsePhysics);
4062 4538
4063 if (pa != null) 4539 if (ParentGroup.Scene == null)
4064 { 4540 return;
4065 pa.SetMaterial(Material);
4066 DoPhysicsPropertyUpdate(UsePhysics, true);
4067
4068 if (
4069 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4070 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4071 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4072 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4073 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4074 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4075 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4076 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4077 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4078 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4079 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4080 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4081 (CollisionSound != UUID.Zero)
4082 )
4083 {
4084 pa.OnCollisionUpdate += PhysicsCollision;
4085 pa.SubscribeEvents(1000);
4086 }
4087 }
4088 }
4089 else // it already has a physical representation
4090 {
4091 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4092 }
4093 }
4094 4541
4095 if (SetVD) 4542 PhysicsActor pa = PhysActor;
4543
4544 if (pa != null && building && pa.Building != building)
4545 pa.Building = building;
4546
4547 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4548 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4096 { 4549 {
4097 // If the above logic worked (this is urgent candidate to unit tests!)
4098 // we now have a physicsactor.
4099 // Defensive programming calls for a check here.
4100 // Better would be throwing an exception that could be catched by a unit test as the internal
4101 // logic should make sure, this Physactor is always here.
4102 if (pa != null) 4550 if (pa != null)
4103 { 4551 {
4104 pa.SetVolumeDetect(1); 4552 if(wasUsingPhysics)
4105 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4553 ParentGroup.Scene.RemovePhysicalPrim(1);
4106 VolumeDetectActive = true; 4554 RemoveFromPhysics();
4107 } 4555 }
4556
4557 Velocity = new Vector3(0, 0, 0);
4558 Acceleration = new Vector3(0, 0, 0);
4559 if (ParentGroup.RootPart == this)
4560 AngularVelocity = new Vector3(0, 0, 0);
4108 } 4561 }
4109 else if (SetVD != wasVD) 4562 else if (SetVD != wasVD)
4110 { 4563 {
4111 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4564 if (ParentGroup.Scene.CollidablePrims)
4112 // (mumbles, well, at least if you have infinte CPU powers :-)) 4565 {
4113 if (pa != null) 4566 if (pa == null)
4114 pa.SetVolumeDetect(0); 4567 {
4568 AddToPhysics(UsePhysics, SetPhantom, building, false);
4569 pa = PhysActor;
4570/*
4571 if (pa != null)
4572 {
4573 if (
4574// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4575// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4576// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4577// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4578// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4579// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4580 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4581 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4582 (CollisionSound != UUID.Zero)
4583 )
4584 {
4585 pa.OnCollisionUpdate += PhysicsCollision;
4586 pa.SubscribeEvents(1000);
4587 }
4588 }
4589*/
4590 }
4591 else // it already has a physical representation
4592 {
4593 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4594/* moved into DoPhysicsPropertyUpdate
4595 if(VolumeDetectActive)
4596 pa.SetVolumeDetect(1);
4597 else
4598 pa.SetVolumeDetect(0);
4599*/
4115 4600
4116 RemFlag(PrimFlags.Phantom); 4601 if (pa.Building != building)
4117 VolumeDetectActive = false; 4602 pa.Building = building;
4118 } 4603 }
4119 4604
4120 if (SetTemporary) 4605 UpdatePhysicsSubscribedEvents();
4121 { 4606 }
4122 AddFlag(PrimFlags.TemporaryOnRez); 4607 }
4123 }
4124 else
4125 {
4126 RemFlag(PrimFlags.TemporaryOnRez);
4127 }
4128 4608
4129 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4609 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4130 4610
4611 // and last in case we have a new actor and not building
4612
4131 if (ParentGroup != null) 4613 if (ParentGroup != null)
4132 { 4614 {
4133 ParentGroup.HasGroupChanged = true; 4615 ParentGroup.HasGroupChanged = true;
4134 ScheduleFullUpdate(); 4616 ScheduleFullUpdate();
4135 } 4617 }
4136 4618
4137// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4619// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4138 } 4620 }
4139 4621
4140 /// <summary> 4622 /// <summary>
4141 /// Adds this part to the physics scene. 4623 /// Adds this part to the physics scene.
4624 /// and sets the PhysActor property
4142 /// </summary> 4625 /// </summary>
4143 /// <remarks>This method also sets the PhysActor property.</remarks> 4626 /// <param name="isPhysical">Add this prim as physical.</param>
4144 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4627 /// <param name="isPhantom">Add this prim as phantom.</param>
4145 /// <returns> 4628 /// <param name="building">tells physics to delay full construction of object</param>
4146 /// The physics actor. null if there was a failure. 4629 /// <param name="applyDynamics">applies velocities, force and torque</param>
4147 /// </returns> 4630 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4148 private PhysicsActor AddToPhysics(bool rigidBody) 4631 {
4149 {
4150 PhysicsActor pa; 4632 PhysicsActor pa;
4151 4633
4634 Vector3 velocity = Velocity;
4635 Vector3 rotationalVelocity = AngularVelocity;;
4636
4152 try 4637 try
4153 { 4638 {
4154 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4639 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4155 string.Format("{0}/{1}", Name, UUID), 4640 string.Format("{0}/{1}", Name, UUID),
4156 Shape, 4641 Shape,
4157 AbsolutePosition, 4642 AbsolutePosition,
4158 Scale, 4643 Scale,
4159 RotationOffset, 4644 GetWorldRotation(),
4160 rigidBody, 4645 isPhysical,
4161 m_localId); 4646 isPhantom,
4647 PhysicsShapeType,
4648 m_localId);
4162 } 4649 }
4163 catch (Exception e) 4650 catch (Exception e)
4164 { 4651 {
4165 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e); 4652 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4166 pa = null; 4653 pa = null;
4167 } 4654 }
4168 4655
4169 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4170 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4171 // being set.
4172 PhysActor = pa;
4173
4174 // Basic Physics can also return null as well as an exception catch.
4175 if (pa != null) 4656 if (pa != null)
4176 { 4657 {
4177 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4658 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4178 pa.SetMaterial(Material); 4659 pa.SetMaterial(Material);
4179 DoPhysicsPropertyUpdate(rigidBody, true); 4660
4661 if (VolumeDetectActive) // change if not the default only
4662 pa.SetVolumeDetect(1);
4663
4664 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4665 m_vehicleParams.SetVehicle(pa);
4666
4667 // we are going to tell rest of code about physics so better have this here
4668 PhysActor = pa;
4669
4670 // DoPhysicsPropertyUpdate(isPhysical, true);
4671 // lets expand it here just with what it really needs to do
4672
4673 if (isPhysical)
4674 {
4675 if (ParentGroup.RootPart.KeyframeMotion != null)
4676 ParentGroup.RootPart.KeyframeMotion.Stop();
4677 ParentGroup.RootPart.KeyframeMotion = null;
4678 ParentGroup.Scene.AddPhysicalPrim(1);
4679
4680 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4681 pa.OnOutOfBounds += PhysicsOutOfBounds;
4682
4683 if (ParentID != 0 && ParentID != LocalId)
4684 {
4685 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4686
4687 if (parentPa != null)
4688 {
4689 pa.link(parentPa);
4690 }
4691 }
4692 }
4693
4694 if (applyDynamics)
4695 // do independent of isphysical so parameters get setted (at least some)
4696 {
4697 Velocity = velocity;
4698 AngularVelocity = rotationalVelocity;
4699// pa.Velocity = velocity;
4700 pa.RotationalVelocity = rotationalVelocity;
4701
4702 // if not vehicle and root part apply force and torque
4703 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4704 && LocalId == ParentGroup.RootPart.LocalId)
4705 {
4706 pa.Force = Force;
4707 pa.Torque = Torque;
4708 }
4709 }
4710
4711// if (Shape.SculptEntry)
4712// CheckSculptAndLoad();
4713// else
4714 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4715
4716 if (!building)
4717 pa.Building = false;
4180 } 4718 }
4181 4719
4182 return pa; 4720 PhysActor = pa;
4183 } 4721 }
4184 4722
4185 /// <summary> 4723 /// <summary>
4186 /// This removes the part from the physics scene. 4724 /// This removes the part from the physics scene.
4187 /// </summary> 4725 /// </summary>
4188 /// <remarks> 4726 /// <remarks>
4189 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4727 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4190 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4728 /// representation for collision detection.
4191 /// phantom.
4192 /// </remarks> 4729 /// </remarks>
4193 public void RemoveFromPhysics() 4730 public void RemoveFromPhysics()
4194 { 4731 {
4195 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4732 PhysicsActor pa = PhysActor;
4733 if (pa != null)
4734 {
4735 pa.OnCollisionUpdate -= PhysicsCollision;
4736 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4737 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4738
4739 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4740 }
4196 PhysActor = null; 4741 PhysActor = null;
4197 } 4742 }
4198 4743
@@ -4324,6 +4869,8 @@ namespace OpenSim.Region.Framework.Scenes
4324 { 4869 {
4325// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 4870// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4326 4871
4872 return;
4873
4327 if (ParentGroup.IsDeleted) 4874 if (ParentGroup.IsDeleted)
4328 return; 4875 return;
4329 4876
@@ -4404,6 +4951,44 @@ namespace OpenSim.Region.Framework.Scenes
4404 ScheduleFullUpdate(); 4951 ScheduleFullUpdate();
4405 } 4952 }
4406 4953
4954
4955 private void UpdatePhysicsSubscribedEvents()
4956 {
4957 PhysicsActor pa = PhysActor;
4958 if (pa == null)
4959 return;
4960
4961 pa.OnCollisionUpdate -= PhysicsCollision;
4962
4963 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
4964
4965 scriptEvents CombinedEvents = AggregateScriptEvents;
4966
4967 // merge with root part
4968 if (ParentGroup != null && ParentGroup.RootPart != null)
4969 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4970
4971 // submit to this part case
4972 if (VolumeDetectActive)
4973 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4974 else if ((Flags & PrimFlags.Phantom) != 0)
4975 CombinedEvents &= PhyscicsPhantonSubsEvents;
4976 else
4977 CombinedEvents &= PhysicsNeededSubsEvents;
4978
4979 if (hassound || CombinedEvents != 0)
4980 {
4981 // subscribe to physics updates.
4982 pa.OnCollisionUpdate += PhysicsCollision;
4983 pa.SubscribeEvents(50); // 20 reports per second
4984 }
4985 else
4986 {
4987 pa.UnSubscribeEvents();
4988 }
4989 }
4990
4991
4407 public void aggregateScriptEvents() 4992 public void aggregateScriptEvents()
4408 { 4993 {
4409 if (ParentGroup == null || ParentGroup.RootPart == null) 4994 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4440,40 +5025,32 @@ namespace OpenSim.Region.Framework.Scenes
4440 { 5025 {
4441 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5026 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4442 } 5027 }
4443 5028/*
4444 PhysicsActor pa = PhysActor; 5029 PhysicsActor pa = PhysActor;
4445 5030 if (pa != null)
4446 if (
4447 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4448 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4449 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4450 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4451 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4452 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4453 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4454 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4455 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4456 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4457 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4458 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4459 (CollisionSound != UUID.Zero)
4460 )
4461 { 5031 {
4462 // subscribe to physics updates. 5032 if (
4463 if (pa != null) 5033// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5034// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5035// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5036// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5037// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5038// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5039 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5040 )
4464 { 5041 {
5042 // subscribe to physics updates.
4465 pa.OnCollisionUpdate += PhysicsCollision; 5043 pa.OnCollisionUpdate += PhysicsCollision;
4466 pa.SubscribeEvents(1000); 5044 pa.SubscribeEvents(1000);
4467 } 5045 }
4468 } 5046 else
4469 else
4470 {
4471 if (pa != null)
4472 { 5047 {
4473 pa.UnSubscribeEvents(); 5048 pa.UnSubscribeEvents();
4474 pa.OnCollisionUpdate -= PhysicsCollision; 5049 pa.OnCollisionUpdate -= PhysicsCollision;
4475 } 5050 }
4476 } 5051 }
5052 */
5053 UpdatePhysicsSubscribedEvents();
4477 5054
4478 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5055 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4479 //{ 5056 //{
@@ -4604,6 +5181,18 @@ namespace OpenSim.Region.Framework.Scenes
4604 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5181 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4605 } 5182 }
4606 5183
5184 public void ResetOwnerChangeFlag()
5185 {
5186 List<UUID> inv = Inventory.GetInventoryList();
5187
5188 foreach (UUID itemID in inv)
5189 {
5190 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5191 item.OwnerChanged = false;
5192 Inventory.UpdateInventoryItem(item, false, false);
5193 }
5194 }
5195
4607 /// <summary> 5196 /// <summary>
4608 /// Record an avatar sitting on this part. 5197 /// Record an avatar sitting on this part.
4609 /// </summary> 5198 /// </summary>