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.cs1731
1 files changed, 1205 insertions, 526 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 189d298..79779a8 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,8 +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;
305 329 protected float m_buoyancy = 0.0f;
330 protected Vector3 m_force;
331 protected Vector3 m_torque;
332
333 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
334 protected float m_density = 1000.0f; // in kg/m^3
335 protected float m_gravitymod = 1.0f;
336 protected float m_friction = 0.6f; // wood
337 protected float m_bounce = 0.5f; // wood
338
339
340 protected bool m_isSelected = false;
341
306 /// <summary> 342 /// <summary>
307 /// Stores media texture data 343 /// Stores media texture data
308 /// </summary> 344 /// </summary>
@@ -314,10 +350,25 @@ namespace OpenSim.Region.Framework.Scenes
314 private Vector3 m_cameraAtOffset; 350 private Vector3 m_cameraAtOffset;
315 private bool m_forceMouselook; 351 private bool m_forceMouselook;
316 352
317 // 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;
318 private UUID m_collisionSound; 356 private UUID m_collisionSound;
319 private float m_collisionSoundVolume; 357 private float m_collisionSoundVolume;
320 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
321 #endregion Fields 372 #endregion Fields
322 373
323// ~SceneObjectPart() 374// ~SceneObjectPart()
@@ -347,6 +398,7 @@ namespace OpenSim.Region.Framework.Scenes
347 // 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
348 // 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
349 m_inventory = new SceneObjectPartInventory(this); 400 m_inventory = new SceneObjectPartInventory(this);
401 LastColSoundSentTime = Util.EnvironmentTickCount();
350 } 402 }
351 403
352 /// <summary> 404 /// <summary>
@@ -361,7 +413,7 @@ namespace OpenSim.Region.Framework.Scenes
361 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 413 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
362 Quaternion rotationOffset, Vector3 offsetPosition) : this() 414 Quaternion rotationOffset, Vector3 offsetPosition) : this()
363 { 415 {
364 m_name = "Primitive"; 416 m_name = "Object";
365 417
366 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 418 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
367 LastOwnerID = CreatorID = OwnerID = ownerID; 419 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -400,7 +452,7 @@ namespace OpenSim.Region.Framework.Scenes
400 private uint _ownerMask = (uint)PermissionMask.All; 452 private uint _ownerMask = (uint)PermissionMask.All;
401 private uint _groupMask = (uint)PermissionMask.None; 453 private uint _groupMask = (uint)PermissionMask.None;
402 private uint _everyoneMask = (uint)PermissionMask.None; 454 private uint _everyoneMask = (uint)PermissionMask.None;
403 private uint _nextOwnerMask = (uint)PermissionMask.All; 455 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
404 private PrimFlags _flags = PrimFlags.None; 456 private PrimFlags _flags = PrimFlags.None;
405 private DateTime m_expires; 457 private DateTime m_expires;
406 private DateTime m_rezzed; 458 private DateTime m_rezzed;
@@ -494,12 +546,16 @@ namespace OpenSim.Region.Framework.Scenes
494 } 546 }
495 547
496 /// <value> 548 /// <value>
497 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 549 /// Get the inventory list
498 /// </value> 550 /// </value>
499 public TaskInventoryDictionary TaskInventory 551 public TaskInventoryDictionary TaskInventory
500 { 552 {
501 get { return m_inventory.Items; } 553 get {
502 set { m_inventory.Items = value; } 554 return m_inventory.Items;
555 }
556 set {
557 m_inventory.Items = value;
558 }
503 } 559 }
504 560
505 /// <summary> 561 /// <summary>
@@ -549,20 +605,6 @@ namespace OpenSim.Region.Framework.Scenes
549 } 605 }
550 } 606 }
551 607
552 public byte Material
553 {
554 get { return (byte) m_material; }
555 set
556 {
557 m_material = (Material)value;
558
559 PhysicsActor pa = PhysActor;
560
561 if (pa != null)
562 pa.SetMaterial((int)value);
563 }
564 }
565
566 [XmlIgnore] 608 [XmlIgnore]
567 public bool PassTouches 609 public bool PassTouches
568 { 610 {
@@ -588,6 +630,18 @@ namespace OpenSim.Region.Framework.Scenes
588 } 630 }
589 } 631 }
590 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
591 public Dictionary<int, string> CollisionFilter 645 public Dictionary<int, string> CollisionFilter
592 { 646 {
593 get { return m_CollisionFilter; } 647 get { return m_CollisionFilter; }
@@ -656,14 +710,12 @@ namespace OpenSim.Region.Framework.Scenes
656 set { m_LoopSoundSlavePrims = value; } 710 set { m_LoopSoundSlavePrims = value; }
657 } 711 }
658 712
659
660 public Byte[] TextureAnimation 713 public Byte[] TextureAnimation
661 { 714 {
662 get { return m_TextureAnimation; } 715 get { return m_TextureAnimation; }
663 set { m_TextureAnimation = value; } 716 set { m_TextureAnimation = value; }
664 } 717 }
665 718
666
667 public Byte[] ParticleSystem 719 public Byte[] ParticleSystem
668 { 720 {
669 get { return m_particleSystem; } 721 get { return m_particleSystem; }
@@ -700,9 +752,12 @@ namespace OpenSim.Region.Framework.Scenes
700 { 752 {
701 // 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.
702 PhysicsActor actor = PhysActor; 754 PhysicsActor actor = PhysActor;
703 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 755 if (ParentID == 0)
704 if (actor != null && ParentID == 0) 756 {
705 m_groupPosition = actor.Position; 757 if (actor != null)
758 m_groupPosition = actor.Position;
759 return m_groupPosition;
760 }
706 761
707 // 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
708 if (ParentGroup.IsAttachment) 763 if (ParentGroup.IsAttachment)
@@ -712,14 +767,16 @@ namespace OpenSim.Region.Framework.Scenes
712 return sp.AbsolutePosition; 767 return sp.AbsolutePosition;
713 } 768 }
714 769
770 // use root prim's group position. Physics may have updated it
771 if (ParentGroup.RootPart != this)
772 m_groupPosition = ParentGroup.RootPart.GroupPosition;
715 return m_groupPosition; 773 return m_groupPosition;
716 } 774 }
717 set 775 set
718 { 776 {
719 m_groupPosition = value; 777 m_groupPosition = value;
720
721 PhysicsActor actor = PhysActor; 778 PhysicsActor actor = PhysActor;
722 if (actor != null) 779 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
723 { 780 {
724 try 781 try
725 { 782 {
@@ -743,16 +800,6 @@ namespace OpenSim.Region.Framework.Scenes
743 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); 800 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
744 } 801 }
745 } 802 }
746
747 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
748 if (SitTargetAvatar != UUID.Zero)
749 {
750 ScenePresence avatar;
751 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
752 {
753 avatar.ParentPosition = GetWorldPosition();
754 }
755 }
756 } 803 }
757 } 804 }
758 805
@@ -761,7 +808,7 @@ namespace OpenSim.Region.Framework.Scenes
761 get { return m_offsetPosition; } 808 get { return m_offsetPosition; }
762 set 809 set
763 { 810 {
764// StoreUndoState(); 811 Vector3 oldpos = m_offsetPosition;
765 m_offsetPosition = value; 812 m_offsetPosition = value;
766 813
767 if (ParentGroup != null && !ParentGroup.IsDeleted) 814 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -773,10 +820,25 @@ namespace OpenSim.Region.Framework.Scenes
773 actor.Orientation = GetWorldRotation(); 820 actor.Orientation = GetWorldRotation();
774 821
775 // Tell the physics engines that this prim changed. 822 // Tell the physics engines that this prim changed.
776 if (ParentGroup.Scene != null) 823 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
777 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 824 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
778 } 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 }
779 } 840 }
841 TriggerScriptChangedEvent(Changed.POSITION);
780 } 842 }
781 } 843 }
782 844
@@ -827,7 +889,7 @@ namespace OpenSim.Region.Framework.Scenes
827 889
828 set 890 set
829 { 891 {
830 StoreUndoState(); 892// StoreUndoState();
831 m_rotationOffset = value; 893 m_rotationOffset = value;
832 894
833 PhysicsActor actor = PhysActor; 895 PhysicsActor actor = PhysActor;
@@ -915,19 +977,36 @@ namespace OpenSim.Region.Framework.Scenes
915 get 977 get
916 { 978 {
917 PhysicsActor actor = PhysActor; 979 PhysicsActor actor = PhysActor;
918 if ((actor != null) && actor.IsPhysical) 980 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
919 { 981 {
920 m_angularVelocity = actor.RotationalVelocity; 982 m_angularVelocity = actor.RotationalVelocity;
921 } 983 }
922 return m_angularVelocity; 984 return m_angularVelocity;
923 } 985 }
924 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 }
925 } 995 }
926 996
927 /// <summary></summary> 997 /// <summary></summary>
928 public Vector3 Acceleration 998 public Vector3 Acceleration
929 { 999 {
930 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
931 set { m_acceleration = value; } 1010 set { m_acceleration = value; }
932 } 1011 }
933 1012
@@ -995,7 +1074,10 @@ namespace OpenSim.Region.Framework.Scenes
995 public PrimitiveBaseShape Shape 1074 public PrimitiveBaseShape Shape
996 { 1075 {
997 get { return m_shape; } 1076 get { return m_shape; }
998 set { m_shape = value;} 1077 set
1078 {
1079 m_shape = value;
1080 }
999 } 1081 }
1000 1082
1001 /// <summary> 1083 /// <summary>
@@ -1008,7 +1090,6 @@ namespace OpenSim.Region.Framework.Scenes
1008 { 1090 {
1009 if (m_shape != null) 1091 if (m_shape != null)
1010 { 1092 {
1011 StoreUndoState();
1012 1093
1013 m_shape.Scale = value; 1094 m_shape.Scale = value;
1014 1095
@@ -1035,6 +1116,7 @@ namespace OpenSim.Region.Framework.Scenes
1035 } 1116 }
1036 1117
1037 public UpdateRequired UpdateFlag { get; set; } 1118 public UpdateRequired UpdateFlag { get; set; }
1119 public bool UpdatePhysRequired { get; set; }
1038 1120
1039 /// <summary> 1121 /// <summary>
1040 /// Used for media on a prim. 1122 /// Used for media on a prim.
@@ -1075,10 +1157,7 @@ namespace OpenSim.Region.Framework.Scenes
1075 { 1157 {
1076 get 1158 get
1077 { 1159 {
1078 if (ParentGroup.IsAttachment) 1160 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1079 return GroupPosition;
1080
1081 return m_offsetPosition + m_groupPosition;
1082 } 1161 }
1083 } 1162 }
1084 1163
@@ -1256,6 +1335,13 @@ namespace OpenSim.Region.Framework.Scenes
1256 _flags = value; 1335 _flags = value;
1257 } 1336 }
1258 } 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 }
1259 1345
1260 /// <summary> 1346 /// <summary>
1261 /// 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
@@ -1306,12 +1392,41 @@ namespace OpenSim.Region.Framework.Scenes
1306 set { m_sitAnimation = value; } 1392 set { m_sitAnimation = value; }
1307 } 1393 }
1308 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
1309 public UUID CollisionSound 1416 public UUID CollisionSound
1310 { 1417 {
1311 get { return m_collisionSound; } 1418 get { return m_collisionSound; }
1312 set 1419 set
1313 { 1420 {
1314 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
1315 aggregateScriptEvents(); 1430 aggregateScriptEvents();
1316 } 1431 }
1317 } 1432 }
@@ -1322,6 +1437,324 @@ namespace OpenSim.Region.Framework.Scenes
1322 set { m_collisionSoundVolume = value; } 1437 set { m_collisionSoundVolume = value; }
1323 } 1438 }
1324 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
1559 public byte DefaultPhysicsShapeType()
1560 {
1561 byte type;
1562
1563 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1564 type = (byte)PhysShapeType.convex;
1565 else
1566 type = (byte)PhysShapeType.prim;
1567
1568 return type;
1569 }
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
1630 public byte PhysicsShapeType
1631 {
1632 get { return m_physicsShapeType; }
1633 set
1634 {
1635 byte oldv = m_physicsShapeType;
1636
1637 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1638 {
1639 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1640 m_physicsShapeType = DefaultPhysicsShapeType();
1641 else
1642 m_physicsShapeType = value;
1643 }
1644 else
1645 m_physicsShapeType = DefaultPhysicsShapeType();
1646
1647 if (m_physicsShapeType != oldv && ParentGroup != null)
1648 {
1649 if (m_physicsShapeType == (byte)PhysShapeType.none)
1650 {
1651 if (PhysActor != null)
1652 {
1653 Velocity = new Vector3(0, 0, 0);
1654 Acceleration = new Vector3(0, 0, 0);
1655 if (ParentGroup.RootPart == this)
1656 AngularVelocity = new Vector3(0, 0, 0);
1657 ParentGroup.Scene.RemovePhysicalPrim(1);
1658 RemoveFromPhysics();
1659 }
1660 }
1661 else if (PhysActor == null)
1662 {
1663 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1664 UpdatePhysicsSubscribedEvents();
1665 }
1666 else
1667 {
1668 PhysActor.PhysicsShapeType = m_physicsShapeType;
1669// if (Shape.SculptEntry)
1670// CheckSculptAndLoad();
1671 }
1672
1673 if (ParentGroup != null)
1674 ParentGroup.HasGroupChanged = true;
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 Bounciness
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;
1754 }
1755 }
1756
1757
1325 #endregion Public Properties with only Get 1758 #endregion Public Properties with only Get
1326 1759
1327 private uint ApplyMask(uint val, bool set, uint mask) 1760 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1467,6 +1900,61 @@ namespace OpenSim.Region.Framework.Scenes
1467 } 1900 }
1468 } 1901 }
1469 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
1470 /// <summary> 1958 /// <summary>
1471 /// hook to the physics scene to apply angular impulse 1959 /// hook to the physics scene to apply angular impulse
1472 /// 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
@@ -1487,7 +1975,7 @@ namespace OpenSim.Region.Framework.Scenes
1487 impulse = newimpulse; 1975 impulse = newimpulse;
1488 } 1976 }
1489 1977
1490 ParentGroup.applyAngularImpulse(impulse); 1978 ParentGroup.ApplyAngularImpulse(impulse);
1491 } 1979 }
1492 1980
1493 /// <summary> 1981 /// <summary>
@@ -1497,20 +1985,24 @@ namespace OpenSim.Region.Framework.Scenes
1497 /// </summary> 1985 /// </summary>
1498 /// <param name="impulsei">Vector force</param> 1986 /// <param name="impulsei">Vector force</param>
1499 /// <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>
1500 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)
1501 { 1991 {
1502 Vector3 impulse = impulsei; 1992 Vector3 torque = torquei;
1503 1993
1504 if (localGlobalTF) 1994 if (localGlobalTF)
1505 { 1995 {
1996/*
1506 Quaternion grot = GetWorldRotation(); 1997 Quaternion grot = GetWorldRotation();
1507 Quaternion AXgrot = grot; 1998 Quaternion AXgrot = grot;
1508 Vector3 AXimpulsei = impulsei; 1999 Vector3 AXimpulsei = impulsei;
1509 Vector3 newimpulse = AXimpulsei * AXgrot; 2000 Vector3 newimpulse = AXimpulsei * AXgrot;
1510 impulse = newimpulse; 2001 */
2002 torque *= GetWorldRotation();
1511 } 2003 }
1512 2004
1513 ParentGroup.setAngularImpulse(impulse); 2005 Torque = torque;
1514 } 2006 }
1515 2007
1516 /// <summary> 2008 /// <summary>
@@ -1518,17 +2010,23 @@ namespace OpenSim.Region.Framework.Scenes
1518 /// </summary> 2010 /// </summary>
1519 /// <param name="rootObjectFlags"></param> 2011 /// <param name="rootObjectFlags"></param>
1520 /// <param name="VolumeDetectActive"></param> 2012 /// <param name="VolumeDetectActive"></param>
1521 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 2013 /// <param name="building"></param>
2014
2015 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1522 { 2016 {
2017 VolumeDetectActive = _VolumeDetectActive;
2018
1523 if (!ParentGroup.Scene.CollidablePrims) 2019 if (!ParentGroup.Scene.CollidablePrims)
1524 return; 2020 return;
1525 2021
1526// m_log.DebugFormat( 2022 if (PhysicsShapeType == (byte)PhysShapeType.none)
1527// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 2023 return;
1528// Name, LocalId, UUID, m_physicalPrim); 2024
2025 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
2026 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1529 2027
1530 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2028 if (_VolumeDetectActive)
1531 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2029 isPhantom = true;
1532 2030
1533 if (IsJoint()) 2031 if (IsJoint())
1534 { 2032 {
@@ -1536,22 +2034,14 @@ namespace OpenSim.Region.Framework.Scenes
1536 } 2034 }
1537 else 2035 else
1538 { 2036 {
1539 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 2037 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1540 if (VolumeDetectActive) 2038 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1541 isPhantom = false;
1542
1543 // 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
1544 // or flexible
1545 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1546 { 2039 {
1547 // Added clarification.. since A rigid body is an object that you can kick around, etc. 2040 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1548 bool rigidBody = isPhysical && !isPhantom; 2041 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1549
1550 PhysicsActor pa = AddToPhysics(rigidBody);
1551
1552 if (pa != null)
1553 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1554 } 2042 }
2043 else
2044 PhysActor = null; // just to be sure
1555 } 2045 }
1556 } 2046 }
1557 2047
@@ -1603,6 +2093,12 @@ namespace OpenSim.Region.Framework.Scenes
1603 dupe.Category = Category; 2093 dupe.Category = Category;
1604 dupe.m_rezzed = m_rezzed; 2094 dupe.m_rezzed = m_rezzed;
1605 2095
2096 dupe.m_UndoRedo = null;
2097 dupe.m_isSelected = false;
2098
2099 dupe.IgnoreUndoUpdate = false;
2100 dupe.Undoing = false;
2101
1606 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2102 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1607 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2103 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1608 2104
@@ -1618,6 +2114,7 @@ namespace OpenSim.Region.Framework.Scenes
1618 2114
1619 // Move afterwards ResetIDs as it clears the localID 2115 // Move afterwards ResetIDs as it clears the localID
1620 dupe.LocalId = localID; 2116 dupe.LocalId = localID;
2117
1621 // 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.
1622 dupe.LastOwnerID = OwnerID; 2119 dupe.LastOwnerID = OwnerID;
1623 2120
@@ -1625,6 +2122,9 @@ namespace OpenSim.Region.Framework.Scenes
1625 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2122 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1626 dupe.Shape.ExtraParams = extraP; 2123 dupe.Shape.ExtraParams = extraP;
1627 2124
2125 // safeguard actual copy is done in sog.copy
2126 dupe.KeyframeMotion = null;
2127
1628 dupe.DynAttrs.CopyFrom(DynAttrs); 2128 dupe.DynAttrs.CopyFrom(DynAttrs);
1629 2129
1630 if (userExposed) 2130 if (userExposed)
@@ -1638,8 +2138,12 @@ namespace OpenSim.Region.Framework.Scenes
1638*/ 2138*/
1639 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2139 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1640 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2140 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2141// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1641 } 2142 }
1642 2143
2144 if (dupe.PhysActor != null)
2145 dupe.PhysActor.LocalID = localID;
2146
1643 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2147 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1644 2148
1645// 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);
@@ -1658,10 +2162,10 @@ namespace OpenSim.Region.Framework.Scenes
1658 { 2162 {
1659 if (asset != null) 2163 if (asset != null)
1660 SculptTextureCallback(asset); 2164 SculptTextureCallback(asset);
1661 else 2165// else
1662 m_log.WarnFormat( 2166// m_log.WarnFormat(
1663 "[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",
1664 Name, UUID, id); 2168// Name, UUID, id);
1665 } 2169 }
1666*/ 2170*/
1667 /// <summary> 2171 /// <summary>
@@ -1760,6 +2264,7 @@ namespace OpenSim.Region.Framework.Scenes
1760 2264
1761 /// <summary> 2265 /// <summary>
1762 /// 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
1763 /// </summary> 2268 /// </summary>
1764 /// <param name="UsePhysics"></param> 2269 /// <param name="UsePhysics"></param>
1765 /// <param name="isNew"></param> 2270 /// <param name="isNew"></param>
@@ -1785,61 +2290,69 @@ namespace OpenSim.Region.Framework.Scenes
1785 { 2290 {
1786 if (pa.IsPhysical) // implies UsePhysics==false for this block 2291 if (pa.IsPhysical) // implies UsePhysics==false for this block
1787 { 2292 {
1788 if (!isNew) 2293 if (!isNew) // implies UsePhysics==false for this block
2294 {
1789 ParentGroup.Scene.RemovePhysicalPrim(1); 2295 ParentGroup.Scene.RemovePhysicalPrim(1);
1790 2296
1791 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2297 Velocity = new Vector3(0, 0, 0);
1792 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2298 Acceleration = new Vector3(0, 0, 0);
1793 pa.delink(); 2299 if (ParentGroup.RootPart == this)
2300 AngularVelocity = new Vector3(0, 0, 0);
1794 2301
1795 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2302 if (pa.Phantom && !VolumeDetectActive)
1796 { 2303 {
1797 // destroy all joints connected to this now deactivated body 2304 RemoveFromPhysics();
1798 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2305 return;
1799 } 2306 }
1800 2307
1801 // stop client-side interpolation of all joint proxy objects that have just been deleted 2308 pa.IsPhysical = UsePhysics;
1802 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2309 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1803 // 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 }
1804 } 2318 }
1805 2319
1806 if (!UsePhysics && !isNew) 2320 if (pa.IsPhysical != UsePhysics)
1807 { 2321 pa.IsPhysical = UsePhysics;
1808 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1809 // prim still has velocity and continues to interpolate its position along the old
1810 // velocity-vector.
1811 Velocity = new Vector3(0, 0, 0);
1812 Acceleration = new Vector3(0, 0, 0);
1813 AngularVelocity = new Vector3(0, 0, 0);
1814 //RotationalVelocity = new Vector3(0, 0, 0);
1815 }
1816 2322
1817 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);
1818 2329
1819 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2330 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1820 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2331 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1821 /// that's not wholesome. Had to make Scene public
1822 //PhysActor = null;
1823 2332
1824 if ((Flags & PrimFlags.Phantom) == 0) 2333 if (ParentID != 0 && ParentID != LocalId)
1825 {
1826 if (UsePhysics)
1827 { 2334 {
1828 ParentGroup.Scene.AddPhysicalPrim(1); 2335 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1829 2336
1830 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2337 if (parentPa != null)
1831 pa.OnOutOfBounds += PhysicsOutOfBounds;
1832 if (ParentID != 0 && ParentID != LocalId)
1833 { 2338 {
1834 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2339 pa.link(parentPa);
1835
1836 if (parentPa != null)
1837 {
1838 pa.link(parentPa);
1839 }
1840 } 2340 }
1841 } 2341 }
1842 } 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);
1843 } 2356 }
1844 2357
1845 // 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
@@ -1958,42 +2471,63 @@ namespace OpenSim.Region.Framework.Scenes
1958 2471
1959 public Vector3 GetGeometricCenter() 2472 public Vector3 GetGeometricCenter()
1960 { 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 {
1961 PhysicsActor pa = PhysActor; 2486 PhysicsActor pa = PhysActor;
1962 2487
1963 if (pa != null) 2488 if (pa != null)
1964 return new Vector3(pa.GeometricCenter.X, pa.GeometricCenter.Y, pa.GeometricCenter.Z); 2489 return pa.Mass;
1965 else 2490 else
1966 return new Vector3(0, 0, 0); 2491 return 0;
1967 } 2492 }
1968 2493
1969 public Vector3 GetCenterOfMass() 2494 public Vector3 GetCenterOfMass()
1970 { 2495 {
2496 if (ParentGroup.RootPart == this)
2497 {
2498 if (ParentGroup.IsDeleted)
2499 return AbsolutePosition;
2500 return ParentGroup.GetCenterOfMass();
2501 }
2502
1971 PhysicsActor pa = PhysActor; 2503 PhysicsActor pa = PhysActor;
1972 2504
1973 if (pa != null) 2505 if (pa != null)
1974 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2506 {
2507 Vector3 tmp = pa.CenterOfMass;
2508 return tmp;
2509 }
1975 else 2510 else
1976 return new Vector3(0, 0, 0); 2511 return AbsolutePosition;
1977 } 2512 }
1978 2513
1979 public float GetMass() 2514 public Vector3 GetPartCenterOfMass()
1980 { 2515 {
1981 PhysicsActor pa = PhysActor; 2516 PhysicsActor pa = PhysActor;
1982 2517
1983 if (pa != null) 2518 if (pa != null)
1984 return pa.Mass; 2519 {
2520 Vector3 tmp = pa.CenterOfMass;
2521 return tmp;
2522 }
1985 else 2523 else
1986 return 0; 2524 return AbsolutePosition;
1987 } 2525 }
1988 2526
2527
1989 public Vector3 GetForce() 2528 public Vector3 GetForce()
1990 { 2529 {
1991 PhysicsActor pa = PhysActor; 2530 return Force;
1992
1993 if (pa != null)
1994 return pa.Force;
1995 else
1996 return Vector3.Zero;
1997 } 2531 }
1998 2532
1999 /// <summary> 2533 /// <summary>
@@ -2208,15 +2742,25 @@ namespace OpenSim.Region.Framework.Scenes
2208 2742
2209 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2743 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2210 { 2744 {
2211 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2745 bool sendToRoot = true;
2212 {
2213 ColliderArgs LandCollidingMessage = new ColliderArgs();
2214 List<DetectedObject> colliding = new List<DetectedObject>();
2215
2216 colliding.Add(CreateDetObjectForGround());
2217 LandCollidingMessage.Colliders = colliding;
2218 2746
2747 ColliderArgs LandCollidingMessage = new ColliderArgs();
2748 List<DetectedObject> colliding = new List<DetectedObject>();
2749
2750 colliding.Add(CreateDetObjectForGround());
2751 LandCollidingMessage.Colliders = colliding;
2752
2753 if (Inventory.ContainsScripts())
2754 {
2755 if (!PassCollisions)
2756 sendToRoot = false;
2757 }
2758 if ((ScriptEvents & ev) != 0)
2219 notify(LocalId, LandCollidingMessage); 2759 notify(LocalId, LandCollidingMessage);
2760
2761 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2762 {
2763 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2220 } 2764 }
2221 } 2765 }
2222 2766
@@ -2232,57 +2776,120 @@ namespace OpenSim.Region.Framework.Scenes
2232 List<uint> endedColliders = new List<uint>(); 2776 List<uint> endedColliders = new List<uint>();
2233 List<uint> startedColliders = new List<uint>(); 2777 List<uint> startedColliders = new List<uint>();
2234 2778
2235 // calculate things that started colliding this time 2779 if (collissionswith.Count == 0)
2236 // and build up list of colliders this time
2237 foreach (uint localid in collissionswith.Keys)
2238 { 2780 {
2239 thisHitColliders.Add(localid); 2781 if (m_lastColliders.Count == 0)
2240 if (!m_lastColliders.Contains(localid)) 2782 return; // nothing to do
2241 startedColliders.Add(localid);
2242 }
2243 2783
2244 // calculate things that ended colliding 2784 foreach (uint localID in m_lastColliders)
2245 foreach (uint localID in m_lastColliders) 2785 {
2246 {
2247 if (!thisHitColliders.Contains(localID))
2248 endedColliders.Add(localID); 2786 endedColliders.Add(localID);
2787 }
2788 m_lastColliders.Clear();
2249 } 2789 }
2250 2790
2251 //add the items that started colliding this time to the last colliders list. 2791 else
2252 foreach (uint localID in startedColliders) 2792 {
2253 m_lastColliders.Add(localID); 2793 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2794
2795 // calculate things that started colliding this time
2796 // and build up list of colliders this time
2797 if (!VolumeDetectActive && CollisionSoundType >= 0)
2798 {
2799 CollisionForSoundInfo soundinfo;
2800 ContactPoint curcontact;
2254 2801
2255 // remove things that ended colliding from the last colliders list 2802 foreach (uint id in collissionswith.Keys)
2256 foreach (uint localID in endedColliders) 2803 {
2257 m_lastColliders.Remove(localID); 2804 thisHitColliders.Add(id);
2805 if (!m_lastColliders.Contains(id))
2806 {
2807 startedColliders.Add(id);
2258 2808
2259 // play the sound. 2809 curcontact = collissionswith[id];
2260 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2810 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2261 { 2811 {
2262 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2812 soundinfo = new CollisionForSoundInfo();
2263 if (soundModule != null) 2813 soundinfo.colliderID = id;
2814 soundinfo.position = curcontact.Position;
2815 soundinfo.relativeVel = curcontact.RelativeSpeed;
2816 soundinfolist.Add(soundinfo);
2817 }
2818 }
2819 }
2820 }
2821 else
2264 { 2822 {
2265 soundModule.SendSound(UUID, CollisionSound, 2823 foreach (uint id in collissionswith.Keys)
2266 CollisionSoundVolume, true, (byte)0, 0, false, 2824 {
2267 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);
2268 } 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);
2269 } 2849 }
2270 2850
2271 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2851 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2272 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2852 if (!VolumeDetectActive)
2853 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2273 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2854 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2274 2855
2275 if (startedColliders.Contains(0)) 2856 if (startedColliders.Contains(0))
2276 { 2857 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2277 if (m_lastColliders.Contains(0)) 2858 if (m_lastColliders.Contains(0))
2278 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2859 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2279 else
2280 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2281 }
2282 if (endedColliders.Contains(0)) 2860 if (endedColliders.Contains(0))
2283 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2861 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2284 } 2862 }
2285 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
2286 public void PhysicsOutOfBounds(Vector3 pos) 2893 public void PhysicsOutOfBounds(Vector3 pos)
2287 { 2894 {
2288 // 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.
@@ -2304,9 +2911,9 @@ namespace OpenSim.Region.Framework.Scenes
2304 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2911 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2305 2912
2306 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2913 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2307 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2914 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2308 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2915 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2309 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2916 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2310 { 2917 {
2311 ParentGroup.AbsolutePosition = newpos; 2918 ParentGroup.AbsolutePosition = newpos;
2312 return; 2919 return;
@@ -2433,6 +3040,19 @@ namespace OpenSim.Region.Framework.Scenes
2433 APIDTarget = Quaternion.Identity; 3040 APIDTarget = Quaternion.Identity;
2434 } 3041 }
2435 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
2436 /// <summary> 3056 /// <summary>
2437 /// Schedules this prim for a full update 3057 /// Schedules this prim for a full update
2438 /// </summary> 3058 /// </summary>
@@ -2578,6 +3198,14 @@ namespace OpenSim.Region.Framework.Scenes
2578 if (ParentGroup == null) 3198 if (ParentGroup == null)
2579 return; 3199 return;
2580 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
2581 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3209 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2582 { 3210 {
2583 SendFullUpdate(avatar.ControllingClient); 3211 SendFullUpdate(avatar.ControllingClient);
@@ -2636,8 +3264,8 @@ namespace OpenSim.Region.Framework.Scenes
2636 { 3264 {
2637 const float ROTATION_TOLERANCE = 0.01f; 3265 const float ROTATION_TOLERANCE = 0.01f;
2638 const float VELOCITY_TOLERANCE = 0.001f; 3266 const float VELOCITY_TOLERANCE = 0.001f;
2639 const float POSITION_TOLERANCE = 0.05f; 3267 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2640 const int TIME_MS_TOLERANCE = 3000; 3268 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2641 3269
2642 switch (UpdateFlag) 3270 switch (UpdateFlag)
2643 { 3271 {
@@ -2651,17 +3279,10 @@ namespace OpenSim.Region.Framework.Scenes
2651 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3279 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2652 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3280 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2653 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3281 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2654 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3282 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2655 { 3283 {
2656 SendTerseUpdateToAllClients(); 3284 SendTerseUpdateToAllClients();
2657 3285
2658 // Update the "last" values
2659 m_lastPosition = OffsetPosition;
2660 m_lastRotation = RotationOffset;
2661 m_lastVelocity = Velocity;
2662 m_lastAcceleration = Acceleration;
2663 m_lastAngularVelocity = AngularVelocity;
2664 m_lastTerseSent = Environment.TickCount;
2665 } 3286 }
2666 break; 3287 break;
2667 } 3288 }
@@ -2679,6 +3300,17 @@ namespace OpenSim.Region.Framework.Scenes
2679 /// </summary> 3300 /// </summary>
2680 public void SendTerseUpdateToAllClients() 3301 public void SendTerseUpdateToAllClients()
2681 { 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
2682 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3314 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2683 { 3315 {
2684 SendTerseUpdateToClient(client); 3316 SendTerseUpdateToClient(client);
@@ -2702,10 +3334,13 @@ namespace OpenSim.Region.Framework.Scenes
2702 3334
2703 public void SetBuoyancy(float fvalue) 3335 public void SetBuoyancy(float fvalue)
2704 { 3336 {
2705 PhysicsActor pa = PhysActor; 3337 Buoyancy = fvalue;
2706 3338/*
2707 if (pa != null) 3339 if (PhysActor != null)
2708 pa.Buoyancy = fvalue; 3340 {
3341 PhysActor.Buoyancy = fvalue;
3342 }
3343 */
2709 } 3344 }
2710 3345
2711 public void SetDieAtEdge(bool p) 3346 public void SetDieAtEdge(bool p)
@@ -2721,47 +3356,111 @@ namespace OpenSim.Region.Framework.Scenes
2721 PhysicsActor pa = PhysActor; 3356 PhysicsActor pa = PhysActor;
2722 3357
2723 if (pa != null) 3358 if (pa != null)
2724 pa.FloatOnWater = floatYN == 1; 3359 pa.FloatOnWater = (floatYN == 1);
2725 } 3360 }
2726 3361
2727 public void SetForce(Vector3 force) 3362 public void SetForce(Vector3 force)
2728 { 3363 {
2729 PhysicsActor pa = PhysActor; 3364 Force = force;
3365 }
2730 3366
2731 if (pa != null) 3367 public SOPVehicle VehicleParams
2732 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 }
2733 } 3393 }
2734 3394
2735 public void SetVehicleType(int type) 3395 public void SetVehicleType(int type)
2736 { 3396 {
2737 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 }
2738 3413
2739 if (pa != null) 3414 public void SetVehicleFlags(int param, bool remove)
2740 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 }
2741 } 3425 }
2742 3426
2743 public void SetVehicleFloatParam(int param, float value) 3427 public void SetVehicleFloatParam(int param, float value)
2744 { 3428 {
2745 PhysicsActor pa = PhysActor; 3429 if (m_vehicleParams == null)
3430 return;
2746 3431
2747 if (pa != null) 3432 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
2748 pa.VehicleFloatParam(param, value); 3433
3434 if (_parentID == 0 && PhysActor != null)
3435 {
3436 PhysActor.VehicleFloatParam(param, value);
3437 }
2749 } 3438 }
2750 3439
2751 public void SetVehicleVectorParam(int param, Vector3 value) 3440 public void SetVehicleVectorParam(int param, Vector3 value)
2752 { 3441 {
2753 PhysicsActor pa = PhysActor; 3442 if (m_vehicleParams == null)
3443 return;
2754 3444
2755 if (pa != null) 3445 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
2756 pa.VehicleVectorParam(param, value); 3446
3447 if (_parentID == 0 && PhysActor != null)
3448 {
3449 PhysActor.VehicleVectorParam(param, value);
3450 }
2757 } 3451 }
2758 3452
2759 public void SetVehicleRotationParam(int param, Quaternion rotation) 3453 public void SetVehicleRotationParam(int param, Quaternion rotation)
2760 { 3454 {
2761 PhysicsActor pa = PhysActor; 3455 if (m_vehicleParams == null)
3456 return;
2762 3457
2763 if (pa != null) 3458 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
2764 pa.VehicleRotationParam(param, rotation); 3459
3460 if (_parentID == 0 && PhysActor != null)
3461 {
3462 PhysActor.VehicleRotationParam(param, rotation);
3463 }
2765 } 3464 }
2766 3465
2767 /// <summary> 3466 /// <summary>
@@ -2962,14 +3661,6 @@ namespace OpenSim.Region.Framework.Scenes
2962 hasProfileCut = hasDimple; // is it the same thing? 3661 hasProfileCut = hasDimple; // is it the same thing?
2963 } 3662 }
2964 3663
2965 public void SetVehicleFlags(int param, bool remove)
2966 {
2967 PhysicsActor pa = PhysActor;
2968
2969 if (pa != null)
2970 pa.VehicleFlags(param, remove);
2971 }
2972
2973 public void SetGroup(UUID groupID, IClientAPI client) 3664 public void SetGroup(UUID groupID, IClientAPI client)
2974 { 3665 {
2975 // Scene.AddNewPrims() calls with client == null so can't use this. 3666 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3069,71 +3760,20 @@ namespace OpenSim.Region.Framework.Scenes
3069 { 3760 {
3070 ParentGroup.stopMoveToTarget(); 3761 ParentGroup.stopMoveToTarget();
3071 3762
3072 ParentGroup.ScheduleGroupForTerseUpdate(); 3763// ParentGroup.ScheduleGroupForTerseUpdate();
3073 //ParentGroup.ScheduleGroupForFullUpdate(); 3764 //ParentGroup.ScheduleGroupForFullUpdate();
3074 } 3765 }
3075 3766
3076 public void StoreUndoState() 3767 public void StoreUndoState(ObjectChangeType change)
3077 {
3078 StoreUndoState(false);
3079 }
3080
3081 public void StoreUndoState(bool forGroup)
3082 { 3768 {
3083 if (ParentGroup == null || ParentGroup.Scene == null) 3769 if (m_UndoRedo == null)
3084 return; 3770 m_UndoRedo = new UndoRedoState(5);
3085
3086 if (Undoing)
3087 {
3088// m_log.DebugFormat(
3089// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3090 return;
3091 }
3092
3093 if (IgnoreUndoUpdate)
3094 {
3095// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3096 return;
3097 }
3098 3771
3099 lock (m_undo) 3772 lock (m_UndoRedo)
3100 { 3773 {
3101 if (m_undo.Count > 0) 3774 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3102 {
3103 UndoState last = m_undo[m_undo.Count - 1];
3104 if (last != null)
3105 {
3106 // TODO: May need to fix for group comparison
3107 if (last.Compare(this))
3108 {
3109// m_log.DebugFormat(
3110// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3111// Name, LocalId, m_undo.Count);
3112
3113 return;
3114 }
3115 }
3116 }
3117
3118// m_log.DebugFormat(
3119// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3120// Name, LocalId, forGroup, m_undo.Count);
3121
3122 if (ParentGroup.Scene.MaxUndoCount > 0)
3123 { 3775 {
3124 UndoState nUndo = new UndoState(this, forGroup); 3776 m_UndoRedo.StoreUndo(this, change);
3125
3126 m_undo.Add(nUndo);
3127
3128 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3129 m_undo.RemoveAt(0);
3130
3131 if (m_redo.Count > 0)
3132 m_redo.Clear();
3133
3134// m_log.DebugFormat(
3135// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3136// Name, LocalId, forGroup, m_undo.Count);
3137 } 3777 }
3138 } 3778 }
3139 } 3779 }
@@ -3145,88 +3785,46 @@ namespace OpenSim.Region.Framework.Scenes
3145 { 3785 {
3146 get 3786 get
3147 { 3787 {
3148 lock (m_undo) 3788 if (m_UndoRedo == null)
3149 return m_undo.Count; 3789 return 0;
3790 return m_UndoRedo.Count;
3150 } 3791 }
3151 } 3792 }
3152 3793
3153 public void Undo() 3794 public void Undo()
3154 { 3795 {
3155 lock (m_undo) 3796 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3156 { 3797 return;
3157// m_log.DebugFormat(
3158// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3159// Name, LocalId, m_undo.Count);
3160
3161 if (m_undo.Count > 0)
3162 {
3163 UndoState goback = m_undo[m_undo.Count - 1];
3164 m_undo.RemoveAt(m_undo.Count - 1);
3165
3166 UndoState nUndo = null;
3167
3168 if (ParentGroup.Scene.MaxUndoCount > 0)
3169 {
3170 nUndo = new UndoState(this, goback.ForGroup);
3171 }
3172
3173 goback.PlaybackState(this);
3174
3175 if (nUndo != null)
3176 {
3177 m_redo.Add(nUndo);
3178
3179 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3180 m_redo.RemoveAt(0);
3181 }
3182 }
3183 3798
3184// m_log.DebugFormat( 3799 lock (m_UndoRedo)
3185// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3800 {
3186// Name, LocalId, m_undo.Count); 3801 Undoing = true;
3802 m_UndoRedo.Undo(this);
3803 Undoing = false;
3187 } 3804 }
3188 } 3805 }
3189 3806
3190 public void Redo() 3807 public void Redo()
3191 { 3808 {
3192 lock (m_undo) 3809 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3193 { 3810 return;
3194// m_log.DebugFormat(
3195// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3196// Name, LocalId, m_redo.Count);
3197
3198 if (m_redo.Count > 0)
3199 {
3200 UndoState gofwd = m_redo[m_redo.Count - 1];
3201 m_redo.RemoveAt(m_redo.Count - 1);
3202
3203 if (ParentGroup.Scene.MaxUndoCount > 0)
3204 {
3205 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3206
3207 m_undo.Add(nUndo);
3208
3209 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3210 m_undo.RemoveAt(0);
3211 }
3212
3213 gofwd.PlayfwdState(this);
3214 3811
3215// m_log.DebugFormat( 3812 lock (m_UndoRedo)
3216// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3813 {
3217// Name, LocalId, m_redo.Count); 3814 Undoing = true;
3218 } 3815 m_UndoRedo.Redo(this);
3816 Undoing = false;
3219 } 3817 }
3220 } 3818 }
3221 3819
3222 public void ClearUndoState() 3820 public void ClearUndoState()
3223 { 3821 {
3224// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3822 if (m_UndoRedo == null || Undoing)
3823 return;
3225 3824
3226 lock (m_undo) 3825 lock (m_UndoRedo)
3227 { 3826 {
3228 m_undo.Clear(); 3827 m_UndoRedo.Clear();
3229 m_redo.Clear();
3230 } 3828 }
3231 } 3829 }
3232 3830
@@ -3777,7 +4375,7 @@ namespace OpenSim.Region.Framework.Scenes
3777 if (god) 4375 if (god)
3778 { 4376 {
3779 BaseMask = ApplyMask(BaseMask, set, mask); 4377 BaseMask = ApplyMask(BaseMask, set, mask);
3780 Inventory.ApplyGodPermissions(_baseMask); 4378 Inventory.ApplyGodPermissions(BaseMask);
3781 } 4379 }
3782 4380
3783 break; 4381 break;
@@ -3796,7 +4394,7 @@ namespace OpenSim.Region.Framework.Scenes
3796 case 16: 4394 case 16:
3797 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4395 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
3798 baseMask; 4396 baseMask;
3799 // Prevent the client from creating no mod, no copy 4397 // Prevent the client from creating no copy, no transfer
3800 // objects 4398 // objects
3801 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4399 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
3802 NextOwnerMask |= (uint)PermissionMask.Transfer; 4400 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -3814,20 +4412,20 @@ namespace OpenSim.Region.Framework.Scenes
3814 { 4412 {
3815 bool update = false; 4413 bool update = false;
3816 4414
3817 if (BaseMask != source.BaseMask || 4415 uint prevOwnerMask = OwnerMask;
3818 OwnerMask != source.OwnerMask || 4416 uint prevGroupMask = GroupMask;
3819 GroupMask != source.GroupMask || 4417 uint prevEveryoneMask = EveryoneMask;
3820 EveryoneMask != source.EveryoneMask || 4418 uint prevNextOwnerMask = NextOwnerMask;
3821 NextOwnerMask != source.NextOwnerMask)
3822 update = true;
3823 4419
3824 BaseMask = source.BaseMask; 4420 OwnerMask = source.OwnerMask & BaseMask;
3825 OwnerMask = source.OwnerMask; 4421 GroupMask = source.GroupMask & BaseMask;
3826 GroupMask = source.GroupMask; 4422 EveryoneMask = source.EveryoneMask & BaseMask;
3827 EveryoneMask = source.EveryoneMask; 4423 NextOwnerMask = source.NextOwnerMask & BaseMask;
3828 NextOwnerMask = source.NextOwnerMask;
3829 4424
3830 if (update) 4425 if (OwnerMask != prevOwnerMask ||
4426 GroupMask != prevGroupMask ||
4427 EveryoneMask != prevEveryoneMask ||
4428 NextOwnerMask != prevNextOwnerMask)
3831 SendFullUpdateToAllClients(); 4429 SendFullUpdateToAllClients();
3832 } 4430 }
3833 4431
@@ -3878,6 +4476,27 @@ namespace OpenSim.Region.Framework.Scenes
3878 } 4476 }
3879 } 4477 }
3880 4478
4479
4480 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4481 {
4482 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4483 return;
4484
4485 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4486 {
4487 PhysicsShapeType = (byte)physdata.PhysShapeType;
4488
4489 }
4490
4491 if(Density != physdata.Density)
4492 Density = physdata.Density;
4493 if(GravityModifier != physdata.GravitationModifier)
4494 GravityModifier = physdata.GravitationModifier;
4495 if(Friction != physdata.Friction)
4496 Friction = physdata.Friction;
4497 if(Bounciness != physdata.Bounce)
4498 Bounciness = physdata.Bounce;
4499 }
3881 /// <summary> 4500 /// <summary>
3882 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4501 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3883 /// </summary> 4502 /// </summary>
@@ -3885,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
3885 /// <param name="SetTemporary"></param> 4504 /// <param name="SetTemporary"></param>
3886 /// <param name="SetPhantom"></param> 4505 /// <param name="SetPhantom"></param>
3887 /// <param name="SetVD"></param> 4506 /// <param name="SetVD"></param>
3888 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)
3889 { 4508 {
3890 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4509 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3891 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4510 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3895,214 +4514,230 @@ namespace OpenSim.Region.Framework.Scenes
3895 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4514 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3896 return; 4515 return;
3897 4516
3898 PhysicsActor pa = PhysActor; 4517 VolumeDetectActive = SetVD;
3899
3900 // Special cases for VD. VD can only be called from a script
3901 // and can't be combined with changes to other states. So we can rely
3902 // that...
3903 // ... if VD is changed, all others are not.
3904 // ... if one of the others is changed, VD is not.
3905 if (SetVD) // VD is active, special logic applies
3906 {
3907 // State machine logic for VolumeDetect
3908 // More logic below
3909 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3910
3911 if (phanReset) // Phantom changes from on to off switch VD off too
3912 {
3913 SetVD = false; // Switch it of for the course of this routine
3914 VolumeDetectActive = false; // and also permanently
3915
3916 if (pa != null)
3917 pa.SetVolumeDetect(0); // Let physics know about it too
3918 }
3919 else
3920 {
3921 // If volumedetect is active we don't want phantom to be applied.
3922 // If this is a new call to VD out of the state "phantom"
3923 // this will also cause the prim to be visible to physics
3924 SetPhantom = false;
3925 }
3926 }
3927 4518
3928 if (UsePhysics && IsJoint()) 4519 // volume detector implies phantom
3929 { 4520 if (VolumeDetectActive)
3930 SetPhantom = true; 4521 SetPhantom = true;
3931 }
3932 4522
3933 if (UsePhysics) 4523 if (UsePhysics)
3934 {
3935 AddFlag(PrimFlags.Physics); 4524 AddFlag(PrimFlags.Physics);
3936 if (!wasUsingPhysics)
3937 {
3938 DoPhysicsPropertyUpdate(UsePhysics, false);
3939 }
3940 }
3941 else 4525 else
3942 {
3943 RemFlag(PrimFlags.Physics); 4526 RemFlag(PrimFlags.Physics);
3944 if (wasUsingPhysics)
3945 {
3946 DoPhysicsPropertyUpdate(UsePhysics, false);
3947 }
3948 }
3949 4527
3950 if (SetPhantom 4528 if (SetPhantom)
3951 || ParentGroup.IsAttachment
3952 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3953 {
3954 AddFlag(PrimFlags.Phantom); 4529 AddFlag(PrimFlags.Phantom);
3955 4530 else
3956 if (PhysActor != null)
3957 {
3958 RemoveFromPhysics();
3959 pa = null;
3960 }
3961 }
3962 else // Not phantom
3963 {
3964 RemFlag(PrimFlags.Phantom); 4531 RemFlag(PrimFlags.Phantom);
3965 4532
3966 if (ParentGroup.Scene == null) 4533 if (SetTemporary)
3967 return; 4534 AddFlag(PrimFlags.TemporaryOnRez);
4535 else
4536 RemFlag(PrimFlags.TemporaryOnRez);
3968 4537
3969 if (ParentGroup.Scene.CollidablePrims && pa == null)
3970 {
3971 pa = AddToPhysics(UsePhysics);
3972 4538
3973 if (pa != null) 4539 if (ParentGroup.Scene == null)
3974 { 4540 return;
3975 pa.SetMaterial(Material); 4541
3976 DoPhysicsPropertyUpdate(UsePhysics, true); 4542 PhysicsActor pa = PhysActor;
3977
3978 if (
3979 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
3980 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3981 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3982 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
3983 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
3984 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
3985 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
3986 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
3987 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
3988 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
3989 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
3990 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
3991 (CollisionSound != UUID.Zero)
3992 )
3993 {
3994 pa.OnCollisionUpdate += PhysicsCollision;
3995 pa.SubscribeEvents(1000);
3996 }
3997 }
3998 }
3999 else // it already has a physical representation
4000 {
4001 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4002 }
4003 }
4004 4543
4005 if (SetVD) 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))
4006 { 4549 {
4007 // If the above logic worked (this is urgent candidate to unit tests!)
4008 // we now have a physicsactor.
4009 // Defensive programming calls for a check here.
4010 // Better would be throwing an exception that could be catched by a unit test as the internal
4011 // logic should make sure, this Physactor is always here.
4012 if (pa != null) 4550 if (pa != null)
4013 { 4551 {
4014 pa.SetVolumeDetect(1); 4552 if(wasUsingPhysics)
4015 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4553 ParentGroup.Scene.RemovePhysicalPrim(1);
4016 VolumeDetectActive = true; 4554 RemoveFromPhysics();
4017 } 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);
4018 } 4561 }
4019 else if (SetVD != wasVD) 4562 else if (SetVD != wasVD)
4020 { 4563 {
4021 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4564 if (ParentGroup.Scene.CollidablePrims)
4022 // (mumbles, well, at least if you have infinte CPU powers :-)) 4565 {
4023 if (pa != null) 4566 if (pa == null)
4024 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*/
4025 4600
4026 RemFlag(PrimFlags.Phantom); 4601 if (pa.Building != building)
4027 VolumeDetectActive = false; 4602 pa.Building = building;
4028 } 4603 }
4029 4604
4030 if (SetTemporary) 4605 UpdatePhysicsSubscribedEvents();
4031 { 4606 }
4032 AddFlag(PrimFlags.TemporaryOnRez); 4607 }
4033 }
4034 else
4035 {
4036 RemFlag(PrimFlags.TemporaryOnRez);
4037 }
4038 4608
4039 // 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());
4040 4610
4611 // and last in case we have a new actor and not building
4612
4041 if (ParentGroup != null) 4613 if (ParentGroup != null)
4042 { 4614 {
4043 ParentGroup.HasGroupChanged = true; 4615 ParentGroup.HasGroupChanged = true;
4044 ScheduleFullUpdate(); 4616 ScheduleFullUpdate();
4045 } 4617 }
4046 4618
4047// 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);
4048 } 4620 }
4049 4621
4050 /// <summary> 4622 /// <summary>
4051 /// Adds this part to the physics scene. 4623 /// Adds this part to the physics scene.
4624 /// and sets the PhysActor property
4052 /// </summary> 4625 /// </summary>
4053 /// <remarks>This method also sets the PhysActor property.</remarks> 4626 /// <param name="isPhysical">Add this prim as physical.</param>
4054 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4627 /// <param name="isPhantom">Add this prim as phantom.</param>
4055 /// <returns> 4628 /// <param name="building">tells physics to delay full construction of object</param>
4056 /// The physics actor. null if there was a failure. 4629 /// <param name="applyDynamics">applies velocities, force and torque</param>
4057 /// </returns> 4630 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4058 private PhysicsActor AddToPhysics(bool rigidBody) 4631 {
4059 {
4060 PhysicsActor pa; 4632 PhysicsActor pa;
4061 4633
4634 Vector3 velocity = Velocity;
4635 Vector3 rotationalVelocity = AngularVelocity;;
4636
4062 try 4637 try
4063 { 4638 {
4064 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4639 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4065 string.Format("{0}/{1}", Name, UUID), 4640 string.Format("{0}/{1}", Name, UUID),
4066 Shape, 4641 Shape,
4067 AbsolutePosition, 4642 AbsolutePosition,
4068 Scale, 4643 Scale,
4069 RotationOffset, 4644 GetWorldRotation(),
4070 rigidBody, 4645 isPhysical,
4071 m_localId); 4646 isPhantom,
4647 PhysicsShapeType,
4648 m_localId);
4072 } 4649 }
4073 catch (Exception e) 4650 catch (Exception e)
4074 { 4651 {
4075 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);
4076 pa = null; 4653 pa = null;
4077 } 4654 }
4078 4655
4079 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4080 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4081 // being set.
4082 PhysActor = pa;
4083
4084 // Basic Physics can also return null as well as an exception catch.
4085 if (pa != null) 4656 if (pa != null)
4086 { 4657 {
4087 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
4088 pa.SetMaterial(Material); 4659 pa.SetMaterial(Material);
4089 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;
4090 } 4718 }
4091 4719
4092 return pa; 4720 PhysActor = pa;
4093 } 4721 }
4094 4722
4095 /// <summary> 4723 /// <summary>
4096 /// This removes the part from the physics scene. 4724 /// This removes the part from the physics scene.
4097 /// </summary> 4725 /// </summary>
4098 /// <remarks> 4726 /// <remarks>
4099 /// 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
4100 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4728 /// representation for collision detection.
4101 /// phantom.
4102 /// </remarks> 4729 /// </remarks>
4103 public void RemoveFromPhysics() 4730 public void RemoveFromPhysics()
4104 { 4731 {
4105 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 }
4106 PhysActor = null; 4741 PhysActor = null;
4107 } 4742 }
4108 4743
@@ -4234,6 +4869,8 @@ namespace OpenSim.Region.Framework.Scenes
4234 { 4869 {
4235// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 4870// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4236 4871
4872 return;
4873
4237 if (ParentGroup.IsDeleted) 4874 if (ParentGroup.IsDeleted)
4238 return; 4875 return;
4239 4876
@@ -4314,6 +4951,44 @@ namespace OpenSim.Region.Framework.Scenes
4314 ScheduleFullUpdate(); 4951 ScheduleFullUpdate();
4315 } 4952 }
4316 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
4317 public void aggregateScriptEvents() 4992 public void aggregateScriptEvents()
4318 { 4993 {
4319 if (ParentGroup == null || ParentGroup.RootPart == null) 4994 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4350,40 +5025,32 @@ namespace OpenSim.Region.Framework.Scenes
4350 { 5025 {
4351 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5026 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4352 } 5027 }
4353 5028/*
4354 PhysicsActor pa = PhysActor; 5029 PhysicsActor pa = PhysActor;
4355 5030 if (pa != null)
4356 if (
4357 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4358 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4359 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4360 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4361 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4362 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4363 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4364 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4365 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4366 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4367 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4368 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4369 (CollisionSound != UUID.Zero)
4370 )
4371 { 5031 {
4372 // subscribe to physics updates. 5032 if (
4373 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 )
4374 { 5041 {
5042 // subscribe to physics updates.
4375 pa.OnCollisionUpdate += PhysicsCollision; 5043 pa.OnCollisionUpdate += PhysicsCollision;
4376 pa.SubscribeEvents(1000); 5044 pa.SubscribeEvents(1000);
4377 } 5045 }
4378 } 5046 else
4379 else
4380 {
4381 if (pa != null)
4382 { 5047 {
4383 pa.UnSubscribeEvents(); 5048 pa.UnSubscribeEvents();
4384 pa.OnCollisionUpdate -= PhysicsCollision; 5049 pa.OnCollisionUpdate -= PhysicsCollision;
4385 } 5050 }
4386 } 5051 }
5052 */
5053 UpdatePhysicsSubscribedEvents();
4387 5054
4388 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5055 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4389 //{ 5056 //{
@@ -4514,6 +5181,18 @@ namespace OpenSim.Region.Framework.Scenes
4514 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));
4515 } 5182 }
4516 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
4517 /// <summary> 5196 /// <summary>
4518 /// Record an avatar sitting on this part. 5197 /// Record an avatar sitting on this part.
4519 /// </summary> 5198 /// </summary>