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.cs1506
1 files changed, 1002 insertions, 504 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index dc76d22..a1f434e 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>
@@ -182,6 +194,18 @@ namespace OpenSim.Region.Framework.Scenes
182 194
183 public uint TimeStampTerse; 195 public uint TimeStampTerse;
184 196
197 // The following two are to hold the attachment data
198 // while an object is inworld
199 [XmlIgnore]
200 public byte AttachPoint = 0;
201
202 [XmlIgnore]
203 public Vector3 AttachOffset = Vector3.Zero;
204
205 [XmlIgnore]
206 public Quaternion AttachRotation = Quaternion.Identity;
207
208 [XmlIgnore]
185 public int STATUS_ROTATE_X; 209 public int STATUS_ROTATE_X;
186 210
187 public int STATUS_ROTATE_Y; 211 public int STATUS_ROTATE_Y;
@@ -208,8 +232,7 @@ namespace OpenSim.Region.Framework.Scenes
208 232
209 public Vector3 RotationAxis = Vector3.One; 233 public Vector3 RotationAxis = Vector3.One;
210 234
211 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 235 public bool VolumeDetectActive;
212 // Certainly this must be a persistant setting finally
213 236
214 public bool IsWaitingForFirstSpinUpdatePacket; 237 public bool IsWaitingForFirstSpinUpdatePacket;
215 238
@@ -249,10 +272,10 @@ namespace OpenSim.Region.Framework.Scenes
249 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 272 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
250 private Vector3 m_sitTargetPosition; 273 private Vector3 m_sitTargetPosition;
251 private string m_sitAnimation = "SIT"; 274 private string m_sitAnimation = "SIT";
275 private bool m_occupied; // KF if any av is sitting on this prim
252 private string m_text = String.Empty; 276 private string m_text = String.Empty;
253 private string m_touchName = String.Empty; 277 private string m_touchName = String.Empty;
254 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 278 private UndoRedoState m_UndoRedo = null;
255 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
256 279
257 private bool m_passTouches = false; 280 private bool m_passTouches = false;
258 private bool m_passCollisions = false; 281 private bool m_passCollisions = false;
@@ -281,7 +304,19 @@ namespace OpenSim.Region.Framework.Scenes
281 protected Vector3 m_lastAcceleration; 304 protected Vector3 m_lastAcceleration;
282 protected Vector3 m_lastAngularVelocity; 305 protected Vector3 m_lastAngularVelocity;
283 protected int m_lastTerseSent; 306 protected int m_lastTerseSent;
284 307 protected float m_buoyancy = 0.0f;
308 protected Vector3 m_force;
309 protected Vector3 m_torque;
310
311 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
312 protected float m_density = 1000.0f; // in kg/m^3
313 protected float m_gravitymod = 1.0f;
314 protected float m_friction = 0.6f; // wood
315 protected float m_bounce = 0.5f; // wood
316
317
318 protected bool m_isSelected = false;
319
285 /// <summary> 320 /// <summary>
286 /// Stores media texture data 321 /// Stores media texture data
287 /// </summary> 322 /// </summary>
@@ -297,6 +332,17 @@ namespace OpenSim.Region.Framework.Scenes
297 private UUID m_collisionSound; 332 private UUID m_collisionSound;
298 private float m_collisionSoundVolume; 333 private float m_collisionSoundVolume;
299 334
335
336 private SOPVehicle m_vehicle = null;
337
338 private KeyframeMotion m_keyframeMotion = null;
339
340 public KeyframeMotion KeyframeMotion
341 {
342 get; set;
343 }
344
345
300 #endregion Fields 346 #endregion Fields
301 347
302// ~SceneObjectPart() 348// ~SceneObjectPart()
@@ -339,7 +385,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 385 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) : this() 386 Quaternion rotationOffset, Vector3 offsetPosition) : this()
341 { 387 {
342 m_name = "Primitive"; 388 m_name = "Object";
343 389
344 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 390 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
345 LastOwnerID = CreatorID = OwnerID = ownerID; 391 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -379,7 +425,7 @@ namespace OpenSim.Region.Framework.Scenes
379 private uint _ownerMask = (uint)PermissionMask.All; 425 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 426 private uint _groupMask = (uint)PermissionMask.None;
381 private uint _everyoneMask = (uint)PermissionMask.None; 427 private uint _everyoneMask = (uint)PermissionMask.None;
382 private uint _nextOwnerMask = (uint)PermissionMask.All; 428 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
383 private PrimFlags _flags = PrimFlags.None; 429 private PrimFlags _flags = PrimFlags.None;
384 private DateTime m_expires; 430 private DateTime m_expires;
385 private DateTime m_rezzed; 431 private DateTime m_rezzed;
@@ -473,12 +519,16 @@ namespace OpenSim.Region.Framework.Scenes
473 } 519 }
474 520
475 /// <value> 521 /// <value>
476 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 522 /// Get the inventory list
477 /// </value> 523 /// </value>
478 public TaskInventoryDictionary TaskInventory 524 public TaskInventoryDictionary TaskInventory
479 { 525 {
480 get { return m_inventory.Items; } 526 get {
481 set { m_inventory.Items = value; } 527 return m_inventory.Items;
528 }
529 set {
530 m_inventory.Items = value;
531 }
482 } 532 }
483 533
484 /// <summary> 534 /// <summary>
@@ -528,20 +578,6 @@ namespace OpenSim.Region.Framework.Scenes
528 } 578 }
529 } 579 }
530 580
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] 581 [XmlIgnore]
546 public bool PassTouches 582 public bool PassTouches
547 { 583 {
@@ -567,6 +603,18 @@ namespace OpenSim.Region.Framework.Scenes
567 } 603 }
568 } 604 }
569 605
606 public bool IsSelected
607 {
608 get { return m_isSelected; }
609 set
610 {
611 m_isSelected = value;
612 if (ParentGroup != null)
613 ParentGroup.PartSelectChanged(value);
614 }
615 }
616
617
570 public Dictionary<int, string> CollisionFilter 618 public Dictionary<int, string> CollisionFilter
571 { 619 {
572 get { return m_CollisionFilter; } 620 get { return m_CollisionFilter; }
@@ -635,14 +683,12 @@ namespace OpenSim.Region.Framework.Scenes
635 set { m_LoopSoundSlavePrims = value; } 683 set { m_LoopSoundSlavePrims = value; }
636 } 684 }
637 685
638
639 public Byte[] TextureAnimation 686 public Byte[] TextureAnimation
640 { 687 {
641 get { return m_TextureAnimation; } 688 get { return m_TextureAnimation; }
642 set { m_TextureAnimation = value; } 689 set { m_TextureAnimation = value; }
643 } 690 }
644 691
645
646 public Byte[] ParticleSystem 692 public Byte[] ParticleSystem
647 { 693 {
648 get { return m_particleSystem; } 694 get { return m_particleSystem; }
@@ -679,8 +725,12 @@ namespace OpenSim.Region.Framework.Scenes
679 { 725 {
680 // If this is a linkset, we don't want the physics engine mucking up our group position here. 726 // If this is a linkset, we don't want the physics engine mucking up our group position here.
681 PhysicsActor actor = PhysActor; 727 PhysicsActor actor = PhysActor;
682 if (actor != null && ParentID == 0) 728 if (ParentID == 0)
683 m_groupPosition = actor.Position; 729 {
730 if (actor != null)
731 m_groupPosition = actor.Position;
732 return m_groupPosition;
733 }
684 734
685 if (ParentGroup.IsAttachment) 735 if (ParentGroup.IsAttachment)
686 { 736 {
@@ -689,12 +739,14 @@ namespace OpenSim.Region.Framework.Scenes
689 return sp.AbsolutePosition; 739 return sp.AbsolutePosition;
690 } 740 }
691 741
742 // use root prim's group position. Physics may have updated it
743 if (ParentGroup.RootPart != this)
744 m_groupPosition = ParentGroup.RootPart.GroupPosition;
692 return m_groupPosition; 745 return m_groupPosition;
693 } 746 }
694 set 747 set
695 { 748 {
696 m_groupPosition = value; 749 m_groupPosition = value;
697
698 PhysicsActor actor = PhysActor; 750 PhysicsActor actor = PhysActor;
699 if (actor != null) 751 if (actor != null)
700 { 752 {
@@ -720,16 +772,6 @@ namespace OpenSim.Region.Framework.Scenes
720 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 772 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
721 } 773 }
722 } 774 }
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 } 775 }
734 } 776 }
735 777
@@ -738,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
738 get { return m_offsetPosition; } 780 get { return m_offsetPosition; }
739 set 781 set
740 { 782 {
741// StoreUndoState(); 783 Vector3 oldpos = m_offsetPosition;
742 m_offsetPosition = value; 784 m_offsetPosition = value;
743 785
744 if (ParentGroup != null && !ParentGroup.IsDeleted) 786 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -753,7 +795,22 @@ namespace OpenSim.Region.Framework.Scenes
753 if (ParentGroup.Scene != null) 795 if (ParentGroup.Scene != null)
754 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 796 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
755 } 797 }
798
799 if (!m_parentGroup.m_dupeInProgress)
800 {
801 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
802 foreach (ScenePresence av in avs)
803 {
804 if (av.ParentID == m_localId)
805 {
806 Vector3 offset = (m_offsetPosition - oldpos);
807 av.AbsolutePosition += offset;
808 av.SendAvatarDataToAllAgents();
809 }
810 }
811 }
756 } 812 }
813 TriggerScriptChangedEvent(Changed.POSITION);
757 } 814 }
758 } 815 }
759 816
@@ -802,7 +859,7 @@ namespace OpenSim.Region.Framework.Scenes
802 859
803 set 860 set
804 { 861 {
805 StoreUndoState(); 862// StoreUndoState();
806 m_rotationOffset = value; 863 m_rotationOffset = value;
807 864
808 PhysicsActor actor = PhysActor; 865 PhysicsActor actor = PhysActor;
@@ -890,7 +947,7 @@ namespace OpenSim.Region.Framework.Scenes
890 get 947 get
891 { 948 {
892 PhysicsActor actor = PhysActor; 949 PhysicsActor actor = PhysActor;
893 if ((actor != null) && actor.IsPhysical) 950 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
894 { 951 {
895 m_angularVelocity = actor.RotationalVelocity; 952 m_angularVelocity = actor.RotationalVelocity;
896 } 953 }
@@ -902,7 +959,16 @@ namespace OpenSim.Region.Framework.Scenes
902 /// <summary></summary> 959 /// <summary></summary>
903 public Vector3 Acceleration 960 public Vector3 Acceleration
904 { 961 {
905 get { return m_acceleration; } 962 get
963 {
964 PhysicsActor actor = PhysActor;
965 if (actor != null)
966 {
967 m_acceleration = actor.Acceleration;
968 }
969 return m_acceleration;
970 }
971
906 set { m_acceleration = value; } 972 set { m_acceleration = value; }
907 } 973 }
908 974
@@ -970,7 +1036,10 @@ namespace OpenSim.Region.Framework.Scenes
970 public PrimitiveBaseShape Shape 1036 public PrimitiveBaseShape Shape
971 { 1037 {
972 get { return m_shape; } 1038 get { return m_shape; }
973 set { m_shape = value;} 1039 set
1040 {
1041 m_shape = value;
1042 }
974 } 1043 }
975 1044
976 /// <summary> 1045 /// <summary>
@@ -983,7 +1052,6 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1052 {
984 if (m_shape != null) 1053 if (m_shape != null)
985 { 1054 {
986 StoreUndoState();
987 1055
988 m_shape.Scale = value; 1056 m_shape.Scale = value;
989 1057
@@ -1010,6 +1078,7 @@ namespace OpenSim.Region.Framework.Scenes
1010 } 1078 }
1011 1079
1012 public UpdateRequired UpdateFlag { get; set; } 1080 public UpdateRequired UpdateFlag { get; set; }
1081 public bool UpdatePhysRequired { get; set; }
1013 1082
1014 /// <summary> 1083 /// <summary>
1015 /// Used for media on a prim. 1084 /// Used for media on a prim.
@@ -1050,10 +1119,7 @@ namespace OpenSim.Region.Framework.Scenes
1050 { 1119 {
1051 get 1120 get
1052 { 1121 {
1053 if (ParentGroup.IsAttachment) 1122 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1054 return GroupPosition;
1055
1056 return m_offsetPosition + m_groupPosition;
1057 } 1123 }
1058 } 1124 }
1059 1125
@@ -1231,6 +1297,13 @@ namespace OpenSim.Region.Framework.Scenes
1231 _flags = value; 1297 _flags = value;
1232 } 1298 }
1233 } 1299 }
1300
1301 [XmlIgnore]
1302 public bool IsOccupied // KF If an av is sittingon this prim
1303 {
1304 get { return m_occupied; }
1305 set { m_occupied = value; }
1306 }
1234 1307
1235 /// <summary> 1308 /// <summary>
1236 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1309 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1290,6 +1363,316 @@ namespace OpenSim.Region.Framework.Scenes
1290 set { m_collisionSoundVolume = value; } 1363 set { m_collisionSoundVolume = value; }
1291 } 1364 }
1292 1365
1366 public float Buoyancy
1367 {
1368 get
1369 {
1370 if (ParentGroup.RootPart == this)
1371 return m_buoyancy;
1372
1373 return ParentGroup.RootPart.Buoyancy;
1374 }
1375 set
1376 {
1377 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1378 {
1379 ParentGroup.RootPart.Buoyancy = value;
1380 return;
1381 }
1382 m_buoyancy = value;
1383 if (PhysActor != null)
1384 PhysActor.Buoyancy = value;
1385 }
1386 }
1387
1388 public Vector3 Force
1389 {
1390 get
1391 {
1392 if (ParentGroup.RootPart == this)
1393 return m_force;
1394
1395 return ParentGroup.RootPart.Force;
1396 }
1397
1398 set
1399 {
1400 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1401 {
1402 ParentGroup.RootPart.Force = value;
1403 return;
1404 }
1405 m_force = value;
1406 if (PhysActor != null)
1407 PhysActor.Force = value;
1408 }
1409 }
1410
1411 public Vector3 Torque
1412 {
1413 get
1414 {
1415 if (ParentGroup.RootPart == this)
1416 return m_torque;
1417
1418 return ParentGroup.RootPart.Torque;
1419 }
1420
1421 set
1422 {
1423 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1424 {
1425 ParentGroup.RootPart.Torque = value;
1426 return;
1427 }
1428 m_torque = value;
1429 if (PhysActor != null)
1430 PhysActor.Torque = value;
1431 }
1432 }
1433
1434 public byte Material
1435 {
1436 get { return (byte)m_material; }
1437 set
1438 {
1439 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1440 {
1441 bool update = false;
1442
1443 if (m_material != (Material)value)
1444 {
1445 update = true;
1446 m_material = (Material)value;
1447 }
1448
1449 if (m_friction != SOPMaterialData.friction(m_material))
1450 {
1451 update = true;
1452 m_friction = SOPMaterialData.friction(m_material);
1453 }
1454
1455 if (m_bounce != SOPMaterialData.bounce(m_material))
1456 {
1457 update = true;
1458 m_bounce = SOPMaterialData.bounce(m_material);
1459 }
1460
1461 if (update)
1462 {
1463 if (PhysActor != null)
1464 {
1465 PhysActor.SetMaterial((int)value);
1466 }
1467 if(ParentGroup != null)
1468 ParentGroup.HasGroupChanged = true;
1469 ScheduleFullUpdateIfNone();
1470 UpdatePhysRequired = true;
1471 }
1472 }
1473 }
1474 }
1475
1476 // not a propriety to move to methods place later
1477 private bool HasMesh()
1478 {
1479 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1480 return true;
1481 return false;
1482 }
1483
1484 // not a propriety to move to methods place later
1485 public byte DefaultPhysicsShapeType()
1486 {
1487 byte type;
1488
1489 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1490 type = (byte)PhysShapeType.convex;
1491 else
1492 type = (byte)PhysShapeType.prim;
1493
1494 return type;
1495 }
1496
1497 [XmlIgnore]
1498 public bool UsesComplexCost
1499 {
1500 get
1501 {
1502 byte pst = PhysicsShapeType;
1503 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1504 return true;
1505 return false;
1506 }
1507 }
1508
1509 [XmlIgnore]
1510 public float PhysicsCost
1511 {
1512 get
1513 {
1514 if(PhysicsShapeType == (byte)PhysShapeType.none)
1515 return 0;
1516
1517 float cost = 0.1f;
1518 if (PhysActor != null)
1519// cost += PhysActor.Cost;
1520
1521 if ((Flags & PrimFlags.Physics) != 0)
1522 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1523 return cost;
1524 }
1525 }
1526
1527 [XmlIgnore]
1528 public float StreamingCost
1529 {
1530 get
1531 {
1532
1533
1534 return 0.1f;
1535 }
1536 }
1537
1538 [XmlIgnore]
1539 public float SimulationCost
1540 {
1541 get
1542 {
1543 // ignoring scripts. Don't like considering them for this
1544 if((Flags & PrimFlags.Physics) != 0)
1545 return 1.0f;
1546
1547 return 0.5f;
1548 }
1549 }
1550
1551 public byte PhysicsShapeType
1552 {
1553 get { return m_physicsShapeType; }
1554 set
1555 {
1556 byte oldv = m_physicsShapeType;
1557
1558 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1559 {
1560 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1561 m_physicsShapeType = DefaultPhysicsShapeType();
1562 else
1563 m_physicsShapeType = value;
1564 }
1565 else
1566 m_physicsShapeType = DefaultPhysicsShapeType();
1567
1568 if (m_physicsShapeType != oldv && ParentGroup != null)
1569 {
1570 if (m_physicsShapeType == (byte)PhysShapeType.none)
1571 {
1572 if (PhysActor != null)
1573 {
1574 Velocity = new Vector3(0, 0, 0);
1575 Acceleration = new Vector3(0, 0, 0);
1576 if (ParentGroup.RootPart == this)
1577 AngularVelocity = new Vector3(0, 0, 0);
1578 ParentGroup.Scene.RemovePhysicalPrim(1);
1579 RemoveFromPhysics();
1580 }
1581 }
1582 else if (PhysActor == null)
1583 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1584 else
1585 {
1586 PhysActor.PhysicsShapeType = m_physicsShapeType;
1587 if (Shape.SculptEntry)
1588 CheckSculptAndLoad();
1589 }
1590
1591 if (ParentGroup != null)
1592 ParentGroup.HasGroupChanged = true;
1593 }
1594
1595 if (m_physicsShapeType != value)
1596 {
1597 UpdatePhysRequired = true;
1598 }
1599 }
1600 }
1601
1602 public float Density // in kg/m^3
1603 {
1604 get { return m_density; }
1605 set
1606 {
1607 if (value >=1 && value <= 22587.0)
1608 {
1609 m_density = value;
1610 UpdatePhysRequired = true;
1611 }
1612
1613 ScheduleFullUpdateIfNone();
1614
1615 if (ParentGroup != null)
1616 ParentGroup.HasGroupChanged = true;
1617 }
1618 }
1619
1620 public float GravityModifier
1621 {
1622 get { return m_gravitymod; }
1623 set
1624 {
1625 if( value >= -1 && value <=28.0f)
1626 {
1627 m_gravitymod = value;
1628 UpdatePhysRequired = true;
1629 }
1630
1631 ScheduleFullUpdateIfNone();
1632
1633 if (ParentGroup != null)
1634 ParentGroup.HasGroupChanged = true;
1635
1636 }
1637 }
1638
1639 public float Friction
1640 {
1641 get { return m_friction; }
1642 set
1643 {
1644 if (value >= 0 && value <= 255.0f)
1645 {
1646 m_friction = value;
1647 UpdatePhysRequired = true;
1648 }
1649
1650 ScheduleFullUpdateIfNone();
1651
1652 if (ParentGroup != null)
1653 ParentGroup.HasGroupChanged = true;
1654 }
1655 }
1656
1657 public float Bounciness
1658 {
1659 get { return m_bounce; }
1660 set
1661 {
1662 if (value >= 0 && value <= 1.0f)
1663 {
1664 m_bounce = value;
1665 UpdatePhysRequired = true;
1666 }
1667
1668 ScheduleFullUpdateIfNone();
1669
1670 if (ParentGroup != null)
1671 ParentGroup.HasGroupChanged = true;
1672 }
1673 }
1674
1675
1293 #endregion Public Properties with only Get 1676 #endregion Public Properties with only Get
1294 1677
1295 private uint ApplyMask(uint val, bool set, uint mask) 1678 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1455,7 +1838,7 @@ namespace OpenSim.Region.Framework.Scenes
1455 impulse = newimpulse; 1838 impulse = newimpulse;
1456 } 1839 }
1457 1840
1458 ParentGroup.applyAngularImpulse(impulse); 1841 ParentGroup.ApplyAngularImpulse(impulse);
1459 } 1842 }
1460 1843
1461 /// <summary> 1844 /// <summary>
@@ -1465,20 +1848,24 @@ namespace OpenSim.Region.Framework.Scenes
1465 /// </summary> 1848 /// </summary>
1466 /// <param name="impulsei">Vector force</param> 1849 /// <param name="impulsei">Vector force</param>
1467 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1850 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1468 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1851
1852 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1853 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1469 { 1854 {
1470 Vector3 impulse = impulsei; 1855 Vector3 torque = torquei;
1471 1856
1472 if (localGlobalTF) 1857 if (localGlobalTF)
1473 { 1858 {
1859/*
1474 Quaternion grot = GetWorldRotation(); 1860 Quaternion grot = GetWorldRotation();
1475 Quaternion AXgrot = grot; 1861 Quaternion AXgrot = grot;
1476 Vector3 AXimpulsei = impulsei; 1862 Vector3 AXimpulsei = impulsei;
1477 Vector3 newimpulse = AXimpulsei * AXgrot; 1863 Vector3 newimpulse = AXimpulsei * AXgrot;
1478 impulse = newimpulse; 1864 */
1865 torque *= GetWorldRotation();
1479 } 1866 }
1480 1867
1481 ParentGroup.setAngularImpulse(impulse); 1868 Torque = torque;
1482 } 1869 }
1483 1870
1484 /// <summary> 1871 /// <summary>
@@ -1486,17 +1873,23 @@ namespace OpenSim.Region.Framework.Scenes
1486 /// </summary> 1873 /// </summary>
1487 /// <param name="rootObjectFlags"></param> 1874 /// <param name="rootObjectFlags"></param>
1488 /// <param name="VolumeDetectActive"></param> 1875 /// <param name="VolumeDetectActive"></param>
1489 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1876 /// <param name="building"></param>
1877
1878 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1490 { 1879 {
1880 VolumeDetectActive = _VolumeDetectActive;
1881
1491 if (!ParentGroup.Scene.CollidablePrims) 1882 if (!ParentGroup.Scene.CollidablePrims)
1492 return; 1883 return;
1493 1884
1494// m_log.DebugFormat( 1885 if (PhysicsShapeType == (byte)PhysShapeType.none)
1495// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1886 return;
1496// Name, LocalId, UUID, m_physicalPrim); 1887
1888 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1889 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1497 1890
1498 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1891 if (_VolumeDetectActive)
1499 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1892 isPhantom = true;
1500 1893
1501 if (IsJoint()) 1894 if (IsJoint())
1502 { 1895 {
@@ -1504,22 +1897,14 @@ namespace OpenSim.Region.Framework.Scenes
1504 } 1897 }
1505 else 1898 else
1506 { 1899 {
1507 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1900 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1508 if (VolumeDetectActive) 1901 && !(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 { 1902 {
1515 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1903 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1516 bool rigidBody = isPhysical && !isPhantom; 1904 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1517
1518 PhysicsActor pa = AddToPhysics(rigidBody);
1519
1520 if (pa != null)
1521 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1522 } 1905 }
1906 else
1907 PhysActor = null; // just to be sure
1523 } 1908 }
1524 } 1909 }
1525 1910
@@ -1571,6 +1956,12 @@ namespace OpenSim.Region.Framework.Scenes
1571 dupe.Category = Category; 1956 dupe.Category = Category;
1572 dupe.m_rezzed = m_rezzed; 1957 dupe.m_rezzed = m_rezzed;
1573 1958
1959 dupe.m_UndoRedo = null;
1960 dupe.m_isSelected = false;
1961
1962 dupe.IgnoreUndoUpdate = false;
1963 dupe.Undoing = false;
1964
1574 dupe.m_inventory = new SceneObjectPartInventory(dupe); 1965 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1575 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 1966 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1576 1967
@@ -1586,6 +1977,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 1977
1587 // Move afterwards ResetIDs as it clears the localID 1978 // Move afterwards ResetIDs as it clears the localID
1588 dupe.LocalId = localID; 1979 dupe.LocalId = localID;
1980
1589 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1981 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1590 dupe.LastOwnerID = OwnerID; 1982 dupe.LastOwnerID = OwnerID;
1591 1983
@@ -1603,8 +1995,12 @@ namespace OpenSim.Region.Framework.Scenes
1603 1995
1604 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 1996 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1605 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 1997 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1998// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1606 } 1999 }
1607 2000
2001 if (dupe.PhysActor != null)
2002 dupe.PhysActor.LocalID = localID;
2003
1608 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2004 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1609 2005
1610// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2006// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1724,6 +2120,7 @@ namespace OpenSim.Region.Framework.Scenes
1724 2120
1725 /// <summary> 2121 /// <summary>
1726 /// Do a physics propery update for this part. 2122 /// Do a physics propery update for this part.
2123 /// now also updates phantom and volume detector
1727 /// </summary> 2124 /// </summary>
1728 /// <param name="UsePhysics"></param> 2125 /// <param name="UsePhysics"></param>
1729 /// <param name="isNew"></param> 2126 /// <param name="isNew"></param>
@@ -1749,61 +2146,69 @@ namespace OpenSim.Region.Framework.Scenes
1749 { 2146 {
1750 if (pa.IsPhysical) // implies UsePhysics==false for this block 2147 if (pa.IsPhysical) // implies UsePhysics==false for this block
1751 { 2148 {
1752 if (!isNew) 2149 if (!isNew) // implies UsePhysics==false for this block
2150 {
1753 ParentGroup.Scene.RemovePhysicalPrim(1); 2151 ParentGroup.Scene.RemovePhysicalPrim(1);
1754 2152
1755 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2153 Velocity = new Vector3(0, 0, 0);
1756 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2154 Acceleration = new Vector3(0, 0, 0);
1757 pa.delink(); 2155 if (ParentGroup.RootPart == this)
2156 AngularVelocity = new Vector3(0, 0, 0);
1758 2157
1759 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2158 if (pa.Phantom && !VolumeDetectActive)
1760 { 2159 {
1761 // destroy all joints connected to this now deactivated body 2160 RemoveFromPhysics();
1762 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2161 return;
1763 } 2162 }
1764 2163
1765 // stop client-side interpolation of all joint proxy objects that have just been deleted 2164 pa.IsPhysical = UsePhysics;
1766 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2165 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1767 // which stops client-side interpolation of deactivated joint proxy objects. 2166 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2167 pa.delink();
2168 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2169 {
2170 // destroy all joints connected to this now deactivated body
2171 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2172 }
2173 }
1768 } 2174 }
1769 2175
1770 if (!UsePhysics && !isNew) 2176 if (pa.IsPhysical != UsePhysics)
1771 { 2177 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 2178
1781 pa.IsPhysical = UsePhysics; 2179 if (UsePhysics)
2180 {
2181 if (ParentGroup.RootPart.KeyframeMotion != null)
2182 ParentGroup.RootPart.KeyframeMotion.Stop();
2183 ParentGroup.RootPart.KeyframeMotion = null;
2184 ParentGroup.Scene.AddPhysicalPrim(1);
1782 2185
1783 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2186 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1784 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2187 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1785 /// that's not wholesome. Had to make Scene public
1786 //PhysActor = null;
1787 2188
1788 if ((Flags & PrimFlags.Phantom) == 0) 2189 if (ParentID != 0 && ParentID != LocalId)
1789 {
1790 if (UsePhysics)
1791 { 2190 {
1792 ParentGroup.Scene.AddPhysicalPrim(1); 2191 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1793 2192
1794 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2193 if (parentPa != null)
1795 pa.OnOutOfBounds += PhysicsOutOfBounds;
1796 if (ParentID != 0 && ParentID != LocalId)
1797 { 2194 {
1798 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2195 pa.link(parentPa);
1799
1800 if (parentPa != null)
1801 {
1802 pa.link(parentPa);
1803 }
1804 } 2196 }
1805 } 2197 }
1806 } 2198 }
2199 }
2200
2201 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2202 if (pa.Phantom != phan)
2203 pa.Phantom = phan;
2204
2205// some engines dont' have this check still
2206// if (VolumeDetectActive != pa.IsVolumeDtc)
2207 {
2208 if (VolumeDetectActive)
2209 pa.SetVolumeDetect(1);
2210 else
2211 pa.SetVolumeDetect(0);
1807 } 2212 }
1808 2213
1809 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2214 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1922,12 +2327,26 @@ namespace OpenSim.Region.Framework.Scenes
1922 2327
1923 public Vector3 GetGeometricCenter() 2328 public Vector3 GetGeometricCenter()
1924 { 2329 {
1925 PhysicsActor pa = PhysActor; 2330 // this is not real geometric center but a average of positions relative to root prim acording to
1926 2331 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
1927 if (pa != null) 2332 // ignoring tortured prims details since sl also seems to ignore
1928 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2333 // so no real use in doing it on physics
1929 else 2334 if (ParentGroup.IsDeleted)
1930 return new Vector3(0, 0, 0); 2335 return new Vector3(0, 0, 0);
2336
2337 return ParentGroup.GetGeometricCenter();
2338
2339 /*
2340 PhysicsActor pa = PhysActor;
2341
2342 if (pa != null)
2343 {
2344 Vector3 vtmp = pa.CenterOfMass;
2345 return vtmp;
2346 }
2347 else
2348 return new Vector3(0, 0, 0);
2349 */
1931 } 2350 }
1932 2351
1933 public float GetMass() 2352 public float GetMass()
@@ -1940,14 +2359,43 @@ namespace OpenSim.Region.Framework.Scenes
1940 return 0; 2359 return 0;
1941 } 2360 }
1942 2361
1943 public Vector3 GetForce() 2362 public Vector3 GetCenterOfMass()
1944 { 2363 {
2364 if (ParentGroup.RootPart == this)
2365 {
2366 if (ParentGroup.IsDeleted)
2367 return AbsolutePosition;
2368 return ParentGroup.GetCenterOfMass();
2369 }
2370
1945 PhysicsActor pa = PhysActor; 2371 PhysicsActor pa = PhysActor;
1946 2372
1947 if (pa != null) 2373 if (pa != null)
1948 return pa.Force; 2374 {
2375 Vector3 tmp = pa.CenterOfMass;
2376 return tmp;
2377 }
1949 else 2378 else
1950 return Vector3.Zero; 2379 return AbsolutePosition;
2380 }
2381
2382 public Vector3 GetPartCenterOfMass()
2383 {
2384 PhysicsActor pa = PhysActor;
2385
2386 if (pa != null)
2387 {
2388 Vector3 tmp = pa.CenterOfMass;
2389 return tmp;
2390 }
2391 else
2392 return AbsolutePosition;
2393 }
2394
2395
2396 public Vector3 GetForce()
2397 {
2398 return Force;
1951 } 2399 }
1952 2400
1953 /// <summary> 2401 /// <summary>
@@ -2178,45 +2626,61 @@ namespace OpenSim.Region.Framework.Scenes
2178 List<uint> endedColliders = new List<uint>(); 2626 List<uint> endedColliders = new List<uint>();
2179 List<uint> startedColliders = new List<uint>(); 2627 List<uint> startedColliders = new List<uint>();
2180 2628
2181 // calculate things that started colliding this time 2629 if (collissionswith.Count == 0)
2182 // and build up list of colliders this time
2183 foreach (uint localid in collissionswith.Keys)
2184 { 2630 {
2185 thisHitColliders.Add(localid); 2631 if (m_lastColliders.Count == 0)
2186 if (!m_lastColliders.Contains(localid)) 2632 return; // nothing to do
2187 startedColliders.Add(localid);
2188 }
2189 2633
2190 // calculate things that ended colliding 2634 foreach (uint localID in m_lastColliders)
2191 foreach (uint localID in m_lastColliders) 2635 {
2192 {
2193 if (!thisHitColliders.Contains(localID))
2194 endedColliders.Add(localID); 2636 endedColliders.Add(localID);
2637 }
2638 m_lastColliders.Clear();
2195 } 2639 }
2196 2640
2197 //add the items that started colliding this time to the last colliders list. 2641 else
2198 foreach (uint localID in startedColliders) 2642 {
2199 m_lastColliders.Add(localID); 2643
2644 // calculate things that started colliding this time
2645 // and build up list of colliders this time
2646 foreach (uint localid in collissionswith.Keys)
2647 {
2648 thisHitColliders.Add(localid);
2649 if (!m_lastColliders.Contains(localid))
2650 startedColliders.Add(localid);
2651 }
2200 2652
2201 // remove things that ended colliding from the last colliders list 2653 // calculate things that ended colliding
2202 foreach (uint localID in endedColliders) 2654 foreach (uint localID in m_lastColliders)
2203 m_lastColliders.Remove(localID); 2655 {
2656 if (!thisHitColliders.Contains(localID))
2657 endedColliders.Add(localID);
2658 }
2204 2659
2660 //add the items that started colliding this time to the last colliders list.
2661 foreach (uint localID in startedColliders)
2662 m_lastColliders.Add(localID);
2663
2664 // remove things that ended colliding from the last colliders list
2665 foreach (uint localID in endedColliders)
2666 m_lastColliders.Remove(localID);
2667 }
2205 // play the sound. 2668 // play the sound.
2206 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2669
2670 bool IsNotVolumeDtc = !VolumeDetectActive;
2671
2672 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f && IsNotVolumeDtc)
2207 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); 2673 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false);
2208 2674
2209 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2675 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2210 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2676 if (IsNotVolumeDtc)
2677 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2211 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2678 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2212 2679
2213 if (startedColliders.Contains(0)) 2680 if (startedColliders.Contains(0))
2214 { 2681 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2215 if (m_lastColliders.Contains(0)) 2682 if (m_lastColliders.Contains(0))
2216 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2683 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)) 2684 if (endedColliders.Contains(0))
2221 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2685 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2222 } 2686 }
@@ -2239,9 +2703,9 @@ namespace OpenSim.Region.Framework.Scenes
2239 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2703 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2240 2704
2241 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2705 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2242 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2706 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2243 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2707 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2244 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2708 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2245 { 2709 {
2246 ParentGroup.AbsolutePosition = newpos; 2710 ParentGroup.AbsolutePosition = newpos;
2247 return; 2711 return;
@@ -2263,17 +2727,18 @@ namespace OpenSim.Region.Framework.Scenes
2263 //Trys to fetch sound id from prim's inventory. 2727 //Trys to fetch sound id from prim's inventory.
2264 //Prim's inventory doesn't support non script items yet 2728 //Prim's inventory doesn't support non script items yet
2265 2729
2266 lock (TaskInventory) 2730 TaskInventory.LockItemsForRead(true);
2731
2732 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2267 { 2733 {
2268 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2734 if (item.Value.Name == sound)
2269 { 2735 {
2270 if (item.Value.Name == sound) 2736 soundID = item.Value.ItemID;
2271 { 2737 break;
2272 soundID = item.Value.ItemID;
2273 break;
2274 }
2275 } 2738 }
2276 } 2739 }
2740
2741 TaskInventory.LockItemsForRead(false);
2277 } 2742 }
2278 2743
2279 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2744 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2396,6 +2861,19 @@ namespace OpenSim.Region.Framework.Scenes
2396 APIDTarget = Quaternion.Identity; 2861 APIDTarget = Quaternion.Identity;
2397 } 2862 }
2398 2863
2864
2865
2866 public void ScheduleFullUpdateIfNone()
2867 {
2868 if (ParentGroup == null)
2869 return;
2870
2871// ??? ParentGroup.HasGroupChanged = true;
2872
2873 if (UpdateFlag != UpdateRequired.FULL)
2874 ScheduleFullUpdate();
2875 }
2876
2399 /// <summary> 2877 /// <summary>
2400 /// Schedules this prim for a full update 2878 /// Schedules this prim for a full update
2401 /// </summary> 2879 /// </summary>
@@ -2597,8 +3075,8 @@ namespace OpenSim.Region.Framework.Scenes
2597 { 3075 {
2598 const float ROTATION_TOLERANCE = 0.01f; 3076 const float ROTATION_TOLERANCE = 0.01f;
2599 const float VELOCITY_TOLERANCE = 0.001f; 3077 const float VELOCITY_TOLERANCE = 0.001f;
2600 const float POSITION_TOLERANCE = 0.05f; 3078 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2601 const int TIME_MS_TOLERANCE = 3000; 3079 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2602 3080
2603 switch (UpdateFlag) 3081 switch (UpdateFlag)
2604 { 3082 {
@@ -2660,17 +3138,16 @@ namespace OpenSim.Region.Framework.Scenes
2660 if (!UUID.TryParse(sound, out soundID)) 3138 if (!UUID.TryParse(sound, out soundID))
2661 { 3139 {
2662 // search sound file from inventory 3140 // search sound file from inventory
2663 lock (TaskInventory) 3141 TaskInventory.LockItemsForRead(true);
3142 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2664 { 3143 {
2665 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3144 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2666 { 3145 {
2667 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3146 soundID = item.Value.ItemID;
2668 { 3147 break;
2669 soundID = item.Value.ItemID;
2670 break;
2671 }
2672 } 3148 }
2673 } 3149 }
3150 TaskInventory.LockItemsForRead(false);
2674 } 3151 }
2675 3152
2676 if (soundID == UUID.Zero) 3153 if (soundID == UUID.Zero)
@@ -2755,10 +3232,13 @@ namespace OpenSim.Region.Framework.Scenes
2755 3232
2756 public void SetBuoyancy(float fvalue) 3233 public void SetBuoyancy(float fvalue)
2757 { 3234 {
2758 PhysicsActor pa = PhysActor; 3235 Buoyancy = fvalue;
2759 3236/*
2760 if (pa != null) 3237 if (PhysActor != null)
2761 pa.Buoyancy = fvalue; 3238 {
3239 PhysActor.Buoyancy = fvalue;
3240 }
3241 */
2762 } 3242 }
2763 3243
2764 public void SetDieAtEdge(bool p) 3244 public void SetDieAtEdge(bool p)
@@ -2774,47 +3254,111 @@ namespace OpenSim.Region.Framework.Scenes
2774 PhysicsActor pa = PhysActor; 3254 PhysicsActor pa = PhysActor;
2775 3255
2776 if (pa != null) 3256 if (pa != null)
2777 pa.FloatOnWater = floatYN == 1; 3257 pa.FloatOnWater = (floatYN == 1);
2778 } 3258 }
2779 3259
2780 public void SetForce(Vector3 force) 3260 public void SetForce(Vector3 force)
2781 { 3261 {
2782 PhysicsActor pa = PhysActor; 3262 Force = force;
3263 }
2783 3264
2784 if (pa != null) 3265 public SOPVehicle sopVehicle
2785 pa.Force = force; 3266 {
3267 get
3268 {
3269 return m_vehicle;
3270 }
3271 set
3272 {
3273 m_vehicle = value;
3274 }
3275 }
3276
3277
3278 public int VehicleType
3279 {
3280 get
3281 {
3282 if (m_vehicle == null)
3283 return (int)Vehicle.TYPE_NONE;
3284 else
3285 return (int)m_vehicle.Type;
3286 }
3287 set
3288 {
3289 SetVehicleType(value);
3290 }
2786 } 3291 }
2787 3292
2788 public void SetVehicleType(int type) 3293 public void SetVehicleType(int type)
2789 { 3294 {
2790 PhysicsActor pa = PhysActor; 3295 m_vehicle = null;
3296
3297 if (type == (int)Vehicle.TYPE_NONE)
3298 {
3299 if (_parentID ==0 && PhysActor != null)
3300 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3301 return;
3302 }
3303 m_vehicle = new SOPVehicle();
3304 m_vehicle.ProcessTypeChange((Vehicle)type);
3305 {
3306 if (_parentID ==0 && PhysActor != null)
3307 PhysActor.VehicleType = type;
3308 return;
3309 }
3310 }
2791 3311
2792 if (pa != null) 3312 public void SetVehicleFlags(int param, bool remove)
2793 pa.VehicleType = type; 3313 {
3314 if (m_vehicle == null)
3315 return;
3316
3317 m_vehicle.ProcessVehicleFlags(param, remove);
3318
3319 if (_parentID ==0 && PhysActor != null)
3320 {
3321 PhysActor.VehicleFlags(param, remove);
3322 }
2794 } 3323 }
2795 3324
2796 public void SetVehicleFloatParam(int param, float value) 3325 public void SetVehicleFloatParam(int param, float value)
2797 { 3326 {
2798 PhysicsActor pa = PhysActor; 3327 if (m_vehicle == null)
3328 return;
2799 3329
2800 if (pa != null) 3330 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
2801 pa.VehicleFloatParam(param, value); 3331
3332 if (_parentID == 0 && PhysActor != null)
3333 {
3334 PhysActor.VehicleFloatParam(param, value);
3335 }
2802 } 3336 }
2803 3337
2804 public void SetVehicleVectorParam(int param, Vector3 value) 3338 public void SetVehicleVectorParam(int param, Vector3 value)
2805 { 3339 {
2806 PhysicsActor pa = PhysActor; 3340 if (m_vehicle == null)
3341 return;
2807 3342
2808 if (pa != null) 3343 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
2809 pa.VehicleVectorParam(param, value); 3344
3345 if (_parentID == 0 && PhysActor != null)
3346 {
3347 PhysActor.VehicleVectorParam(param, value);
3348 }
2810 } 3349 }
2811 3350
2812 public void SetVehicleRotationParam(int param, Quaternion rotation) 3351 public void SetVehicleRotationParam(int param, Quaternion rotation)
2813 { 3352 {
2814 PhysicsActor pa = PhysActor; 3353 if (m_vehicle == null)
3354 return;
2815 3355
2816 if (pa != null) 3356 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
2817 pa.VehicleRotationParam(param, rotation); 3357
3358 if (_parentID == 0 && PhysActor != null)
3359 {
3360 PhysActor.VehicleRotationParam(param, rotation);
3361 }
2818 } 3362 }
2819 3363
2820 /// <summary> 3364 /// <summary>
@@ -2998,14 +3542,6 @@ namespace OpenSim.Region.Framework.Scenes
2998 hasProfileCut = hasDimple; // is it the same thing? 3542 hasProfileCut = hasDimple; // is it the same thing?
2999 } 3543 }
3000 3544
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) 3545 public void SetGroup(UUID groupID, IClientAPI client)
3010 { 3546 {
3011 // Scene.AddNewPrims() calls with client == null so can't use this. 3547 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3109,68 +3645,18 @@ namespace OpenSim.Region.Framework.Scenes
3109 //ParentGroup.ScheduleGroupForFullUpdate(); 3645 //ParentGroup.ScheduleGroupForFullUpdate();
3110 } 3646 }
3111 3647
3112 public void StoreUndoState() 3648 public void StoreUndoState(ObjectChangeType change)
3113 { 3649 {
3114 StoreUndoState(false); 3650 if (m_UndoRedo == null)
3115 } 3651 m_UndoRedo = new UndoRedoState(5);
3116 3652
3117 public void StoreUndoState(bool forGroup) 3653 lock (m_UndoRedo)
3118 {
3119 if (!Undoing)
3120 { 3654 {
3121 if (!IgnoreUndoUpdate) 3655 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3122 { 3656 {
3123 if (ParentGroup != null) 3657 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 } 3658 }
3164// else
3165// {
3166// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3167// }
3168 } 3659 }
3169// else
3170// {
3171// m_log.DebugFormat(
3172// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3173// }
3174 } 3660 }
3175 3661
3176 /// <summary> 3662 /// <summary>
@@ -3180,84 +3666,46 @@ namespace OpenSim.Region.Framework.Scenes
3180 { 3666 {
3181 get 3667 get
3182 { 3668 {
3183 lock (m_undo) 3669 if (m_UndoRedo == null)
3184 return m_undo.Count; 3670 return 0;
3671 return m_UndoRedo.Count;
3185 } 3672 }
3186 } 3673 }
3187 3674
3188 public void Undo() 3675 public void Undo()
3189 { 3676 {
3190 lock (m_undo) 3677 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3191 { 3678 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 3679
3216// m_log.DebugFormat( 3680 lock (m_UndoRedo)
3217// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3681 {
3218// Name, LocalId, m_undo.Count); 3682 Undoing = true;
3683 m_UndoRedo.Undo(this);
3684 Undoing = false;
3219 } 3685 }
3220 } 3686 }
3221 3687
3222 public void Redo() 3688 public void Redo()
3223 { 3689 {
3224 lock (m_undo) 3690 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3225 { 3691 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 3692
3246// m_log.DebugFormat( 3693 lock (m_UndoRedo)
3247// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3694 {
3248// Name, LocalId, m_redo.Count); 3695 Undoing = true;
3249 } 3696 m_UndoRedo.Redo(this);
3697 Undoing = false;
3250 } 3698 }
3251 } 3699 }
3252 3700
3253 public void ClearUndoState() 3701 public void ClearUndoState()
3254 { 3702 {
3255// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3703 if (m_UndoRedo == null || Undoing)
3704 return;
3256 3705
3257 lock (m_undo) 3706 lock (m_UndoRedo)
3258 { 3707 {
3259 m_undo.Clear(); 3708 m_UndoRedo.Clear();
3260 m_redo.Clear();
3261 } 3709 }
3262 } 3710 }
3263 3711
@@ -3887,6 +4335,27 @@ namespace OpenSim.Region.Framework.Scenes
3887 } 4335 }
3888 } 4336 }
3889 4337
4338
4339 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4340 {
4341 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4342 return;
4343
4344 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4345 {
4346 PhysicsShapeType = (byte)physdata.PhysShapeType;
4347
4348 }
4349
4350 if(Density != physdata.Density)
4351 Density = physdata.Density;
4352 if(GravityModifier != physdata.GravitationModifier)
4353 GravityModifier = physdata.GravitationModifier;
4354 if(Friction != physdata.Friction)
4355 Friction = physdata.Friction;
4356 if(Bounciness != physdata.Bounce)
4357 Bounciness = physdata.Bounce;
4358 }
3890 /// <summary> 4359 /// <summary>
3891 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4360 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3892 /// </summary> 4361 /// </summary>
@@ -3894,7 +4363,7 @@ namespace OpenSim.Region.Framework.Scenes
3894 /// <param name="SetTemporary"></param> 4363 /// <param name="SetTemporary"></param>
3895 /// <param name="SetPhantom"></param> 4364 /// <param name="SetPhantom"></param>
3896 /// <param name="SetVD"></param> 4365 /// <param name="SetVD"></param>
3897 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4366 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3898 { 4367 {
3899 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4368 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3900 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4369 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3904,233 +4373,218 @@ namespace OpenSim.Region.Framework.Scenes
3904 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4373 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3905 return; 4374 return;
3906 4375
3907 PhysicsActor pa = PhysActor; 4376 VolumeDetectActive = SetVD;
3908 4377
3909 // Special cases for VD. VD can only be called from a script 4378 // volume detector implies phantom
3910 // and can't be combined with changes to other states. So we can rely 4379 if (VolumeDetectActive)
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
3937 if (UsePhysics && IsJoint())
3938 {
3939 SetPhantom = true; 4380 SetPhantom = true;
3940 }
3941 4381
3942 if (UsePhysics) 4382 if (UsePhysics)
3943 {
3944 AddFlag(PrimFlags.Physics); 4383 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 4384 else
3959 {
3960 RemFlag(PrimFlags.Physics); 4385 RemFlag(PrimFlags.Physics);
3961 if (wasUsingPhysics)
3962 {
3963 DoPhysicsPropertyUpdate(UsePhysics, false);
3964 }
3965 }
3966 4386
3967 if (SetPhantom 4387 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); 4388 AddFlag(PrimFlags.Phantom);
3972 4389 else
3973 if (PhysActor != null)
3974 {
3975 RemoveFromPhysics();
3976 pa = null;
3977 }
3978 }
3979 else // Not phantom
3980 {
3981 RemFlag(PrimFlags.Phantom); 4390 RemFlag(PrimFlags.Phantom);
3982 4391
3983 if (ParentGroup.Scene == null) 4392 if (SetTemporary)
3984 return; 4393 AddFlag(PrimFlags.TemporaryOnRez);
4394 else
4395 RemFlag(PrimFlags.TemporaryOnRez);
3985 4396
3986 if (ParentGroup.Scene.CollidablePrims && pa == null)
3987 {
3988 pa = AddToPhysics(UsePhysics);
3989 4397
3990 if (pa != null) 4398 if (ParentGroup.Scene == null)
3991 { 4399 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 4400
4028 if (!ParentGroup.IsDeleted) 4401 PhysicsActor pa = PhysActor;
4029 {
4030 if (LocalId == ParentGroup.RootPart.LocalId)
4031 {
4032 ParentGroup.CheckSculptAndLoad();
4033 }
4034 }
4035 }
4036 }
4037 4402
4038 if (SetVD) 4403 if (pa != null && building && pa.Building != building)
4404 pa.Building = building;
4405
4406 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4407 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4039 { 4408 {
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) 4409 if (pa != null)
4046 { 4410 {
4047 pa.SetVolumeDetect(1); 4411 ParentGroup.Scene.RemovePhysicalPrim(1);
4048 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4412 RemoveFromPhysics();
4049 VolumeDetectActive = true;
4050 } 4413 }
4414
4415 Velocity = new Vector3(0, 0, 0);
4416 Acceleration = new Vector3(0, 0, 0);
4417 if (ParentGroup.RootPart == this)
4418 AngularVelocity = new Vector3(0, 0, 0);
4051 } 4419 }
4052 else 4420 else
4053 { 4421 {
4054 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4422 if (ParentGroup.Scene.CollidablePrims)
4055 // (mumbles, well, at least if you have infinte CPU powers :-)) 4423 {
4056 if (pa != null) 4424 if (pa == null)
4057 pa.SetVolumeDetect(0); 4425 {
4426 AddToPhysics(UsePhysics, SetPhantom, building, false);
4427 pa = PhysActor;
4428 /*
4429 if (pa != null)
4430 {
4431 if (
4432 // ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4433 // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4434 // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4435 // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4436 // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4437 // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4438 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4439 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4440 (CollisionSound != UUID.Zero)
4441 )
4442 {
4443 pa.OnCollisionUpdate += PhysicsCollision;
4444 pa.SubscribeEvents(1000);
4445 }
4446 }
4447 */
4448 }
4449 else // it already has a physical representation
4450 {
4451 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4452 /* moved into DoPhysicsPropertyUpdate
4453 if(VolumeDetectActive)
4454 pa.SetVolumeDetect(1);
4455 else
4456 pa.SetVolumeDetect(0);
4457 */
4058 4458
4059 VolumeDetectActive = false;
4060 }
4061 4459
4062 if (SetTemporary) 4460 if (pa.Building != building)
4063 { 4461 pa.Building = building;
4064 AddFlag(PrimFlags.TemporaryOnRez); 4462 }
4065 } 4463
4066 else 4464 UpdatePhysicsSubscribedEvents();
4067 { 4465 }
4068 RemFlag(PrimFlags.TemporaryOnRez); 4466 }
4069 }
4070 4467
4071 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4468 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4072 4469
4470 // and last in case we have a new actor and not building
4471
4073 if (ParentGroup != null) 4472 if (ParentGroup != null)
4074 { 4473 {
4075 ParentGroup.HasGroupChanged = true; 4474 ParentGroup.HasGroupChanged = true;
4076 ScheduleFullUpdate(); 4475 ScheduleFullUpdate();
4077 } 4476 }
4078 4477
4079// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4478// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4080 } 4479 }
4081 4480
4082 /// <summary> 4481 /// <summary>
4083 /// Adds this part to the physics scene. 4482 /// Adds this part to the physics scene.
4483 /// and sets the PhysActor property
4084 /// </summary> 4484 /// </summary>
4085 /// <remarks>This method also sets the PhysActor property.</remarks> 4485 /// <param name="isPhysical">Add this prim as physical.</param>
4086 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4486 /// <param name="isPhantom">Add this prim as phantom.</param>
4087 /// <returns> 4487 /// <param name="building">tells physics to delay full construction of object</param>
4088 /// The physics actor. null if there was a failure. 4488 /// <param name="applyDynamics">applies velocities, force and torque</param>
4089 /// </returns> 4489 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4090 private PhysicsActor AddToPhysics(bool rigidBody) 4490 {
4091 {
4092 PhysicsActor pa; 4491 PhysicsActor pa;
4093 4492
4493 Vector3 velocity = Velocity;
4494 Vector3 rotationalVelocity = AngularVelocity;;
4495
4094 try 4496 try
4095 { 4497 {
4096 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4498 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4097 string.Format("{0}/{1}", Name, UUID), 4499 string.Format("{0}/{1}", Name, UUID),
4098 Shape, 4500 Shape,
4099 AbsolutePosition, 4501 AbsolutePosition,
4100 Scale, 4502 Scale,
4101 RotationOffset, 4503 GetWorldRotation(),
4102 rigidBody, 4504 isPhysical,
4103 m_localId); 4505 isPhantom,
4506 PhysicsShapeType,
4507 m_localId);
4104 } 4508 }
4105 catch 4509 catch (Exception ex)
4106 { 4510 {
4107 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4511 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4108 pa = null; 4512 pa = null;
4109 } 4513 }
4110 4514
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) 4515 if (pa != null)
4118 { 4516 {
4119 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4517 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4120 pa.SetMaterial(Material); 4518 pa.SetMaterial(Material);
4121 DoPhysicsPropertyUpdate(rigidBody, true); 4519
4520 if (VolumeDetectActive) // change if not the default only
4521 pa.SetVolumeDetect(1);
4522
4523 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4524 m_vehicle.SetVehicle(pa);
4525
4526 // we are going to tell rest of code about physics so better have this here
4527 PhysActor = pa;
4528
4529 // DoPhysicsPropertyUpdate(isPhysical, true);
4530 // lets expand it here just with what it really needs to do
4531
4532 if (isPhysical)
4533 {
4534 if (ParentGroup.RootPart.KeyframeMotion != null)
4535 ParentGroup.RootPart.KeyframeMotion.Stop();
4536 ParentGroup.RootPart.KeyframeMotion = null;
4537 ParentGroup.Scene.AddPhysicalPrim(1);
4538
4539 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4540 pa.OnOutOfBounds += PhysicsOutOfBounds;
4541
4542 if (ParentID != 0 && ParentID != LocalId)
4543 {
4544 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4545
4546 if (parentPa != null)
4547 {
4548 pa.link(parentPa);
4549 }
4550 }
4551 }
4552
4553 if (applyDynamics)
4554 // do independent of isphysical so parameters get setted (at least some)
4555 {
4556 Velocity = velocity;
4557 AngularVelocity = rotationalVelocity;
4558// pa.Velocity = velocity;
4559 pa.RotationalVelocity = rotationalVelocity;
4560
4561 // if not vehicle and root part apply force and torque
4562 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
4563 && LocalId == ParentGroup.RootPart.LocalId)
4564 {
4565 pa.Force = Force;
4566 pa.Torque = Torque;
4567 }
4568 }
4569
4570 if (Shape.SculptEntry)
4571 CheckSculptAndLoad();
4572 else
4573 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4574
4575 if (!building)
4576 pa.Building = false;
4122 } 4577 }
4123 4578
4124 return pa; 4579 PhysActor = pa;
4125 } 4580 }
4126 4581
4127 /// <summary> 4582 /// <summary>
4128 /// This removes the part from the physics scene. 4583 /// This removes the part from the physics scene.
4129 /// </summary> 4584 /// </summary>
4130 /// <remarks> 4585 /// <remarks>
4131 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4586 /// 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 4587 /// representation for collision detection.
4133 /// phantom.
4134 /// </remarks> 4588 /// </remarks>
4135 public void RemoveFromPhysics() 4589 public void RemoveFromPhysics()
4136 { 4590 {
@@ -4294,6 +4748,46 @@ namespace OpenSim.Region.Framework.Scenes
4294 ScheduleFullUpdate(); 4748 ScheduleFullUpdate();
4295 } 4749 }
4296 4750
4751
4752 private void UpdatePhysicsSubscribedEvents()
4753 {
4754 PhysicsActor pa = PhysActor;
4755 if (pa == null)
4756 return;
4757
4758 pa.OnCollisionUpdate -= PhysicsCollision;
4759
4760 bool hassound = ( CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f);
4761 scriptEvents CombinedEvents = AggregateScriptEvents;
4762
4763 // merge with root part
4764 if (ParentGroup != null && ParentGroup.RootPart != null)
4765 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4766
4767 // submit to this part case
4768 if (VolumeDetectActive)
4769 {
4770 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4771 hassound = false;
4772 }
4773 else if ((Flags & PrimFlags.Phantom) != 0)
4774 CombinedEvents &= PhyscicsPhantonSubsEvents;
4775 else
4776 CombinedEvents &= PhysicsNeededSubsEvents;
4777
4778 if (hassound || CombinedEvents != 0)
4779 {
4780 // subscribe to physics updates.
4781 pa.OnCollisionUpdate += PhysicsCollision;
4782 pa.SubscribeEvents(50); // 20 reports per second
4783 }
4784 else
4785 {
4786 pa.UnSubscribeEvents();
4787 }
4788 }
4789
4790
4297 public void aggregateScriptEvents() 4791 public void aggregateScriptEvents()
4298 { 4792 {
4299 if (ParentGroup == null || ParentGroup.RootPart == null) 4793 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4330,40 +4824,32 @@ namespace OpenSim.Region.Framework.Scenes
4330 { 4824 {
4331 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4825 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4332 } 4826 }
4333 4827/*
4334 PhysicsActor pa = PhysActor; 4828 PhysicsActor pa = PhysActor;
4335 4829 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 { 4830 {
4352 // subscribe to physics updates. 4831 if (
4353 if (pa != null) 4832// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4833// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4834// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4835// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4836// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4837// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4838 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
4839 )
4354 { 4840 {
4841 // subscribe to physics updates.
4355 pa.OnCollisionUpdate += PhysicsCollision; 4842 pa.OnCollisionUpdate += PhysicsCollision;
4356 pa.SubscribeEvents(1000); 4843 pa.SubscribeEvents(1000);
4357 } 4844 }
4358 } 4845 else
4359 else
4360 {
4361 if (pa != null)
4362 { 4846 {
4363 pa.UnSubscribeEvents(); 4847 pa.UnSubscribeEvents();
4364 pa.OnCollisionUpdate -= PhysicsCollision; 4848 pa.OnCollisionUpdate -= PhysicsCollision;
4365 } 4849 }
4366 } 4850 }
4851 */
4852 UpdatePhysicsSubscribedEvents();
4367 4853
4368 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 4854 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4369 //{ 4855 //{
@@ -4491,5 +4977,17 @@ namespace OpenSim.Region.Framework.Scenes
4491 Color color = Color; 4977 Color color = Color;
4492 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4978 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4493 } 4979 }
4980
4981 public void ResetOwnerChangeFlag()
4982 {
4983 List<UUID> inv = Inventory.GetInventoryList();
4984
4985 foreach (UUID itemID in inv)
4986 {
4987 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4988 item.OwnerChanged = false;
4989 Inventory.UpdateInventoryItem(item, false, false);
4990 }
4991 }
4494 } 4992 }
4495} 4993}