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 3d81358..f1e781c 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>
@@ -2598,8 +3150,8 @@ namespace OpenSim.Region.Framework.Scenes
2598 { 3150 {
2599 const float ROTATION_TOLERANCE = 0.01f; 3151 const float ROTATION_TOLERANCE = 0.01f;
2600 const float VELOCITY_TOLERANCE = 0.001f; 3152 const float VELOCITY_TOLERANCE = 0.001f;
2601 const float POSITION_TOLERANCE = 0.05f; 3153 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2602 const int TIME_MS_TOLERANCE = 3000; 3154 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2603 3155
2604 switch (UpdateFlag) 3156 switch (UpdateFlag)
2605 { 3157 {
@@ -2661,17 +3213,16 @@ namespace OpenSim.Region.Framework.Scenes
2661 if (!UUID.TryParse(sound, out soundID)) 3213 if (!UUID.TryParse(sound, out soundID))
2662 { 3214 {
2663 // search sound file from inventory 3215 // search sound file from inventory
2664 lock (TaskInventory) 3216 TaskInventory.LockItemsForRead(true);
3217 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2665 { 3218 {
2666 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3219 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2667 { 3220 {
2668 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3221 soundID = item.Value.ItemID;
2669 { 3222 break;
2670 soundID = item.Value.ItemID;
2671 break;
2672 }
2673 } 3223 }
2674 } 3224 }
3225 TaskInventory.LockItemsForRead(false);
2675 } 3226 }
2676 3227
2677 if (soundID == UUID.Zero) 3228 if (soundID == UUID.Zero)
@@ -2728,6 +3279,35 @@ namespace OpenSim.Region.Framework.Scenes
2728 } 3279 }
2729 } 3280 }
2730 3281
3282 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3283 {
3284 if (soundID == UUID.Zero)
3285 return;
3286
3287 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3288 if (soundModule == null)
3289 return;
3290
3291 if (volume > 1)
3292 volume = 1;
3293 if (volume < 0)
3294 volume = 0;
3295
3296 int now = Util.EnvironmentTickCount();
3297 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3298 return;
3299
3300 LastColSoundSentTime = now;
3301
3302 UUID ownerID = OwnerID;
3303 UUID objectID = ParentGroup.RootPart.UUID;
3304 UUID parentID = ParentGroup.UUID;
3305 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3306
3307 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3308 }
3309
3310
2731 /// <summary> 3311 /// <summary>
2732 /// Send a terse update to all clients 3312 /// Send a terse update to all clients
2733 /// </summary> 3313 /// </summary>
@@ -2756,10 +3336,13 @@ namespace OpenSim.Region.Framework.Scenes
2756 3336
2757 public void SetBuoyancy(float fvalue) 3337 public void SetBuoyancy(float fvalue)
2758 { 3338 {
2759 PhysicsActor pa = PhysActor; 3339 Buoyancy = fvalue;
2760 3340/*
2761 if (pa != null) 3341 if (PhysActor != null)
2762 pa.Buoyancy = fvalue; 3342 {
3343 PhysActor.Buoyancy = fvalue;
3344 }
3345 */
2763 } 3346 }
2764 3347
2765 public void SetDieAtEdge(bool p) 3348 public void SetDieAtEdge(bool p)
@@ -2775,47 +3358,111 @@ namespace OpenSim.Region.Framework.Scenes
2775 PhysicsActor pa = PhysActor; 3358 PhysicsActor pa = PhysActor;
2776 3359
2777 if (pa != null) 3360 if (pa != null)
2778 pa.FloatOnWater = floatYN == 1; 3361 pa.FloatOnWater = (floatYN == 1);
2779 } 3362 }
2780 3363
2781 public void SetForce(Vector3 force) 3364 public void SetForce(Vector3 force)
2782 { 3365 {
2783 PhysicsActor pa = PhysActor; 3366 Force = force;
3367 }
2784 3368
2785 if (pa != null) 3369 public SOPVehicle sopVehicle
2786 pa.Force = force; 3370 {
3371 get
3372 {
3373 return m_vehicle;
3374 }
3375 set
3376 {
3377 m_vehicle = value;
3378 }
3379 }
3380
3381
3382 public int VehicleType
3383 {
3384 get
3385 {
3386 if (m_vehicle == null)
3387 return (int)Vehicle.TYPE_NONE;
3388 else
3389 return (int)m_vehicle.Type;
3390 }
3391 set
3392 {
3393 SetVehicleType(value);
3394 }
2787 } 3395 }
2788 3396
2789 public void SetVehicleType(int type) 3397 public void SetVehicleType(int type)
2790 { 3398 {
2791 PhysicsActor pa = PhysActor; 3399 m_vehicle = null;
3400
3401 if (type == (int)Vehicle.TYPE_NONE)
3402 {
3403 if (_parentID ==0 && PhysActor != null)
3404 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3405 return;
3406 }
3407 m_vehicle = new SOPVehicle();
3408 m_vehicle.ProcessTypeChange((Vehicle)type);
3409 {
3410 if (_parentID ==0 && PhysActor != null)
3411 PhysActor.VehicleType = type;
3412 return;
3413 }
3414 }
2792 3415
2793 if (pa != null) 3416 public void SetVehicleFlags(int param, bool remove)
2794 pa.VehicleType = type; 3417 {
3418 if (m_vehicle == null)
3419 return;
3420
3421 m_vehicle.ProcessVehicleFlags(param, remove);
3422
3423 if (_parentID ==0 && PhysActor != null)
3424 {
3425 PhysActor.VehicleFlags(param, remove);
3426 }
2795 } 3427 }
2796 3428
2797 public void SetVehicleFloatParam(int param, float value) 3429 public void SetVehicleFloatParam(int param, float value)
2798 { 3430 {
2799 PhysicsActor pa = PhysActor; 3431 if (m_vehicle == null)
3432 return;
2800 3433
2801 if (pa != null) 3434 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
2802 pa.VehicleFloatParam(param, value); 3435
3436 if (_parentID == 0 && PhysActor != null)
3437 {
3438 PhysActor.VehicleFloatParam(param, value);
3439 }
2803 } 3440 }
2804 3441
2805 public void SetVehicleVectorParam(int param, Vector3 value) 3442 public void SetVehicleVectorParam(int param, Vector3 value)
2806 { 3443 {
2807 PhysicsActor pa = PhysActor; 3444 if (m_vehicle == null)
3445 return;
2808 3446
2809 if (pa != null) 3447 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
2810 pa.VehicleVectorParam(param, value); 3448
3449 if (_parentID == 0 && PhysActor != null)
3450 {
3451 PhysActor.VehicleVectorParam(param, value);
3452 }
2811 } 3453 }
2812 3454
2813 public void SetVehicleRotationParam(int param, Quaternion rotation) 3455 public void SetVehicleRotationParam(int param, Quaternion rotation)
2814 { 3456 {
2815 PhysicsActor pa = PhysActor; 3457 if (m_vehicle == null)
3458 return;
2816 3459
2817 if (pa != null) 3460 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
2818 pa.VehicleRotationParam(param, rotation); 3461
3462 if (_parentID == 0 && PhysActor != null)
3463 {
3464 PhysActor.VehicleRotationParam(param, rotation);
3465 }
2819 } 3466 }
2820 3467
2821 /// <summary> 3468 /// <summary>
@@ -2999,14 +3646,6 @@ namespace OpenSim.Region.Framework.Scenes
2999 hasProfileCut = hasDimple; // is it the same thing? 3646 hasProfileCut = hasDimple; // is it the same thing?
3000 } 3647 }
3001 3648
3002 public void SetVehicleFlags(int param, bool remove)
3003 {
3004 PhysicsActor pa = PhysActor;
3005
3006 if (pa != null)
3007 pa.VehicleFlags(param, remove);
3008 }
3009
3010 public void SetGroup(UUID groupID, IClientAPI client) 3649 public void SetGroup(UUID groupID, IClientAPI client)
3011 { 3650 {
3012 // Scene.AddNewPrims() calls with client == null so can't use this. 3651 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3110,68 +3749,18 @@ namespace OpenSim.Region.Framework.Scenes
3110 //ParentGroup.ScheduleGroupForFullUpdate(); 3749 //ParentGroup.ScheduleGroupForFullUpdate();
3111 } 3750 }
3112 3751
3113 public void StoreUndoState() 3752 public void StoreUndoState(ObjectChangeType change)
3114 { 3753 {
3115 StoreUndoState(false); 3754 if (m_UndoRedo == null)
3116 } 3755 m_UndoRedo = new UndoRedoState(5);
3117 3756
3118 public void StoreUndoState(bool forGroup) 3757 lock (m_UndoRedo)
3119 {
3120 if (!Undoing)
3121 { 3758 {
3122 if (!IgnoreUndoUpdate) 3759 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3123 { 3760 {
3124 if (ParentGroup != null) 3761 m_UndoRedo.StoreUndo(this, change);
3125 {
3126 lock (m_undo)
3127 {
3128 if (m_undo.Count > 0)
3129 {
3130 UndoState last = m_undo.Peek();
3131 if (last != null)
3132 {
3133 // TODO: May need to fix for group comparison
3134 if (last.Compare(this))
3135 {
3136 // m_log.DebugFormat(
3137 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3138 // Name, LocalId, m_undo.Count);
3139
3140 return;
3141 }
3142 }
3143 }
3144
3145 // m_log.DebugFormat(
3146 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3147 // Name, LocalId, forGroup, m_undo.Count);
3148
3149 if (ParentGroup.GetSceneMaxUndo() > 0)
3150 {
3151 UndoState nUndo = new UndoState(this, forGroup);
3152
3153 m_undo.Push(nUndo);
3154
3155 if (m_redo.Count > 0)
3156 m_redo.Clear();
3157
3158 // m_log.DebugFormat(
3159 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3160 // Name, LocalId, forGroup, m_undo.Count);
3161 }
3162 }
3163 }
3164 } 3762 }
3165// else
3166// {
3167// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3168// }
3169 } 3763 }
3170// else
3171// {
3172// m_log.DebugFormat(
3173// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3174// }
3175 } 3764 }
3176 3765
3177 /// <summary> 3766 /// <summary>
@@ -3181,84 +3770,46 @@ namespace OpenSim.Region.Framework.Scenes
3181 { 3770 {
3182 get 3771 get
3183 { 3772 {
3184 lock (m_undo) 3773 if (m_UndoRedo == null)
3185 return m_undo.Count; 3774 return 0;
3775 return m_UndoRedo.Count;
3186 } 3776 }
3187 } 3777 }
3188 3778
3189 public void Undo() 3779 public void Undo()
3190 { 3780 {
3191 lock (m_undo) 3781 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3192 { 3782 return;
3193// m_log.DebugFormat(
3194// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3195// Name, LocalId, m_undo.Count);
3196
3197 if (m_undo.Count > 0)
3198 {
3199 UndoState goback = m_undo.Pop();
3200
3201 if (goback != null)
3202 {
3203 UndoState nUndo = null;
3204
3205 if (ParentGroup.GetSceneMaxUndo() > 0)
3206 {
3207 nUndo = new UndoState(this, goback.ForGroup);
3208 }
3209
3210 goback.PlaybackState(this);
3211
3212 if (nUndo != null)
3213 m_redo.Push(nUndo);
3214 }
3215 }
3216 3783
3217// m_log.DebugFormat( 3784 lock (m_UndoRedo)
3218// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3785 {
3219// Name, LocalId, m_undo.Count); 3786 Undoing = true;
3787 m_UndoRedo.Undo(this);
3788 Undoing = false;
3220 } 3789 }
3221 } 3790 }
3222 3791
3223 public void Redo() 3792 public void Redo()
3224 { 3793 {
3225 lock (m_undo) 3794 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3226 { 3795 return;
3227// m_log.DebugFormat(
3228// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3229// Name, LocalId, m_redo.Count);
3230
3231 if (m_redo.Count > 0)
3232 {
3233 UndoState gofwd = m_redo.Pop();
3234
3235 if (gofwd != null)
3236 {
3237 if (ParentGroup.GetSceneMaxUndo() > 0)
3238 {
3239 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3240
3241 m_undo.Push(nUndo);
3242 }
3243
3244 gofwd.PlayfwdState(this);
3245 }
3246 3796
3247// m_log.DebugFormat( 3797 lock (m_UndoRedo)
3248// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3798 {
3249// Name, LocalId, m_redo.Count); 3799 Undoing = true;
3250 } 3800 m_UndoRedo.Redo(this);
3801 Undoing = false;
3251 } 3802 }
3252 } 3803 }
3253 3804
3254 public void ClearUndoState() 3805 public void ClearUndoState()
3255 { 3806 {
3256// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3807 if (m_UndoRedo == null || Undoing)
3808 return;
3257 3809
3258 lock (m_undo) 3810 lock (m_UndoRedo)
3259 { 3811 {
3260 m_undo.Clear(); 3812 m_UndoRedo.Clear();
3261 m_redo.Clear();
3262 } 3813 }
3263 } 3814 }
3264 3815
@@ -3888,6 +4439,27 @@ namespace OpenSim.Region.Framework.Scenes
3888 } 4439 }
3889 } 4440 }
3890 4441
4442
4443 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4444 {
4445 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4446 return;
4447
4448 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4449 {
4450 PhysicsShapeType = (byte)physdata.PhysShapeType;
4451
4452 }
4453
4454 if(Density != physdata.Density)
4455 Density = physdata.Density;
4456 if(GravityModifier != physdata.GravitationModifier)
4457 GravityModifier = physdata.GravitationModifier;
4458 if(Friction != physdata.Friction)
4459 Friction = physdata.Friction;
4460 if(Bounciness != physdata.Bounce)
4461 Bounciness = physdata.Bounce;
4462 }
3891 /// <summary> 4463 /// <summary>
3892 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4464 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3893 /// </summary> 4465 /// </summary>
@@ -3895,7 +4467,7 @@ namespace OpenSim.Region.Framework.Scenes
3895 /// <param name="SetTemporary"></param> 4467 /// <param name="SetTemporary"></param>
3896 /// <param name="SetPhantom"></param> 4468 /// <param name="SetPhantom"></param>
3897 /// <param name="SetVD"></param> 4469 /// <param name="SetVD"></param>
3898 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4470 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3899 { 4471 {
3900 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4472 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3901 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4473 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3905,237 +4477,230 @@ namespace OpenSim.Region.Framework.Scenes
3905 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4477 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3906 return; 4478 return;
3907 4479
3908 PhysicsActor pa = PhysActor; 4480 VolumeDetectActive = SetVD;
3909
3910 // Special cases for VD. VD can only be called from a script
3911 // and can't be combined with changes to other states. So we can rely
3912 // that...
3913 // ... if VD is changed, all others are not.
3914 // ... if one of the others is changed, VD is not.
3915 if (SetVD) // VD is active, special logic applies
3916 {
3917 // State machine logic for VolumeDetect
3918 // More logic below
3919 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3920
3921 if (phanReset) // Phantom changes from on to off switch VD off too
3922 {
3923 SetVD = false; // Switch it of for the course of this routine
3924 VolumeDetectActive = false; // and also permanently
3925
3926 if (pa != null)
3927 pa.SetVolumeDetect(0); // Let physics know about it too
3928 }
3929 else
3930 {
3931 // If volumedetect is active we don't want phantom to be applied.
3932 // If this is a new call to VD out of the state "phantom"
3933 // this will also cause the prim to be visible to physics
3934 SetPhantom = false;
3935 }
3936 }
3937 4481
3938 if (UsePhysics && IsJoint()) 4482 // volume detector implies phantom
3939 { 4483 if (VolumeDetectActive)
3940 SetPhantom = true; 4484 SetPhantom = true;
3941 }
3942 4485
3943 if (UsePhysics) 4486 if (UsePhysics)
3944 {
3945 AddFlag(PrimFlags.Physics); 4487 AddFlag(PrimFlags.Physics);
3946 if (!wasUsingPhysics)
3947 {
3948 DoPhysicsPropertyUpdate(UsePhysics, false);
3949
3950 if (!ParentGroup.IsDeleted)
3951 {
3952 if (LocalId == ParentGroup.RootPart.LocalId)
3953 {
3954 ParentGroup.CheckSculptAndLoad();
3955 }
3956 }
3957 }
3958 }
3959 else 4488 else
3960 {
3961 RemFlag(PrimFlags.Physics); 4489 RemFlag(PrimFlags.Physics);
3962 if (wasUsingPhysics)
3963 {
3964 DoPhysicsPropertyUpdate(UsePhysics, false);
3965 }
3966 }
3967 4490
3968 if (SetPhantom 4491 if (SetPhantom)
3969 || ParentGroup.IsAttachment
3970 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3971 {
3972 AddFlag(PrimFlags.Phantom); 4492 AddFlag(PrimFlags.Phantom);
3973 4493 else
3974 if (PhysActor != null)
3975 {
3976 RemoveFromPhysics();
3977 pa = null;
3978 }
3979 }
3980 else // Not phantom
3981 {
3982 RemFlag(PrimFlags.Phantom); 4494 RemFlag(PrimFlags.Phantom);
3983 4495
3984 if (ParentGroup.Scene == null) 4496 if (SetTemporary)
3985 return; 4497 AddFlag(PrimFlags.TemporaryOnRez);
4498 else
4499 RemFlag(PrimFlags.TemporaryOnRez);
3986 4500
3987 if (ParentGroup.Scene.CollidablePrims && pa == null)
3988 {
3989 pa = AddToPhysics(UsePhysics);
3990 4501
3991 if (pa != null) 4502 if (ParentGroup.Scene == null)
3992 { 4503 return;
3993 pa.SetMaterial(Material);
3994 DoPhysicsPropertyUpdate(UsePhysics, true);
3995
3996 if (!ParentGroup.IsDeleted)
3997 {
3998 if (LocalId == ParentGroup.RootPart.LocalId)
3999 {
4000 ParentGroup.CheckSculptAndLoad();
4001 }
4002 }
4003
4004 if (
4005 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4006 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4007 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4008 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4009 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4010 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4011 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4012 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4013 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4014 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4015 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4016 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4017 (CollisionSound != UUID.Zero)
4018 )
4019 {
4020 pa.OnCollisionUpdate += PhysicsCollision;
4021 pa.SubscribeEvents(1000);
4022 }
4023 }
4024 }
4025 else // it already has a physical representation
4026 {
4027 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4028 4504
4029 if (!ParentGroup.IsDeleted) 4505 PhysicsActor pa = PhysActor;
4030 {
4031 if (LocalId == ParentGroup.RootPart.LocalId)
4032 {
4033 ParentGroup.CheckSculptAndLoad();
4034 }
4035 }
4036 }
4037 }
4038 4506
4039 if (SetVD) 4507 if (pa != null && building && pa.Building != building)
4508 pa.Building = building;
4509
4510 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4511 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4040 { 4512 {
4041 // If the above logic worked (this is urgent candidate to unit tests!)
4042 // we now have a physicsactor.
4043 // Defensive programming calls for a check here.
4044 // Better would be throwing an exception that could be catched by a unit test as the internal
4045 // logic should make sure, this Physactor is always here.
4046 if (pa != null) 4513 if (pa != null)
4047 { 4514 {
4048 pa.SetVolumeDetect(1); 4515 ParentGroup.Scene.RemovePhysicalPrim(1);
4049 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4516 RemoveFromPhysics();
4050 VolumeDetectActive = true;
4051 } 4517 }
4518
4519 Velocity = new Vector3(0, 0, 0);
4520 Acceleration = new Vector3(0, 0, 0);
4521 if (ParentGroup.RootPart == this)
4522 AngularVelocity = new Vector3(0, 0, 0);
4052 } 4523 }
4053 else 4524 else
4054 { 4525 {
4055 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4526 if (ParentGroup.Scene.CollidablePrims)
4056 // (mumbles, well, at least if you have infinte CPU powers :-)) 4527 {
4057 if (pa != null) 4528 if (pa == null)
4058 pa.SetVolumeDetect(0); 4529 {
4530 AddToPhysics(UsePhysics, SetPhantom, building, false);
4531 pa = PhysActor;
4532 /*
4533 if (pa != null)
4534 {
4535 if (
4536 // ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4537 // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4538 // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4539 // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4540 // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4541 // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4542 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4543 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4544 (CollisionSound != UUID.Zero)
4545 )
4546 {
4547 pa.OnCollisionUpdate += PhysicsCollision;
4548 pa.SubscribeEvents(1000);
4549 }
4550 }
4551 */
4552 }
4553 else // it already has a physical representation
4554 {
4555 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4556 /* moved into DoPhysicsPropertyUpdate
4557 if(VolumeDetectActive)
4558 pa.SetVolumeDetect(1);
4559 else
4560 pa.SetVolumeDetect(0);
4561 */
4059 4562
4060 VolumeDetectActive = false;
4061 }
4062 4563
4063 if (SetTemporary) 4564 if (pa.Building != building)
4064 { 4565 pa.Building = building;
4065 AddFlag(PrimFlags.TemporaryOnRez); 4566 }
4066 } 4567
4067 else 4568 UpdatePhysicsSubscribedEvents();
4068 { 4569 }
4069 RemFlag(PrimFlags.TemporaryOnRez); 4570 }
4070 }
4071 4571
4072 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4572 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4073 4573
4574 // and last in case we have a new actor and not building
4575
4074 if (ParentGroup != null) 4576 if (ParentGroup != null)
4075 { 4577 {
4076 ParentGroup.HasGroupChanged = true; 4578 ParentGroup.HasGroupChanged = true;
4077 ScheduleFullUpdate(); 4579 ScheduleFullUpdate();
4078 } 4580 }
4079 4581
4080// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4582// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4081 } 4583 }
4082 4584
4083 /// <summary> 4585 /// <summary>
4084 /// Adds this part to the physics scene. 4586 /// Adds this part to the physics scene.
4587 /// and sets the PhysActor property
4085 /// </summary> 4588 /// </summary>
4086 /// <remarks>This method also sets the PhysActor property.</remarks> 4589 /// <param name="isPhysical">Add this prim as physical.</param>
4087 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4590 /// <param name="isPhantom">Add this prim as phantom.</param>
4088 /// <returns> 4591 /// <param name="building">tells physics to delay full construction of object</param>
4089 /// The physics actor. null if there was a failure. 4592 /// <param name="applyDynamics">applies velocities, force and torque</param>
4090 /// </returns> 4593 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4091 private PhysicsActor AddToPhysics(bool rigidBody) 4594 {
4092 {
4093 PhysicsActor pa; 4595 PhysicsActor pa;
4094 4596
4597 Vector3 velocity = Velocity;
4598 Vector3 rotationalVelocity = AngularVelocity;;
4599
4095 try 4600 try
4096 { 4601 {
4097 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4602 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4098 string.Format("{0}/{1}", Name, UUID), 4603 string.Format("{0}/{1}", Name, UUID),
4099 Shape, 4604 Shape,
4100 AbsolutePosition, 4605 AbsolutePosition,
4101 Scale, 4606 Scale,
4102 RotationOffset, 4607 GetWorldRotation(),
4103 rigidBody, 4608 isPhysical,
4104 m_localId); 4609 isPhantom,
4610 PhysicsShapeType,
4611 m_localId);
4105 } 4612 }
4106 catch 4613 catch (Exception ex)
4107 { 4614 {
4108 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4615 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4109 pa = null; 4616 pa = null;
4110 } 4617 }
4111 4618
4112 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4113 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4114 // being set.
4115 PhysActor = pa;
4116
4117 // Basic Physics can also return null as well as an exception catch.
4118 if (pa != null) 4619 if (pa != null)
4119 { 4620 {
4120 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4621 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4121 pa.SetMaterial(Material); 4622 pa.SetMaterial(Material);
4122 DoPhysicsPropertyUpdate(rigidBody, true); 4623
4624 if (VolumeDetectActive) // change if not the default only
4625 pa.SetVolumeDetect(1);
4626
4627 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4628 m_vehicle.SetVehicle(pa);
4629
4630 // we are going to tell rest of code about physics so better have this here
4631 PhysActor = pa;
4632
4633 // DoPhysicsPropertyUpdate(isPhysical, true);
4634 // lets expand it here just with what it really needs to do
4635
4636 if (isPhysical)
4637 {
4638 if (ParentGroup.RootPart.KeyframeMotion != null)
4639 ParentGroup.RootPart.KeyframeMotion.Stop();
4640 ParentGroup.RootPart.KeyframeMotion = null;
4641 ParentGroup.Scene.AddPhysicalPrim(1);
4642
4643 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4644 pa.OnOutOfBounds += PhysicsOutOfBounds;
4645
4646 if (ParentID != 0 && ParentID != LocalId)
4647 {
4648 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4649
4650 if (parentPa != null)
4651 {
4652 pa.link(parentPa);
4653 }
4654 }
4655 }
4656
4657 if (applyDynamics)
4658 // do independent of isphysical so parameters get setted (at least some)
4659 {
4660 Velocity = velocity;
4661 AngularVelocity = rotationalVelocity;
4662// pa.Velocity = velocity;
4663 pa.RotationalVelocity = rotationalVelocity;
4664
4665 // if not vehicle and root part apply force and torque
4666 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
4667 && LocalId == ParentGroup.RootPart.LocalId)
4668 {
4669 pa.Force = Force;
4670 pa.Torque = Torque;
4671 }
4672 }
4673
4674 if (Shape.SculptEntry)
4675 CheckSculptAndLoad();
4676 else
4677 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4678
4679 if (!building)
4680 pa.Building = false;
4123 } 4681 }
4124 4682
4125 return pa; 4683 PhysActor = pa;
4126 } 4684 }
4127 4685
4128 /// <summary> 4686 /// <summary>
4129 /// This removes the part from the physics scene. 4687 /// This removes the part from the physics scene.
4130 /// </summary> 4688 /// </summary>
4131 /// <remarks> 4689 /// <remarks>
4132 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4690 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4133 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4691 /// representation for collision detection.
4134 /// phantom.
4135 /// </remarks> 4692 /// </remarks>
4136 public void RemoveFromPhysics() 4693 public void RemoveFromPhysics()
4137 { 4694 {
4138 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4695 PhysicsActor pa = PhysActor;
4696 if (pa != null)
4697 {
4698 pa.OnCollisionUpdate -= PhysicsCollision;
4699 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4700 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4701
4702 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4703 }
4139 PhysActor = null; 4704 PhysActor = null;
4140 } 4705 }
4141 4706
@@ -4295,6 +4860,44 @@ namespace OpenSim.Region.Framework.Scenes
4295 ScheduleFullUpdate(); 4860 ScheduleFullUpdate();
4296 } 4861 }
4297 4862
4863
4864 private void UpdatePhysicsSubscribedEvents()
4865 {
4866 PhysicsActor pa = PhysActor;
4867 if (pa == null)
4868 return;
4869
4870 pa.OnCollisionUpdate -= PhysicsCollision;
4871
4872 bool hassound = (CollisionSoundType >= 0 && !VolumeDetectActive);
4873
4874 scriptEvents CombinedEvents = AggregateScriptEvents;
4875
4876 // merge with root part
4877 if (ParentGroup != null && ParentGroup.RootPart != null)
4878 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4879
4880 // submit to this part case
4881 if (VolumeDetectActive)
4882 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4883 else if ((Flags & PrimFlags.Phantom) != 0)
4884 CombinedEvents &= PhyscicsPhantonSubsEvents;
4885 else
4886 CombinedEvents &= PhysicsNeededSubsEvents;
4887
4888 if (hassound || CombinedEvents != 0)
4889 {
4890 // subscribe to physics updates.
4891 pa.OnCollisionUpdate += PhysicsCollision;
4892 pa.SubscribeEvents(50); // 20 reports per second
4893 }
4894 else
4895 {
4896 pa.UnSubscribeEvents();
4897 }
4898 }
4899
4900
4298 public void aggregateScriptEvents() 4901 public void aggregateScriptEvents()
4299 { 4902 {
4300 if (ParentGroup == null || ParentGroup.RootPart == null) 4903 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4331,40 +4934,32 @@ namespace OpenSim.Region.Framework.Scenes
4331 { 4934 {
4332 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4935 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4333 } 4936 }
4334 4937/*
4335 PhysicsActor pa = PhysActor; 4938 PhysicsActor pa = PhysActor;
4336 4939 if (pa != null)
4337 if (
4338 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4339 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4340 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4344 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4345 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4350 (CollisionSound != UUID.Zero)
4351 )
4352 { 4940 {
4353 // subscribe to physics updates. 4941 if (
4354 if (pa != null) 4942// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4943// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4944// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4945// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4946// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4947// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4948 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
4949 )
4355 { 4950 {
4951 // subscribe to physics updates.
4356 pa.OnCollisionUpdate += PhysicsCollision; 4952 pa.OnCollisionUpdate += PhysicsCollision;
4357 pa.SubscribeEvents(1000); 4953 pa.SubscribeEvents(1000);
4358 } 4954 }
4359 } 4955 else
4360 else
4361 {
4362 if (pa != null)
4363 { 4956 {
4364 pa.UnSubscribeEvents(); 4957 pa.UnSubscribeEvents();
4365 pa.OnCollisionUpdate -= PhysicsCollision; 4958 pa.OnCollisionUpdate -= PhysicsCollision;
4366 } 4959 }
4367 } 4960 }
4961 */
4962 UpdatePhysicsSubscribedEvents();
4368 4963
4369 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 4964 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4370 //{ 4965 //{
@@ -4493,5 +5088,17 @@ namespace OpenSim.Region.Framework.Scenes
4493 Color color = Color; 5088 Color color = Color;
4494 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5089 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4495 } 5090 }
5091
5092 public void ResetOwnerChangeFlag()
5093 {
5094 List<UUID> inv = Inventory.GetInventoryList();
5095
5096 foreach (UUID itemID in inv)
5097 {
5098 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5099 item.OwnerChanged = false;
5100 Inventory.UpdateInventoryItem(item, false, false);
5101 }
5102 }
4496 } 5103 }
4497} 5104}