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.cs1639
1 files changed, 1123 insertions, 516 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 17c7661..61ef827 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -121,7 +122,18 @@ namespace OpenSim.Region.Framework.Scenes
121 /// Denote all sides of the prim 122 /// Denote all sides of the prim
122 /// </value> 123 /// </value>
123 public const int ALL_SIDES = -1; 124 public const int ALL_SIDES = -1;
124 125
126 private const scriptEvents PhysicsNeededSubsEvents = (
127 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
128 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
129 );
130 private const scriptEvents PhyscicsPhantonSubsEvents = (
131 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
132 );
133 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
134 scriptEvents.collision_start | scriptEvents.collision_end
135 );
136
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 138
127 /// <value> 139 /// <value>
@@ -176,12 +188,25 @@ namespace OpenSim.Region.Framework.Scenes
176 188
177 public double SoundRadius; 189 public double SoundRadius;
178 190
191
179 public uint TimeStampFull; 192 public uint TimeStampFull;
180 193
181 public uint TimeStampLastActivity; // Will be used for AutoReturn 194 public uint TimeStampLastActivity; // Will be used for AutoReturn
182 195
183 public uint TimeStampTerse; 196 public uint TimeStampTerse;
184 197
198 // The following two are to hold the attachment data
199 // while an object is inworld
200 [XmlIgnore]
201 public byte AttachPoint = 0;
202
203 [XmlIgnore]
204 public Vector3 AttachOffset = Vector3.Zero;
205
206 [XmlIgnore]
207 public Quaternion AttachRotation = Quaternion.Identity;
208
209 [XmlIgnore]
185 public int STATUS_ROTATE_X; 210 public int STATUS_ROTATE_X;
186 211
187 public int STATUS_ROTATE_Y; 212 public int STATUS_ROTATE_Y;
@@ -208,8 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
208 233
209 public Vector3 RotationAxis = Vector3.One; 234 public Vector3 RotationAxis = Vector3.One;
210 235
211 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 236 public bool VolumeDetectActive;
212 // Certainly this must be a persistant setting finally
213 237
214 public bool IsWaitingForFirstSpinUpdatePacket; 238 public bool IsWaitingForFirstSpinUpdatePacket;
215 239
@@ -249,10 +273,10 @@ namespace OpenSim.Region.Framework.Scenes
249 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 273 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
250 private Vector3 m_sitTargetPosition; 274 private Vector3 m_sitTargetPosition;
251 private string m_sitAnimation = "SIT"; 275 private string m_sitAnimation = "SIT";
276 private bool m_occupied; // KF if any av is sitting on this prim
252 private string m_text = String.Empty; 277 private string m_text = String.Empty;
253 private string m_touchName = String.Empty; 278 private string m_touchName = String.Empty;
254 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 279 private UndoRedoState m_UndoRedo = null;
255 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
256 280
257 private bool m_passTouches = false; 281 private bool m_passTouches = false;
258 private bool m_passCollisions = false; 282 private bool m_passCollisions = false;
@@ -281,7 +305,19 @@ namespace OpenSim.Region.Framework.Scenes
281 protected Vector3 m_lastAcceleration; 305 protected Vector3 m_lastAcceleration;
282 protected Vector3 m_lastAngularVelocity; 306 protected Vector3 m_lastAngularVelocity;
283 protected int m_lastTerseSent; 307 protected int m_lastTerseSent;
284 308 protected float m_buoyancy = 0.0f;
309 protected Vector3 m_force;
310 protected Vector3 m_torque;
311
312 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
313 protected float m_density = 1000.0f; // in kg/m^3
314 protected float m_gravitymod = 1.0f;
315 protected float m_friction = 0.6f; // wood
316 protected float m_bounce = 0.5f; // wood
317
318
319 protected bool m_isSelected = false;
320
285 /// <summary> 321 /// <summary>
286 /// Stores media texture data 322 /// Stores media texture data
287 /// </summary> 323 /// </summary>
@@ -293,10 +329,25 @@ namespace OpenSim.Region.Framework.Scenes
293 private Vector3 m_cameraAtOffset; 329 private Vector3 m_cameraAtOffset;
294 private bool m_forceMouselook; 330 private bool m_forceMouselook;
295 331
296 // TODO: Collision sound should have default. 332
333 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
334 private sbyte m_collisionSoundType;
297 private UUID m_collisionSound; 335 private UUID m_collisionSound;
298 private float m_collisionSoundVolume; 336 private float m_collisionSoundVolume;
299 337
338 private int LastColSoundSentTime;
339
340
341 private SOPVehicle m_vehicle = null;
342
343 private KeyframeMotion m_keyframeMotion = null;
344
345 public KeyframeMotion KeyframeMotion
346 {
347 get; set;
348 }
349
350
300 #endregion Fields 351 #endregion Fields
301 352
302// ~SceneObjectPart() 353// ~SceneObjectPart()
@@ -325,6 +376,7 @@ namespace OpenSim.Region.Framework.Scenes
325 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 376 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
326 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 377 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
327 m_inventory = new SceneObjectPartInventory(this); 378 m_inventory = new SceneObjectPartInventory(this);
379 LastColSoundSentTime = Util.EnvironmentTickCount();
328 } 380 }
329 381
330 /// <summary> 382 /// <summary>
@@ -339,7 +391,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 391 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) : this() 392 Quaternion rotationOffset, Vector3 offsetPosition) : this()
341 { 393 {
342 m_name = "Primitive"; 394 m_name = "Object";
343 395
344 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 396 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
345 LastOwnerID = CreatorID = OwnerID = ownerID; 397 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -379,7 +431,7 @@ namespace OpenSim.Region.Framework.Scenes
379 private uint _ownerMask = (uint)PermissionMask.All; 431 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 432 private uint _groupMask = (uint)PermissionMask.None;
381 private uint _everyoneMask = (uint)PermissionMask.None; 433 private uint _everyoneMask = (uint)PermissionMask.None;
382 private uint _nextOwnerMask = (uint)PermissionMask.All; 434 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
383 private PrimFlags _flags = PrimFlags.None; 435 private PrimFlags _flags = PrimFlags.None;
384 private DateTime m_expires; 436 private DateTime m_expires;
385 private DateTime m_rezzed; 437 private DateTime m_rezzed;
@@ -473,12 +525,16 @@ namespace OpenSim.Region.Framework.Scenes
473 } 525 }
474 526
475 /// <value> 527 /// <value>
476 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 528 /// Get the inventory list
477 /// </value> 529 /// </value>
478 public TaskInventoryDictionary TaskInventory 530 public TaskInventoryDictionary TaskInventory
479 { 531 {
480 get { return m_inventory.Items; } 532 get {
481 set { m_inventory.Items = value; } 533 return m_inventory.Items;
534 }
535 set {
536 m_inventory.Items = value;
537 }
482 } 538 }
483 539
484 /// <summary> 540 /// <summary>
@@ -528,20 +584,6 @@ namespace OpenSim.Region.Framework.Scenes
528 } 584 }
529 } 585 }
530 586
531 public byte Material
532 {
533 get { return (byte) m_material; }
534 set
535 {
536 m_material = (Material)value;
537
538 PhysicsActor pa = PhysActor;
539
540 if (pa != null)
541 pa.SetMaterial((int)value);
542 }
543 }
544
545 [XmlIgnore] 587 [XmlIgnore]
546 public bool PassTouches 588 public bool PassTouches
547 { 589 {
@@ -567,6 +609,18 @@ namespace OpenSim.Region.Framework.Scenes
567 } 609 }
568 } 610 }
569 611
612 public bool IsSelected
613 {
614 get { return m_isSelected; }
615 set
616 {
617 m_isSelected = value;
618 if (ParentGroup != null)
619 ParentGroup.PartSelectChanged(value);
620 }
621 }
622
623
570 public Dictionary<int, string> CollisionFilter 624 public Dictionary<int, string> CollisionFilter
571 { 625 {
572 get { return m_CollisionFilter; } 626 get { return m_CollisionFilter; }
@@ -635,14 +689,12 @@ namespace OpenSim.Region.Framework.Scenes
635 set { m_LoopSoundSlavePrims = value; } 689 set { m_LoopSoundSlavePrims = value; }
636 } 690 }
637 691
638
639 public Byte[] TextureAnimation 692 public Byte[] TextureAnimation
640 { 693 {
641 get { return m_TextureAnimation; } 694 get { return m_TextureAnimation; }
642 set { m_TextureAnimation = value; } 695 set { m_TextureAnimation = value; }
643 } 696 }
644 697
645
646 public Byte[] ParticleSystem 698 public Byte[] ParticleSystem
647 { 699 {
648 get { return m_particleSystem; } 700 get { return m_particleSystem; }
@@ -679,8 +731,12 @@ namespace OpenSim.Region.Framework.Scenes
679 { 731 {
680 // If this is a linkset, we don't want the physics engine mucking up our group position here. 732 // If this is a linkset, we don't want the physics engine mucking up our group position here.
681 PhysicsActor actor = PhysActor; 733 PhysicsActor actor = PhysActor;
682 if (actor != null && ParentID == 0) 734 if (ParentID == 0)
683 m_groupPosition = actor.Position; 735 {
736 if (actor != null)
737 m_groupPosition = actor.Position;
738 return m_groupPosition;
739 }
684 740
685 if (ParentGroup.IsAttachment) 741 if (ParentGroup.IsAttachment)
686 { 742 {
@@ -689,12 +745,14 @@ namespace OpenSim.Region.Framework.Scenes
689 return sp.AbsolutePosition; 745 return sp.AbsolutePosition;
690 } 746 }
691 747
748 // use root prim's group position. Physics may have updated it
749 if (ParentGroup.RootPart != this)
750 m_groupPosition = ParentGroup.RootPart.GroupPosition;
692 return m_groupPosition; 751 return m_groupPosition;
693 } 752 }
694 set 753 set
695 { 754 {
696 m_groupPosition = value; 755 m_groupPosition = value;
697
698 PhysicsActor actor = PhysActor; 756 PhysicsActor actor = PhysActor;
699 if (actor != null) 757 if (actor != null)
700 { 758 {
@@ -720,16 +778,6 @@ namespace OpenSim.Region.Framework.Scenes
720 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 778 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
721 } 779 }
722 } 780 }
723
724 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
725 if (SitTargetAvatar != UUID.Zero)
726 {
727 ScenePresence avatar;
728 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
729 {
730 avatar.ParentPosition = GetWorldPosition();
731 }
732 }
733 } 781 }
734 } 782 }
735 783
@@ -738,7 +786,7 @@ namespace OpenSim.Region.Framework.Scenes
738 get { return m_offsetPosition; } 786 get { return m_offsetPosition; }
739 set 787 set
740 { 788 {
741// StoreUndoState(); 789 Vector3 oldpos = m_offsetPosition;
742 m_offsetPosition = value; 790 m_offsetPosition = value;
743 791
744 if (ParentGroup != null && !ParentGroup.IsDeleted) 792 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -753,7 +801,22 @@ namespace OpenSim.Region.Framework.Scenes
753 if (ParentGroup.Scene != null) 801 if (ParentGroup.Scene != null)
754 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 802 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
755 } 803 }
804
805 if (!m_parentGroup.m_dupeInProgress)
806 {
807 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
808 foreach (ScenePresence av in avs)
809 {
810 if (av.ParentID == m_localId)
811 {
812 Vector3 offset = (m_offsetPosition - oldpos);
813 av.AbsolutePosition += offset;
814 av.SendAvatarDataToAllAgents();
815 }
816 }
817 }
756 } 818 }
819 TriggerScriptChangedEvent(Changed.POSITION);
757 } 820 }
758 } 821 }
759 822
@@ -802,7 +865,7 @@ namespace OpenSim.Region.Framework.Scenes
802 865
803 set 866 set
804 { 867 {
805 StoreUndoState(); 868// StoreUndoState();
806 m_rotationOffset = value; 869 m_rotationOffset = value;
807 870
808 PhysicsActor actor = PhysActor; 871 PhysicsActor actor = PhysActor;
@@ -890,7 +953,7 @@ namespace OpenSim.Region.Framework.Scenes
890 get 953 get
891 { 954 {
892 PhysicsActor actor = PhysActor; 955 PhysicsActor actor = PhysActor;
893 if ((actor != null) && actor.IsPhysical) 956 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
894 { 957 {
895 m_angularVelocity = actor.RotationalVelocity; 958 m_angularVelocity = actor.RotationalVelocity;
896 } 959 }
@@ -902,7 +965,16 @@ namespace OpenSim.Region.Framework.Scenes
902 /// <summary></summary> 965 /// <summary></summary>
903 public Vector3 Acceleration 966 public Vector3 Acceleration
904 { 967 {
905 get { return m_acceleration; } 968 get
969 {
970 PhysicsActor actor = PhysActor;
971 if (actor != null)
972 {
973 m_acceleration = actor.Acceleration;
974 }
975 return m_acceleration;
976 }
977
906 set { m_acceleration = value; } 978 set { m_acceleration = value; }
907 } 979 }
908 980
@@ -970,7 +1042,10 @@ namespace OpenSim.Region.Framework.Scenes
970 public PrimitiveBaseShape Shape 1042 public PrimitiveBaseShape Shape
971 { 1043 {
972 get { return m_shape; } 1044 get { return m_shape; }
973 set { m_shape = value;} 1045 set
1046 {
1047 m_shape = value;
1048 }
974 } 1049 }
975 1050
976 /// <summary> 1051 /// <summary>
@@ -983,7 +1058,6 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1058 {
984 if (m_shape != null) 1059 if (m_shape != null)
985 { 1060 {
986 StoreUndoState();
987 1061
988 m_shape.Scale = value; 1062 m_shape.Scale = value;
989 1063
@@ -1010,6 +1084,7 @@ namespace OpenSim.Region.Framework.Scenes
1010 } 1084 }
1011 1085
1012 public UpdateRequired UpdateFlag { get; set; } 1086 public UpdateRequired UpdateFlag { get; set; }
1087 public bool UpdatePhysRequired { get; set; }
1013 1088
1014 /// <summary> 1089 /// <summary>
1015 /// Used for media on a prim. 1090 /// Used for media on a prim.
@@ -1050,10 +1125,7 @@ namespace OpenSim.Region.Framework.Scenes
1050 { 1125 {
1051 get 1126 get
1052 { 1127 {
1053 if (ParentGroup.IsAttachment) 1128 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1054 return GroupPosition;
1055
1056 return m_offsetPosition + m_groupPosition;
1057 } 1129 }
1058 } 1130 }
1059 1131
@@ -1231,6 +1303,13 @@ namespace OpenSim.Region.Framework.Scenes
1231 _flags = value; 1303 _flags = value;
1232 } 1304 }
1233 } 1305 }
1306
1307 [XmlIgnore]
1308 public bool IsOccupied // KF If an av is sittingon this prim
1309 {
1310 get { return m_occupied; }
1311 set { m_occupied = value; }
1312 }
1234 1313
1235 /// <summary> 1314 /// <summary>
1236 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1315 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1274,12 +1353,41 @@ namespace OpenSim.Region.Framework.Scenes
1274 set { m_sitAnimation = value; } 1353 set { m_sitAnimation = value; }
1275 } 1354 }
1276 1355
1356 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1357
1358 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1359 // runtime thing.. do not persist
1360 [XmlIgnore]
1361 public sbyte CollisionSoundType
1362 {
1363 get
1364 {
1365 return m_collisionSoundType;
1366 }
1367 set
1368 {
1369 m_collisionSoundType = value;
1370 if (value == -1)
1371 m_collisionSound = invalidCollisionSoundUUID;
1372 else if (value == 0)
1373 m_collisionSound = UUID.Zero;
1374 }
1375 }
1376
1277 public UUID CollisionSound 1377 public UUID CollisionSound
1278 { 1378 {
1279 get { return m_collisionSound; } 1379 get { return m_collisionSound; }
1280 set 1380 set
1281 { 1381 {
1282 m_collisionSound = value; 1382 m_collisionSound = value;
1383
1384 if (value == invalidCollisionSoundUUID)
1385 m_collisionSoundType = -1;
1386 else if (value == UUID.Zero)
1387 m_collisionSoundType = 0;
1388 else
1389 m_collisionSoundType = 1;
1390
1283 aggregateScriptEvents(); 1391 aggregateScriptEvents();
1284 } 1392 }
1285 } 1393 }
@@ -1290,6 +1398,319 @@ namespace OpenSim.Region.Framework.Scenes
1290 set { m_collisionSoundVolume = value; } 1398 set { m_collisionSoundVolume = value; }
1291 } 1399 }
1292 1400
1401 public float Buoyancy
1402 {
1403 get
1404 {
1405 if (ParentGroup.RootPart == this)
1406 return m_buoyancy;
1407
1408 return ParentGroup.RootPart.Buoyancy;
1409 }
1410 set
1411 {
1412 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1413 {
1414 ParentGroup.RootPart.Buoyancy = value;
1415 return;
1416 }
1417 m_buoyancy = value;
1418 if (PhysActor != null)
1419 PhysActor.Buoyancy = value;
1420 }
1421 }
1422
1423 public Vector3 Force
1424 {
1425 get
1426 {
1427 if (ParentGroup.RootPart == this)
1428 return m_force;
1429
1430 return ParentGroup.RootPart.Force;
1431 }
1432
1433 set
1434 {
1435 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1436 {
1437 ParentGroup.RootPart.Force = value;
1438 return;
1439 }
1440 m_force = value;
1441 if (PhysActor != null)
1442 PhysActor.Force = value;
1443 }
1444 }
1445
1446 public Vector3 Torque
1447 {
1448 get
1449 {
1450 if (ParentGroup.RootPart == this)
1451 return m_torque;
1452
1453 return ParentGroup.RootPart.Torque;
1454 }
1455
1456 set
1457 {
1458 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1459 {
1460 ParentGroup.RootPart.Torque = value;
1461 return;
1462 }
1463 m_torque = value;
1464 if (PhysActor != null)
1465 PhysActor.Torque = value;
1466 }
1467 }
1468
1469 public byte Material
1470 {
1471 get { return (byte)m_material; }
1472 set
1473 {
1474 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1475 {
1476 bool update = false;
1477
1478 if (m_material != (Material)value)
1479 {
1480 update = true;
1481 m_material = (Material)value;
1482 }
1483
1484 if (m_friction != SOPMaterialData.friction(m_material))
1485 {
1486 update = true;
1487 m_friction = SOPMaterialData.friction(m_material);
1488 }
1489
1490 if (m_bounce != SOPMaterialData.bounce(m_material))
1491 {
1492 update = true;
1493 m_bounce = SOPMaterialData.bounce(m_material);
1494 }
1495
1496 if (update)
1497 {
1498 if (PhysActor != null)
1499 {
1500 PhysActor.SetMaterial((int)value);
1501 }
1502 if(ParentGroup != null)
1503 ParentGroup.HasGroupChanged = true;
1504 ScheduleFullUpdateIfNone();
1505 UpdatePhysRequired = true;
1506 }
1507 }
1508 }
1509 }
1510
1511 // not a propriety to move to methods place later
1512 private bool HasMesh()
1513 {
1514 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1515 return true;
1516 return false;
1517 }
1518
1519 // not a propriety to move to methods place later
1520 public byte DefaultPhysicsShapeType()
1521 {
1522 byte type;
1523
1524 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1525 type = (byte)PhysShapeType.convex;
1526 else
1527 type = (byte)PhysShapeType.prim;
1528
1529 return type;
1530 }
1531
1532 [XmlIgnore]
1533 public bool UsesComplexCost
1534 {
1535 get
1536 {
1537 byte pst = PhysicsShapeType;
1538 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1539 return true;
1540 return false;
1541 }
1542 }
1543
1544 [XmlIgnore]
1545 public float PhysicsCost
1546 {
1547 get
1548 {
1549 if(PhysicsShapeType == (byte)PhysShapeType.none)
1550 return 0;
1551
1552 float cost = 0.1f;
1553 if (PhysActor != null)
1554// cost += PhysActor.Cost;
1555
1556 if ((Flags & PrimFlags.Physics) != 0)
1557 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1558 return cost;
1559 }
1560 }
1561
1562 [XmlIgnore]
1563 public float StreamingCost
1564 {
1565 get
1566 {
1567
1568
1569 return 0.1f;
1570 }
1571 }
1572
1573 [XmlIgnore]
1574 public float SimulationCost
1575 {
1576 get
1577 {
1578 // ignoring scripts. Don't like considering them for this
1579 if((Flags & PrimFlags.Physics) != 0)
1580 return 1.0f;
1581
1582 return 0.5f;
1583 }
1584 }
1585
1586 public byte PhysicsShapeType
1587 {
1588 get { return m_physicsShapeType; }
1589 set
1590 {
1591 byte oldv = m_physicsShapeType;
1592
1593 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1594 {
1595 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1596 m_physicsShapeType = DefaultPhysicsShapeType();
1597 else
1598 m_physicsShapeType = value;
1599 }
1600 else
1601 m_physicsShapeType = DefaultPhysicsShapeType();
1602
1603 if (m_physicsShapeType != oldv && ParentGroup != null)
1604 {
1605 if (m_physicsShapeType == (byte)PhysShapeType.none)
1606 {
1607 if (PhysActor != null)
1608 {
1609 Velocity = new Vector3(0, 0, 0);
1610 Acceleration = new Vector3(0, 0, 0);
1611 if (ParentGroup.RootPart == this)
1612 AngularVelocity = new Vector3(0, 0, 0);
1613 ParentGroup.Scene.RemovePhysicalPrim(1);
1614 RemoveFromPhysics();
1615 }
1616 }
1617 else if (PhysActor == null)
1618 {
1619 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1620 UpdatePhysicsSubscribedEvents();
1621 }
1622 else
1623 {
1624 PhysActor.PhysicsShapeType = m_physicsShapeType;
1625 if (Shape.SculptEntry)
1626 CheckSculptAndLoad();
1627 }
1628
1629 if (ParentGroup != null)
1630 ParentGroup.HasGroupChanged = true;
1631 }
1632
1633 if (m_physicsShapeType != value)
1634 {
1635 UpdatePhysRequired = true;
1636 }
1637 }
1638 }
1639
1640 public float Density // in kg/m^3
1641 {
1642 get { return m_density; }
1643 set
1644 {
1645 if (value >=1 && value <= 22587.0)
1646 {
1647 m_density = value;
1648 UpdatePhysRequired = true;
1649 }
1650
1651 ScheduleFullUpdateIfNone();
1652
1653 if (ParentGroup != null)
1654 ParentGroup.HasGroupChanged = true;
1655 }
1656 }
1657
1658 public float GravityModifier
1659 {
1660 get { return m_gravitymod; }
1661 set
1662 {
1663 if( value >= -1 && value <=28.0f)
1664 {
1665 m_gravitymod = value;
1666 UpdatePhysRequired = true;
1667 }
1668
1669 ScheduleFullUpdateIfNone();
1670
1671 if (ParentGroup != null)
1672 ParentGroup.HasGroupChanged = true;
1673
1674 }
1675 }
1676
1677 public float Friction
1678 {
1679 get { return m_friction; }
1680 set
1681 {
1682 if (value >= 0 && value <= 255.0f)
1683 {
1684 m_friction = value;
1685 UpdatePhysRequired = true;
1686 }
1687
1688 ScheduleFullUpdateIfNone();
1689
1690 if (ParentGroup != null)
1691 ParentGroup.HasGroupChanged = true;
1692 }
1693 }
1694
1695 public float Bounciness
1696 {
1697 get { return m_bounce; }
1698 set
1699 {
1700 if (value >= 0 && value <= 1.0f)
1701 {
1702 m_bounce = value;
1703 UpdatePhysRequired = true;
1704 }
1705
1706 ScheduleFullUpdateIfNone();
1707
1708 if (ParentGroup != null)
1709 ParentGroup.HasGroupChanged = true;
1710 }
1711 }
1712
1713
1293 #endregion Public Properties with only Get 1714 #endregion Public Properties with only Get
1294 1715
1295 private uint ApplyMask(uint val, bool set, uint mask) 1716 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1455,7 +1876,7 @@ namespace OpenSim.Region.Framework.Scenes
1455 impulse = newimpulse; 1876 impulse = newimpulse;
1456 } 1877 }
1457 1878
1458 ParentGroup.applyAngularImpulse(impulse); 1879 ParentGroup.ApplyAngularImpulse(impulse);
1459 } 1880 }
1460 1881
1461 /// <summary> 1882 /// <summary>
@@ -1465,20 +1886,24 @@ namespace OpenSim.Region.Framework.Scenes
1465 /// </summary> 1886 /// </summary>
1466 /// <param name="impulsei">Vector force</param> 1887 /// <param name="impulsei">Vector force</param>
1467 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1888 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1468 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1889
1890 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1891 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1469 { 1892 {
1470 Vector3 impulse = impulsei; 1893 Vector3 torque = torquei;
1471 1894
1472 if (localGlobalTF) 1895 if (localGlobalTF)
1473 { 1896 {
1897/*
1474 Quaternion grot = GetWorldRotation(); 1898 Quaternion grot = GetWorldRotation();
1475 Quaternion AXgrot = grot; 1899 Quaternion AXgrot = grot;
1476 Vector3 AXimpulsei = impulsei; 1900 Vector3 AXimpulsei = impulsei;
1477 Vector3 newimpulse = AXimpulsei * AXgrot; 1901 Vector3 newimpulse = AXimpulsei * AXgrot;
1478 impulse = newimpulse; 1902 */
1903 torque *= GetWorldRotation();
1479 } 1904 }
1480 1905
1481 ParentGroup.setAngularImpulse(impulse); 1906 Torque = torque;
1482 } 1907 }
1483 1908
1484 /// <summary> 1909 /// <summary>
@@ -1486,17 +1911,23 @@ namespace OpenSim.Region.Framework.Scenes
1486 /// </summary> 1911 /// </summary>
1487 /// <param name="rootObjectFlags"></param> 1912 /// <param name="rootObjectFlags"></param>
1488 /// <param name="VolumeDetectActive"></param> 1913 /// <param name="VolumeDetectActive"></param>
1489 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1914 /// <param name="building"></param>
1915
1916 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1490 { 1917 {
1918 VolumeDetectActive = _VolumeDetectActive;
1919
1491 if (!ParentGroup.Scene.CollidablePrims) 1920 if (!ParentGroup.Scene.CollidablePrims)
1492 return; 1921 return;
1493 1922
1494// m_log.DebugFormat( 1923 if (PhysicsShapeType == (byte)PhysShapeType.none)
1495// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1924 return;
1496// Name, LocalId, UUID, m_physicalPrim); 1925
1926 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1927 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1497 1928
1498 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1929 if (_VolumeDetectActive)
1499 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1930 isPhantom = true;
1500 1931
1501 if (IsJoint()) 1932 if (IsJoint())
1502 { 1933 {
@@ -1504,22 +1935,14 @@ namespace OpenSim.Region.Framework.Scenes
1504 } 1935 }
1505 else 1936 else
1506 { 1937 {
1507 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1938 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1508 if (VolumeDetectActive) 1939 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1509 isPhantom = false;
1510
1511 // 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
1512 // or flexible
1513 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1514 { 1940 {
1515 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1941 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1516 bool rigidBody = isPhysical && !isPhantom; 1942 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1517
1518 PhysicsActor pa = AddToPhysics(rigidBody);
1519
1520 if (pa != null)
1521 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1522 } 1943 }
1944 else
1945 PhysActor = null; // just to be sure
1523 } 1946 }
1524 } 1947 }
1525 1948
@@ -1571,6 +1994,12 @@ namespace OpenSim.Region.Framework.Scenes
1571 dupe.Category = Category; 1994 dupe.Category = Category;
1572 dupe.m_rezzed = m_rezzed; 1995 dupe.m_rezzed = m_rezzed;
1573 1996
1997 dupe.m_UndoRedo = null;
1998 dupe.m_isSelected = false;
1999
2000 dupe.IgnoreUndoUpdate = false;
2001 dupe.Undoing = false;
2002
1574 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2003 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1575 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2004 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1576 2005
@@ -1586,6 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 2015
1587 // Move afterwards ResetIDs as it clears the localID 2016 // Move afterwards ResetIDs as it clears the localID
1588 dupe.LocalId = localID; 2017 dupe.LocalId = localID;
2018
1589 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2019 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1590 dupe.LastOwnerID = OwnerID; 2020 dupe.LastOwnerID = OwnerID;
1591 2021
@@ -1603,8 +2033,12 @@ namespace OpenSim.Region.Framework.Scenes
1603 2033
1604 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2034 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1605 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2035 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2036// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1606 } 2037 }
1607 2038
2039 if (dupe.PhysActor != null)
2040 dupe.PhysActor.LocalID = localID;
2041
1608 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2042 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1609 2043
1610// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2044// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1724,6 +2158,7 @@ namespace OpenSim.Region.Framework.Scenes
1724 2158
1725 /// <summary> 2159 /// <summary>
1726 /// Do a physics propery update for this part. 2160 /// Do a physics propery update for this part.
2161 /// now also updates phantom and volume detector
1727 /// </summary> 2162 /// </summary>
1728 /// <param name="UsePhysics"></param> 2163 /// <param name="UsePhysics"></param>
1729 /// <param name="isNew"></param> 2164 /// <param name="isNew"></param>
@@ -1749,61 +2184,69 @@ namespace OpenSim.Region.Framework.Scenes
1749 { 2184 {
1750 if (pa.IsPhysical) // implies UsePhysics==false for this block 2185 if (pa.IsPhysical) // implies UsePhysics==false for this block
1751 { 2186 {
1752 if (!isNew) 2187 if (!isNew) // implies UsePhysics==false for this block
2188 {
1753 ParentGroup.Scene.RemovePhysicalPrim(1); 2189 ParentGroup.Scene.RemovePhysicalPrim(1);
1754 2190
1755 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2191 Velocity = new Vector3(0, 0, 0);
1756 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2192 Acceleration = new Vector3(0, 0, 0);
1757 pa.delink(); 2193 if (ParentGroup.RootPart == this)
2194 AngularVelocity = new Vector3(0, 0, 0);
1758 2195
1759 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2196 if (pa.Phantom && !VolumeDetectActive)
1760 { 2197 {
1761 // destroy all joints connected to this now deactivated body 2198 RemoveFromPhysics();
1762 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2199 return;
1763 } 2200 }
1764 2201
1765 // stop client-side interpolation of all joint proxy objects that have just been deleted 2202 pa.IsPhysical = UsePhysics;
1766 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2203 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1767 // which stops client-side interpolation of deactivated joint proxy objects. 2204 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2205 pa.delink();
2206 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2207 {
2208 // destroy all joints connected to this now deactivated body
2209 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2210 }
2211 }
1768 } 2212 }
1769 2213
1770 if (!UsePhysics && !isNew) 2214 if (pa.IsPhysical != UsePhysics)
1771 { 2215 pa.IsPhysical = UsePhysics;
1772 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1773 // prim still has velocity and continues to interpolate its position along the old
1774 // velocity-vector.
1775 Velocity = new Vector3(0, 0, 0);
1776 Acceleration = new Vector3(0, 0, 0);
1777 AngularVelocity = new Vector3(0, 0, 0);
1778 //RotationalVelocity = new Vector3(0, 0, 0);
1779 }
1780 2216
1781 pa.IsPhysical = UsePhysics; 2217 if (UsePhysics)
2218 {
2219 if (ParentGroup.RootPart.KeyframeMotion != null)
2220 ParentGroup.RootPart.KeyframeMotion.Stop();
2221 ParentGroup.RootPart.KeyframeMotion = null;
2222 ParentGroup.Scene.AddPhysicalPrim(1);
1782 2223
1783 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2224 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1784 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2225 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1785 /// that's not wholesome. Had to make Scene public
1786 //PhysActor = null;
1787 2226
1788 if ((Flags & PrimFlags.Phantom) == 0) 2227 if (ParentID != 0 && ParentID != LocalId)
1789 {
1790 if (UsePhysics)
1791 { 2228 {
1792 ParentGroup.Scene.AddPhysicalPrim(1); 2229 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1793 2230
1794 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2231 if (parentPa != null)
1795 pa.OnOutOfBounds += PhysicsOutOfBounds;
1796 if (ParentID != 0 && ParentID != LocalId)
1797 { 2232 {
1798 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2233 pa.link(parentPa);
1799
1800 if (parentPa != null)
1801 {
1802 pa.link(parentPa);
1803 }
1804 } 2234 }
1805 } 2235 }
1806 } 2236 }
2237 }
2238
2239 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2240 if (pa.Phantom != phan)
2241 pa.Phantom = phan;
2242
2243// some engines dont' have this check still
2244// if (VolumeDetectActive != pa.IsVolumeDtc)
2245 {
2246 if (VolumeDetectActive)
2247 pa.SetVolumeDetect(1);
2248 else
2249 pa.SetVolumeDetect(0);
1807 } 2250 }
1808 2251
1809 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2252 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1922,12 +2365,26 @@ namespace OpenSim.Region.Framework.Scenes
1922 2365
1923 public Vector3 GetGeometricCenter() 2366 public Vector3 GetGeometricCenter()
1924 { 2367 {
1925 PhysicsActor pa = PhysActor; 2368 // this is not real geometric center but a average of positions relative to root prim acording to
1926 2369 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
1927 if (pa != null) 2370 // ignoring tortured prims details since sl also seems to ignore
1928 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2371 // so no real use in doing it on physics
1929 else 2372 if (ParentGroup.IsDeleted)
1930 return new Vector3(0, 0, 0); 2373 return new Vector3(0, 0, 0);
2374
2375 return ParentGroup.GetGeometricCenter();
2376
2377 /*
2378 PhysicsActor pa = PhysActor;
2379
2380 if (pa != null)
2381 {
2382 Vector3 vtmp = pa.CenterOfMass;
2383 return vtmp;
2384 }
2385 else
2386 return new Vector3(0, 0, 0);
2387 */
1931 } 2388 }
1932 2389
1933 public float GetMass() 2390 public float GetMass()
@@ -1940,14 +2397,43 @@ namespace OpenSim.Region.Framework.Scenes
1940 return 0; 2397 return 0;
1941 } 2398 }
1942 2399
1943 public Vector3 GetForce() 2400 public Vector3 GetCenterOfMass()
2401 {
2402 if (ParentGroup.RootPart == this)
2403 {
2404 if (ParentGroup.IsDeleted)
2405 return AbsolutePosition;
2406 return ParentGroup.GetCenterOfMass();
2407 }
2408
2409 PhysicsActor pa = PhysActor;
2410
2411 if (pa != null)
2412 {
2413 Vector3 tmp = pa.CenterOfMass;
2414 return tmp;
2415 }
2416 else
2417 return AbsolutePosition;
2418 }
2419
2420 public Vector3 GetPartCenterOfMass()
1944 { 2421 {
1945 PhysicsActor pa = PhysActor; 2422 PhysicsActor pa = PhysActor;
1946 2423
1947 if (pa != null) 2424 if (pa != null)
1948 return pa.Force; 2425 {
2426 Vector3 tmp = pa.CenterOfMass;
2427 return tmp;
2428 }
1949 else 2429 else
1950 return Vector3.Zero; 2430 return AbsolutePosition;
2431 }
2432
2433
2434 public Vector3 GetForce()
2435 {
2436 return Force;
1951 } 2437 }
1952 2438
1953 /// <summary> 2439 /// <summary>
@@ -2154,15 +2640,25 @@ namespace OpenSim.Region.Framework.Scenes
2154 2640
2155 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2641 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2156 { 2642 {
2157 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2643 bool sendToRoot = true;
2158 {
2159 ColliderArgs LandCollidingMessage = new ColliderArgs();
2160 List<DetectedObject> colliding = new List<DetectedObject>();
2161
2162 colliding.Add(CreateDetObjectForGround());
2163 LandCollidingMessage.Colliders = colliding;
2164 2644
2645 ColliderArgs LandCollidingMessage = new ColliderArgs();
2646 List<DetectedObject> colliding = new List<DetectedObject>();
2647
2648 colliding.Add(CreateDetObjectForGround());
2649 LandCollidingMessage.Colliders = colliding;
2650
2651 if (Inventory.ContainsScripts())
2652 {
2653 if (!PassCollisions)
2654 sendToRoot = false;
2655 }
2656 if ((ScriptEvents & ev) != 0)
2165 notify(LocalId, LandCollidingMessage); 2657 notify(LocalId, LandCollidingMessage);
2658
2659 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2660 {
2661 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2166 } 2662 }
2167 } 2663 }
2168 2664
@@ -2178,45 +2674,87 @@ namespace OpenSim.Region.Framework.Scenes
2178 List<uint> endedColliders = new List<uint>(); 2674 List<uint> endedColliders = new List<uint>();
2179 List<uint> startedColliders = new List<uint>(); 2675 List<uint> startedColliders = new List<uint>();
2180 2676
2181 // calculate things that started colliding this time 2677 if (collissionswith.Count == 0)
2182 // and build up list of colliders this time
2183 foreach (uint localid in collissionswith.Keys)
2184 { 2678 {
2185 thisHitColliders.Add(localid); 2679 if (m_lastColliders.Count == 0)
2186 if (!m_lastColliders.Contains(localid)) 2680 return; // nothing to do
2187 startedColliders.Add(localid);
2188 }
2189 2681
2190 // calculate things that ended colliding 2682 foreach (uint localID in m_lastColliders)
2191 foreach (uint localID in m_lastColliders) 2683 {
2192 {
2193 if (!thisHitColliders.Contains(localID))
2194 endedColliders.Add(localID); 2684 endedColliders.Add(localID);
2685 }
2686 m_lastColliders.Clear();
2195 } 2687 }
2196 2688
2197 //add the items that started colliding this time to the last colliders list. 2689 else
2198 foreach (uint localID in startedColliders) 2690 {
2199 m_lastColliders.Add(localID); 2691 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2692
2693 // calculate things that started colliding this time
2694 // and build up list of colliders this time
2695 if (!VolumeDetectActive && CollisionSoundType >= 0)
2696 {
2697 CollisionForSoundInfo soundinfo;
2698 ContactPoint curcontact;
2699
2700 foreach (uint id in collissionswith.Keys)
2701 {
2702 thisHitColliders.Add(id);
2703 if (!m_lastColliders.Contains(id))
2704 {
2705 startedColliders.Add(id);
2706
2707 curcontact = collissionswith[id];
2708 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2709 {
2710 soundinfo = new CollisionForSoundInfo();
2711 soundinfo.colliderID = id;
2712 soundinfo.position = curcontact.Position;
2713 soundinfo.relativeVel = curcontact.RelativeSpeed;
2714 soundinfolist.Add(soundinfo);
2715 }
2716 }
2717 }
2718 }
2719 else
2720 {
2721 foreach (uint id in collissionswith.Keys)
2722 {
2723 thisHitColliders.Add(id);
2724 if (!m_lastColliders.Contains(id))
2725 startedColliders.Add(id);
2726 }
2727 }
2728
2729 // calculate things that ended colliding
2730 foreach (uint localID in m_lastColliders)
2731 {
2732 if (!thisHitColliders.Contains(localID))
2733 endedColliders.Add(localID);
2734 }
2735
2736 //add the items that started colliding this time to the last colliders list.
2737 foreach (uint localID in startedColliders)
2738 m_lastColliders.Add(localID);
2200 2739
2201 // remove things that ended colliding from the last colliders list 2740 // remove things that ended colliding from the last colliders list
2202 foreach (uint localID in endedColliders) 2741 foreach (uint localID in endedColliders)
2203 m_lastColliders.Remove(localID); 2742 m_lastColliders.Remove(localID);
2204 2743
2205 // play the sound. 2744 // play sounds.
2206 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2745 if (soundinfolist.Count > 0)
2207 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); 2746 CollisionSounds.PartCollisionSound(this, soundinfolist);
2747 }
2208 2748
2209 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2749 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2210 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2750 if (!VolumeDetectActive)
2751 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2211 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2752 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2212 2753
2213 if (startedColliders.Contains(0)) 2754 if (startedColliders.Contains(0))
2214 { 2755 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2215 if (m_lastColliders.Contains(0)) 2756 if (m_lastColliders.Contains(0))
2216 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2757 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2217 else
2218 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2219 }
2220 if (endedColliders.Contains(0)) 2758 if (endedColliders.Contains(0))
2221 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2759 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2222 } 2760 }
@@ -2239,9 +2777,9 @@ namespace OpenSim.Region.Framework.Scenes
2239 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2777 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2240 2778
2241 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2779 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2242 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2780 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2243 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2781 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2244 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2782 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2245 { 2783 {
2246 ParentGroup.AbsolutePosition = newpos; 2784 ParentGroup.AbsolutePosition = newpos;
2247 return; 2785 return;
@@ -2263,17 +2801,18 @@ namespace OpenSim.Region.Framework.Scenes
2263 //Trys to fetch sound id from prim's inventory. 2801 //Trys to fetch sound id from prim's inventory.
2264 //Prim's inventory doesn't support non script items yet 2802 //Prim's inventory doesn't support non script items yet
2265 2803
2266 lock (TaskInventory) 2804 TaskInventory.LockItemsForRead(true);
2805
2806 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2267 { 2807 {
2268 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2808 if (item.Value.Name == sound)
2269 { 2809 {
2270 if (item.Value.Name == sound) 2810 soundID = item.Value.ItemID;
2271 { 2811 break;
2272 soundID = item.Value.ItemID;
2273 break;
2274 }
2275 } 2812 }
2276 } 2813 }
2814
2815 TaskInventory.LockItemsForRead(false);
2277 } 2816 }
2278 2817
2279 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2818 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2396,6 +2935,19 @@ namespace OpenSim.Region.Framework.Scenes
2396 APIDTarget = Quaternion.Identity; 2935 APIDTarget = Quaternion.Identity;
2397 } 2936 }
2398 2937
2938
2939
2940 public void ScheduleFullUpdateIfNone()
2941 {
2942 if (ParentGroup == null)
2943 return;
2944
2945// ??? ParentGroup.HasGroupChanged = true;
2946
2947 if (UpdateFlag != UpdateRequired.FULL)
2948 ScheduleFullUpdate();
2949 }
2950
2399 /// <summary> 2951 /// <summary>
2400 /// Schedules this prim for a full update 2952 /// Schedules this prim for a full update
2401 /// </summary> 2953 /// </summary>
@@ -2597,8 +3149,8 @@ namespace OpenSim.Region.Framework.Scenes
2597 { 3149 {
2598 const float ROTATION_TOLERANCE = 0.01f; 3150 const float ROTATION_TOLERANCE = 0.01f;
2599 const float VELOCITY_TOLERANCE = 0.001f; 3151 const float VELOCITY_TOLERANCE = 0.001f;
2600 const float POSITION_TOLERANCE = 0.05f; 3152 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2601 const int TIME_MS_TOLERANCE = 3000; 3153 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2602 3154
2603 switch (UpdateFlag) 3155 switch (UpdateFlag)
2604 { 3156 {
@@ -2660,17 +3212,16 @@ namespace OpenSim.Region.Framework.Scenes
2660 if (!UUID.TryParse(sound, out soundID)) 3212 if (!UUID.TryParse(sound, out soundID))
2661 { 3213 {
2662 // search sound file from inventory 3214 // search sound file from inventory
2663 lock (TaskInventory) 3215 TaskInventory.LockItemsForRead(true);
3216 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2664 { 3217 {
2665 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3218 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2666 { 3219 {
2667 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3220 soundID = item.Value.ItemID;
2668 { 3221 break;
2669 soundID = item.Value.ItemID;
2670 break;
2671 }
2672 } 3222 }
2673 } 3223 }
3224 TaskInventory.LockItemsForRead(false);
2674 } 3225 }
2675 3226
2676 if (soundID == UUID.Zero) 3227 if (soundID == UUID.Zero)
@@ -2727,6 +3278,35 @@ namespace OpenSim.Region.Framework.Scenes
2727 } 3278 }
2728 } 3279 }
2729 3280
3281 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3282 {
3283 if (soundID == UUID.Zero)
3284 return;
3285
3286 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3287 if (soundModule == null)
3288 return;
3289
3290 if (volume > 1)
3291 volume = 1;
3292 if (volume < 0)
3293 volume = 0;
3294
3295 int now = Util.EnvironmentTickCount();
3296 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3297 return;
3298
3299 LastColSoundSentTime = now;
3300
3301 UUID ownerID = OwnerID;
3302 UUID objectID = ParentGroup.RootPart.UUID;
3303 UUID parentID = ParentGroup.UUID;
3304 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3305
3306 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3307 }
3308
3309
2730 /// <summary> 3310 /// <summary>
2731 /// Send a terse update to all clients 3311 /// Send a terse update to all clients
2732 /// </summary> 3312 /// </summary>
@@ -2755,10 +3335,13 @@ namespace OpenSim.Region.Framework.Scenes
2755 3335
2756 public void SetBuoyancy(float fvalue) 3336 public void SetBuoyancy(float fvalue)
2757 { 3337 {
2758 PhysicsActor pa = PhysActor; 3338 Buoyancy = fvalue;
2759 3339/*
2760 if (pa != null) 3340 if (PhysActor != null)
2761 pa.Buoyancy = fvalue; 3341 {
3342 PhysActor.Buoyancy = fvalue;
3343 }
3344 */
2762 } 3345 }
2763 3346
2764 public void SetDieAtEdge(bool p) 3347 public void SetDieAtEdge(bool p)
@@ -2774,47 +3357,111 @@ namespace OpenSim.Region.Framework.Scenes
2774 PhysicsActor pa = PhysActor; 3357 PhysicsActor pa = PhysActor;
2775 3358
2776 if (pa != null) 3359 if (pa != null)
2777 pa.FloatOnWater = floatYN == 1; 3360 pa.FloatOnWater = (floatYN == 1);
2778 } 3361 }
2779 3362
2780 public void SetForce(Vector3 force) 3363 public void SetForce(Vector3 force)
2781 { 3364 {
2782 PhysicsActor pa = PhysActor; 3365 Force = force;
3366 }
2783 3367
2784 if (pa != null) 3368 public SOPVehicle sopVehicle
2785 pa.Force = force; 3369 {
3370 get
3371 {
3372 return m_vehicle;
3373 }
3374 set
3375 {
3376 m_vehicle = value;
3377 }
3378 }
3379
3380
3381 public int VehicleType
3382 {
3383 get
3384 {
3385 if (m_vehicle == null)
3386 return (int)Vehicle.TYPE_NONE;
3387 else
3388 return (int)m_vehicle.Type;
3389 }
3390 set
3391 {
3392 SetVehicleType(value);
3393 }
2786 } 3394 }
2787 3395
2788 public void SetVehicleType(int type) 3396 public void SetVehicleType(int type)
2789 { 3397 {
2790 PhysicsActor pa = PhysActor; 3398 m_vehicle = null;
3399
3400 if (type == (int)Vehicle.TYPE_NONE)
3401 {
3402 if (_parentID ==0 && PhysActor != null)
3403 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3404 return;
3405 }
3406 m_vehicle = new SOPVehicle();
3407 m_vehicle.ProcessTypeChange((Vehicle)type);
3408 {
3409 if (_parentID ==0 && PhysActor != null)
3410 PhysActor.VehicleType = type;
3411 return;
3412 }
3413 }
2791 3414
2792 if (pa != null) 3415 public void SetVehicleFlags(int param, bool remove)
2793 pa.VehicleType = type; 3416 {
3417 if (m_vehicle == null)
3418 return;
3419
3420 m_vehicle.ProcessVehicleFlags(param, remove);
3421
3422 if (_parentID ==0 && PhysActor != null)
3423 {
3424 PhysActor.VehicleFlags(param, remove);
3425 }
2794 } 3426 }
2795 3427
2796 public void SetVehicleFloatParam(int param, float value) 3428 public void SetVehicleFloatParam(int param, float value)
2797 { 3429 {
2798 PhysicsActor pa = PhysActor; 3430 if (m_vehicle == null)
3431 return;
2799 3432
2800 if (pa != null) 3433 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
2801 pa.VehicleFloatParam(param, value); 3434
3435 if (_parentID == 0 && PhysActor != null)
3436 {
3437 PhysActor.VehicleFloatParam(param, value);
3438 }
2802 } 3439 }
2803 3440
2804 public void SetVehicleVectorParam(int param, Vector3 value) 3441 public void SetVehicleVectorParam(int param, Vector3 value)
2805 { 3442 {
2806 PhysicsActor pa = PhysActor; 3443 if (m_vehicle == null)
3444 return;
2807 3445
2808 if (pa != null) 3446 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
2809 pa.VehicleVectorParam(param, value); 3447
3448 if (_parentID == 0 && PhysActor != null)
3449 {
3450 PhysActor.VehicleVectorParam(param, value);
3451 }
2810 } 3452 }
2811 3453
2812 public void SetVehicleRotationParam(int param, Quaternion rotation) 3454 public void SetVehicleRotationParam(int param, Quaternion rotation)
2813 { 3455 {
2814 PhysicsActor pa = PhysActor; 3456 if (m_vehicle == null)
3457 return;
2815 3458
2816 if (pa != null) 3459 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
2817 pa.VehicleRotationParam(param, rotation); 3460
3461 if (_parentID == 0 && PhysActor != null)
3462 {
3463 PhysActor.VehicleRotationParam(param, rotation);
3464 }
2818 } 3465 }
2819 3466
2820 /// <summary> 3467 /// <summary>
@@ -2998,14 +3645,6 @@ namespace OpenSim.Region.Framework.Scenes
2998 hasProfileCut = hasDimple; // is it the same thing? 3645 hasProfileCut = hasDimple; // is it the same thing?
2999 } 3646 }
3000 3647
3001 public void SetVehicleFlags(int param, bool remove)
3002 {
3003 PhysicsActor pa = PhysActor;
3004
3005 if (pa != null)
3006 pa.VehicleFlags(param, remove);
3007 }
3008
3009 public void SetGroup(UUID groupID, IClientAPI client) 3648 public void SetGroup(UUID groupID, IClientAPI client)
3010 { 3649 {
3011 // Scene.AddNewPrims() calls with client == null so can't use this. 3650 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3109,68 +3748,18 @@ namespace OpenSim.Region.Framework.Scenes
3109 //ParentGroup.ScheduleGroupForFullUpdate(); 3748 //ParentGroup.ScheduleGroupForFullUpdate();
3110 } 3749 }
3111 3750
3112 public void StoreUndoState() 3751 public void StoreUndoState(ObjectChangeType change)
3113 { 3752 {
3114 StoreUndoState(false); 3753 if (m_UndoRedo == null)
3115 } 3754 m_UndoRedo = new UndoRedoState(5);
3116 3755
3117 public void StoreUndoState(bool forGroup) 3756 lock (m_UndoRedo)
3118 {
3119 if (!Undoing)
3120 { 3757 {
3121 if (!IgnoreUndoUpdate) 3758 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3122 { 3759 {
3123 if (ParentGroup != null) 3760 m_UndoRedo.StoreUndo(this, change);
3124 {
3125 lock (m_undo)
3126 {
3127 if (m_undo.Count > 0)
3128 {
3129 UndoState last = m_undo.Peek();
3130 if (last != null)
3131 {
3132 // TODO: May need to fix for group comparison
3133 if (last.Compare(this))
3134 {
3135 // m_log.DebugFormat(
3136 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3137 // Name, LocalId, m_undo.Count);
3138
3139 return;
3140 }
3141 }
3142 }
3143
3144 // m_log.DebugFormat(
3145 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3146 // Name, LocalId, forGroup, m_undo.Count);
3147
3148 if (ParentGroup.GetSceneMaxUndo() > 0)
3149 {
3150 UndoState nUndo = new UndoState(this, forGroup);
3151
3152 m_undo.Push(nUndo);
3153
3154 if (m_redo.Count > 0)
3155 m_redo.Clear();
3156
3157 // m_log.DebugFormat(
3158 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3159 // Name, LocalId, forGroup, m_undo.Count);
3160 }
3161 }
3162 }
3163 } 3761 }
3164// else
3165// {
3166// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3167// }
3168 } 3762 }
3169// else
3170// {
3171// m_log.DebugFormat(
3172// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3173// }
3174 } 3763 }
3175 3764
3176 /// <summary> 3765 /// <summary>
@@ -3180,84 +3769,46 @@ namespace OpenSim.Region.Framework.Scenes
3180 { 3769 {
3181 get 3770 get
3182 { 3771 {
3183 lock (m_undo) 3772 if (m_UndoRedo == null)
3184 return m_undo.Count; 3773 return 0;
3774 return m_UndoRedo.Count;
3185 } 3775 }
3186 } 3776 }
3187 3777
3188 public void Undo() 3778 public void Undo()
3189 { 3779 {
3190 lock (m_undo) 3780 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3191 { 3781 return;
3192// m_log.DebugFormat(
3193// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3194// Name, LocalId, m_undo.Count);
3195
3196 if (m_undo.Count > 0)
3197 {
3198 UndoState goback = m_undo.Pop();
3199
3200 if (goback != null)
3201 {
3202 UndoState nUndo = null;
3203
3204 if (ParentGroup.GetSceneMaxUndo() > 0)
3205 {
3206 nUndo = new UndoState(this, goback.ForGroup);
3207 }
3208
3209 goback.PlaybackState(this);
3210
3211 if (nUndo != null)
3212 m_redo.Push(nUndo);
3213 }
3214 }
3215 3782
3216// m_log.DebugFormat( 3783 lock (m_UndoRedo)
3217// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3784 {
3218// Name, LocalId, m_undo.Count); 3785 Undoing = true;
3786 m_UndoRedo.Undo(this);
3787 Undoing = false;
3219 } 3788 }
3220 } 3789 }
3221 3790
3222 public void Redo() 3791 public void Redo()
3223 { 3792 {
3224 lock (m_undo) 3793 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3225 { 3794 return;
3226// m_log.DebugFormat(
3227// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3228// Name, LocalId, m_redo.Count);
3229
3230 if (m_redo.Count > 0)
3231 {
3232 UndoState gofwd = m_redo.Pop();
3233
3234 if (gofwd != null)
3235 {
3236 if (ParentGroup.GetSceneMaxUndo() > 0)
3237 {
3238 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3239
3240 m_undo.Push(nUndo);
3241 }
3242
3243 gofwd.PlayfwdState(this);
3244 }
3245 3795
3246// m_log.DebugFormat( 3796 lock (m_UndoRedo)
3247// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3797 {
3248// Name, LocalId, m_redo.Count); 3798 Undoing = true;
3249 } 3799 m_UndoRedo.Redo(this);
3800 Undoing = false;
3250 } 3801 }
3251 } 3802 }
3252 3803
3253 public void ClearUndoState() 3804 public void ClearUndoState()
3254 { 3805 {
3255// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3806 if (m_UndoRedo == null || Undoing)
3807 return;
3256 3808
3257 lock (m_undo) 3809 lock (m_UndoRedo)
3258 { 3810 {
3259 m_undo.Clear(); 3811 m_UndoRedo.Clear();
3260 m_redo.Clear();
3261 } 3812 }
3262 } 3813 }
3263 3814
@@ -3887,6 +4438,27 @@ namespace OpenSim.Region.Framework.Scenes
3887 } 4438 }
3888 } 4439 }
3889 4440
4441
4442 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4443 {
4444 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4445 return;
4446
4447 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4448 {
4449 PhysicsShapeType = (byte)physdata.PhysShapeType;
4450
4451 }
4452
4453 if(Density != physdata.Density)
4454 Density = physdata.Density;
4455 if(GravityModifier != physdata.GravitationModifier)
4456 GravityModifier = physdata.GravitationModifier;
4457 if(Friction != physdata.Friction)
4458 Friction = physdata.Friction;
4459 if(Bounciness != physdata.Bounce)
4460 Bounciness = physdata.Bounce;
4461 }
3890 /// <summary> 4462 /// <summary>
3891 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4463 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3892 /// </summary> 4464 /// </summary>
@@ -3894,7 +4466,7 @@ namespace OpenSim.Region.Framework.Scenes
3894 /// <param name="SetTemporary"></param> 4466 /// <param name="SetTemporary"></param>
3895 /// <param name="SetPhantom"></param> 4467 /// <param name="SetPhantom"></param>
3896 /// <param name="SetVD"></param> 4468 /// <param name="SetVD"></param>
3897 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4469 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3898 { 4470 {
3899 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4471 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3900 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4472 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3904,237 +4476,230 @@ namespace OpenSim.Region.Framework.Scenes
3904 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4476 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3905 return; 4477 return;
3906 4478
3907 PhysicsActor pa = PhysActor; 4479 VolumeDetectActive = SetVD;
3908
3909 // Special cases for VD. VD can only be called from a script
3910 // and can't be combined with changes to other states. So we can rely
3911 // that...
3912 // ... if VD is changed, all others are not.
3913 // ... if one of the others is changed, VD is not.
3914 if (SetVD) // VD is active, special logic applies
3915 {
3916 // State machine logic for VolumeDetect
3917 // More logic below
3918 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3919
3920 if (phanReset) // Phantom changes from on to off switch VD off too
3921 {
3922 SetVD = false; // Switch it of for the course of this routine
3923 VolumeDetectActive = false; // and also permanently
3924
3925 if (pa != null)
3926 pa.SetVolumeDetect(0); // Let physics know about it too
3927 }
3928 else
3929 {
3930 // If volumedetect is active we don't want phantom to be applied.
3931 // If this is a new call to VD out of the state "phantom"
3932 // this will also cause the prim to be visible to physics
3933 SetPhantom = false;
3934 }
3935 }
3936 4480
3937 if (UsePhysics && IsJoint()) 4481 // volume detector implies phantom
3938 { 4482 if (VolumeDetectActive)
3939 SetPhantom = true; 4483 SetPhantom = true;
3940 }
3941 4484
3942 if (UsePhysics) 4485 if (UsePhysics)
3943 {
3944 AddFlag(PrimFlags.Physics); 4486 AddFlag(PrimFlags.Physics);
3945 if (!wasUsingPhysics)
3946 {
3947 DoPhysicsPropertyUpdate(UsePhysics, false);
3948
3949 if (!ParentGroup.IsDeleted)
3950 {
3951 if (LocalId == ParentGroup.RootPart.LocalId)
3952 {
3953 ParentGroup.CheckSculptAndLoad();
3954 }
3955 }
3956 }
3957 }
3958 else 4487 else
3959 {
3960 RemFlag(PrimFlags.Physics); 4488 RemFlag(PrimFlags.Physics);
3961 if (wasUsingPhysics)
3962 {
3963 DoPhysicsPropertyUpdate(UsePhysics, false);
3964 }
3965 }
3966 4489
3967 if (SetPhantom 4490 if (SetPhantom)
3968 || ParentGroup.IsAttachment
3969 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3970 {
3971 AddFlag(PrimFlags.Phantom); 4491 AddFlag(PrimFlags.Phantom);
3972 4492 else
3973 if (PhysActor != null)
3974 {
3975 RemoveFromPhysics();
3976 pa = null;
3977 }
3978 }
3979 else // Not phantom
3980 {
3981 RemFlag(PrimFlags.Phantom); 4493 RemFlag(PrimFlags.Phantom);
3982 4494
3983 if (ParentGroup.Scene == null) 4495 if (SetTemporary)
3984 return; 4496 AddFlag(PrimFlags.TemporaryOnRez);
4497 else
4498 RemFlag(PrimFlags.TemporaryOnRez);
3985 4499
3986 if (ParentGroup.Scene.CollidablePrims && pa == null)
3987 {
3988 pa = AddToPhysics(UsePhysics);
3989 4500
3990 if (pa != null) 4501 if (ParentGroup.Scene == null)
3991 { 4502 return;
3992 pa.SetMaterial(Material);
3993 DoPhysicsPropertyUpdate(UsePhysics, true);
3994
3995 if (!ParentGroup.IsDeleted)
3996 {
3997 if (LocalId == ParentGroup.RootPart.LocalId)
3998 {
3999 ParentGroup.CheckSculptAndLoad();
4000 }
4001 }
4002
4003 if (
4004 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4005 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4006 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4007 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4008 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4009 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4010 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4011 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4012 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4013 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4014 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4015 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4016 (CollisionSound != UUID.Zero)
4017 )
4018 {
4019 pa.OnCollisionUpdate += PhysicsCollision;
4020 pa.SubscribeEvents(1000);
4021 }
4022 }
4023 }
4024 else // it already has a physical representation
4025 {
4026 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4027 4503
4028 if (!ParentGroup.IsDeleted) 4504 PhysicsActor pa = PhysActor;
4029 {
4030 if (LocalId == ParentGroup.RootPart.LocalId)
4031 {
4032 ParentGroup.CheckSculptAndLoad();
4033 }
4034 }
4035 }
4036 }
4037 4505
4038 if (SetVD) 4506 if (pa != null && building && pa.Building != building)
4507 pa.Building = building;
4508
4509 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4510 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4039 { 4511 {
4040 // If the above logic worked (this is urgent candidate to unit tests!)
4041 // we now have a physicsactor.
4042 // Defensive programming calls for a check here.
4043 // Better would be throwing an exception that could be catched by a unit test as the internal
4044 // logic should make sure, this Physactor is always here.
4045 if (pa != null) 4512 if (pa != null)
4046 { 4513 {
4047 pa.SetVolumeDetect(1); 4514 ParentGroup.Scene.RemovePhysicalPrim(1);
4048 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4515 RemoveFromPhysics();
4049 VolumeDetectActive = true;
4050 } 4516 }
4517
4518 Velocity = new Vector3(0, 0, 0);
4519 Acceleration = new Vector3(0, 0, 0);
4520 if (ParentGroup.RootPart == this)
4521 AngularVelocity = new Vector3(0, 0, 0);
4051 } 4522 }
4052 else 4523 else
4053 { 4524 {
4054 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4525 if (ParentGroup.Scene.CollidablePrims)
4055 // (mumbles, well, at least if you have infinte CPU powers :-)) 4526 {
4056 if (pa != null) 4527 if (pa == null)
4057 pa.SetVolumeDetect(0); 4528 {
4529 AddToPhysics(UsePhysics, SetPhantom, building, false);
4530 pa = PhysActor;
4531 /*
4532 if (pa != null)
4533 {
4534 if (
4535 // ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4536 // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4537 // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4538 // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4539 // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4540 // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4541 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4542 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4543 (CollisionSound != UUID.Zero)
4544 )
4545 {
4546 pa.OnCollisionUpdate += PhysicsCollision;
4547 pa.SubscribeEvents(1000);
4548 }
4549 }
4550 */
4551 }
4552 else // it already has a physical representation
4553 {
4554 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4555 /* moved into DoPhysicsPropertyUpdate
4556 if(VolumeDetectActive)
4557 pa.SetVolumeDetect(1);
4558 else
4559 pa.SetVolumeDetect(0);
4560 */
4058 4561
4059 VolumeDetectActive = false;
4060 }
4061 4562
4062 if (SetTemporary) 4563 if (pa.Building != building)
4063 { 4564 pa.Building = building;
4064 AddFlag(PrimFlags.TemporaryOnRez); 4565 }
4065 } 4566
4066 else 4567 UpdatePhysicsSubscribedEvents();
4067 { 4568 }
4068 RemFlag(PrimFlags.TemporaryOnRez); 4569 }
4069 }
4070 4570
4071 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4571 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4072 4572
4573 // and last in case we have a new actor and not building
4574
4073 if (ParentGroup != null) 4575 if (ParentGroup != null)
4074 { 4576 {
4075 ParentGroup.HasGroupChanged = true; 4577 ParentGroup.HasGroupChanged = true;
4076 ScheduleFullUpdate(); 4578 ScheduleFullUpdate();
4077 } 4579 }
4078 4580
4079// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4581// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4080 } 4582 }
4081 4583
4082 /// <summary> 4584 /// <summary>
4083 /// Adds this part to the physics scene. 4585 /// Adds this part to the physics scene.
4586 /// and sets the PhysActor property
4084 /// </summary> 4587 /// </summary>
4085 /// <remarks>This method also sets the PhysActor property.</remarks> 4588 /// <param name="isPhysical">Add this prim as physical.</param>
4086 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4589 /// <param name="isPhantom">Add this prim as phantom.</param>
4087 /// <returns> 4590 /// <param name="building">tells physics to delay full construction of object</param>
4088 /// The physics actor. null if there was a failure. 4591 /// <param name="applyDynamics">applies velocities, force and torque</param>
4089 /// </returns> 4592 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4090 private PhysicsActor AddToPhysics(bool rigidBody) 4593 {
4091 {
4092 PhysicsActor pa; 4594 PhysicsActor pa;
4093 4595
4596 Vector3 velocity = Velocity;
4597 Vector3 rotationalVelocity = AngularVelocity;;
4598
4094 try 4599 try
4095 { 4600 {
4096 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4601 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4097 string.Format("{0}/{1}", Name, UUID), 4602 string.Format("{0}/{1}", Name, UUID),
4098 Shape, 4603 Shape,
4099 AbsolutePosition, 4604 AbsolutePosition,
4100 Scale, 4605 Scale,
4101 RotationOffset, 4606 GetWorldRotation(),
4102 rigidBody, 4607 isPhysical,
4103 m_localId); 4608 isPhantom,
4609 PhysicsShapeType,
4610 m_localId);
4104 } 4611 }
4105 catch 4612 catch (Exception ex)
4106 { 4613 {
4107 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4614 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4108 pa = null; 4615 pa = null;
4109 } 4616 }
4110 4617
4111 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4112 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4113 // being set.
4114 PhysActor = pa;
4115
4116 // Basic Physics can also return null as well as an exception catch.
4117 if (pa != null) 4618 if (pa != null)
4118 { 4619 {
4119 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4620 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4120 pa.SetMaterial(Material); 4621 pa.SetMaterial(Material);
4121 DoPhysicsPropertyUpdate(rigidBody, true); 4622
4623 if (VolumeDetectActive) // change if not the default only
4624 pa.SetVolumeDetect(1);
4625
4626 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4627 m_vehicle.SetVehicle(pa);
4628
4629 // we are going to tell rest of code about physics so better have this here
4630 PhysActor = pa;
4631
4632 // DoPhysicsPropertyUpdate(isPhysical, true);
4633 // lets expand it here just with what it really needs to do
4634
4635 if (isPhysical)
4636 {
4637 if (ParentGroup.RootPart.KeyframeMotion != null)
4638 ParentGroup.RootPart.KeyframeMotion.Stop();
4639 ParentGroup.RootPart.KeyframeMotion = null;
4640 ParentGroup.Scene.AddPhysicalPrim(1);
4641
4642 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4643 pa.OnOutOfBounds += PhysicsOutOfBounds;
4644
4645 if (ParentID != 0 && ParentID != LocalId)
4646 {
4647 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4648
4649 if (parentPa != null)
4650 {
4651 pa.link(parentPa);
4652 }
4653 }
4654 }
4655
4656 if (applyDynamics)
4657 // do independent of isphysical so parameters get setted (at least some)
4658 {
4659 Velocity = velocity;
4660 AngularVelocity = rotationalVelocity;
4661// pa.Velocity = velocity;
4662 pa.RotationalVelocity = rotationalVelocity;
4663
4664 // if not vehicle and root part apply force and torque
4665 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
4666 && LocalId == ParentGroup.RootPart.LocalId)
4667 {
4668 pa.Force = Force;
4669 pa.Torque = Torque;
4670 }
4671 }
4672
4673 if (Shape.SculptEntry)
4674 CheckSculptAndLoad();
4675 else
4676 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4677
4678 if (!building)
4679 pa.Building = false;
4122 } 4680 }
4123 4681
4124 return pa; 4682 PhysActor = pa;
4125 } 4683 }
4126 4684
4127 /// <summary> 4685 /// <summary>
4128 /// This removes the part from the physics scene. 4686 /// This removes the part from the physics scene.
4129 /// </summary> 4687 /// </summary>
4130 /// <remarks> 4688 /// <remarks>
4131 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4689 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4132 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4690 /// representation for collision detection.
4133 /// phantom.
4134 /// </remarks> 4691 /// </remarks>
4135 public void RemoveFromPhysics() 4692 public void RemoveFromPhysics()
4136 { 4693 {
4137 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4694 PhysicsActor pa = PhysActor;
4695 if (pa != null)
4696 {
4697 pa.OnCollisionUpdate -= PhysicsCollision;
4698 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4699 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4700
4701 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4702 }
4138 PhysActor = null; 4703 PhysActor = null;
4139 } 4704 }
4140 4705
@@ -4294,6 +4859,44 @@ namespace OpenSim.Region.Framework.Scenes
4294 ScheduleFullUpdate(); 4859 ScheduleFullUpdate();
4295 } 4860 }
4296 4861
4862
4863 private void UpdatePhysicsSubscribedEvents()
4864 {
4865 PhysicsActor pa = PhysActor;
4866 if (pa == null)
4867 return;
4868
4869 pa.OnCollisionUpdate -= PhysicsCollision;
4870
4871 bool hassound = (CollisionSoundType >= 0 && !VolumeDetectActive);
4872
4873 scriptEvents CombinedEvents = AggregateScriptEvents;
4874
4875 // merge with root part
4876 if (ParentGroup != null && ParentGroup.RootPart != null)
4877 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4878
4879 // submit to this part case
4880 if (VolumeDetectActive)
4881 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4882 else if ((Flags & PrimFlags.Phantom) != 0)
4883 CombinedEvents &= PhyscicsPhantonSubsEvents;
4884 else
4885 CombinedEvents &= PhysicsNeededSubsEvents;
4886
4887 if (hassound || CombinedEvents != 0)
4888 {
4889 // subscribe to physics updates.
4890 pa.OnCollisionUpdate += PhysicsCollision;
4891 pa.SubscribeEvents(50); // 20 reports per second
4892 }
4893 else
4894 {
4895 pa.UnSubscribeEvents();
4896 }
4897 }
4898
4899
4297 public void aggregateScriptEvents() 4900 public void aggregateScriptEvents()
4298 { 4901 {
4299 if (ParentGroup == null || ParentGroup.RootPart == null) 4902 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4330,40 +4933,32 @@ namespace OpenSim.Region.Framework.Scenes
4330 { 4933 {
4331 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4934 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4332 } 4935 }
4333 4936/*
4334 PhysicsActor pa = PhysActor; 4937 PhysicsActor pa = PhysActor;
4335 4938 if (pa != null)
4336 if (
4337 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4338 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4339 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4340 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4343 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4344 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4345 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4349 (CollisionSound != UUID.Zero)
4350 )
4351 { 4939 {
4352 // subscribe to physics updates. 4940 if (
4353 if (pa != null) 4941// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4942// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4943// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4944// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4945// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4946// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4947 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
4948 )
4354 { 4949 {
4950 // subscribe to physics updates.
4355 pa.OnCollisionUpdate += PhysicsCollision; 4951 pa.OnCollisionUpdate += PhysicsCollision;
4356 pa.SubscribeEvents(1000); 4952 pa.SubscribeEvents(1000);
4357 } 4953 }
4358 } 4954 else
4359 else
4360 {
4361 if (pa != null)
4362 { 4955 {
4363 pa.UnSubscribeEvents(); 4956 pa.UnSubscribeEvents();
4364 pa.OnCollisionUpdate -= PhysicsCollision; 4957 pa.OnCollisionUpdate -= PhysicsCollision;
4365 } 4958 }
4366 } 4959 }
4960 */
4961 UpdatePhysicsSubscribedEvents();
4367 4962
4368 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 4963 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4369 //{ 4964 //{
@@ -4491,5 +5086,17 @@ namespace OpenSim.Region.Framework.Scenes
4491 Color color = Color; 5086 Color color = Color;
4492 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5087 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4493 } 5088 }
5089
5090 public void ResetOwnerChangeFlag()
5091 {
5092 List<UUID> inv = Inventory.GetInventoryList();
5093
5094 foreach (UUID itemID in inv)
5095 {
5096 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5097 item.OwnerChanged = false;
5098 Inventory.UpdateInventoryItem(item, false, false);
5099 }
5100 }
4494 } 5101 }
4495} 5102}