diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1378 |
1 files changed, 901 insertions, 477 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index e3f06f8..6064279 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,6 +122,11 @@ 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; |
125 | |||
126 | private const scriptEvents PhyscicsNeededSubsEvents = ( | ||
127 | scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end | | ||
128 | scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end | ||
129 | ); | ||
124 | 130 | ||
125 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 131 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
126 | 132 | ||
@@ -182,6 +188,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
182 | 188 | ||
183 | public uint TimeStampTerse; | 189 | public uint TimeStampTerse; |
184 | 190 | ||
191 | // The following two are to hold the attachment data | ||
192 | // while an object is inworld | ||
193 | [XmlIgnore] | ||
194 | public byte AttachPoint = 0; | ||
195 | |||
196 | [XmlIgnore] | ||
197 | public Vector3 AttachOffset = Vector3.Zero; | ||
198 | |||
199 | [XmlIgnore] | ||
200 | public Quaternion AttachRotation = Quaternion.Identity; | ||
201 | |||
202 | [XmlIgnore] | ||
185 | public int STATUS_ROTATE_X; | 203 | public int STATUS_ROTATE_X; |
186 | 204 | ||
187 | public int STATUS_ROTATE_Y; | 205 | public int STATUS_ROTATE_Y; |
@@ -208,8 +226,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
208 | 226 | ||
209 | public Vector3 RotationAxis = Vector3.One; | 227 | public Vector3 RotationAxis = Vector3.One; |
210 | 228 | ||
211 | public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this | 229 | public bool VolumeDetectActive; |
212 | // Certainly this must be a persistant setting finally | ||
213 | 230 | ||
214 | public bool IsWaitingForFirstSpinUpdatePacket; | 231 | public bool IsWaitingForFirstSpinUpdatePacket; |
215 | 232 | ||
@@ -249,10 +266,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
249 | private Quaternion m_sitTargetOrientation = Quaternion.Identity; | 266 | private Quaternion m_sitTargetOrientation = Quaternion.Identity; |
250 | private Vector3 m_sitTargetPosition; | 267 | private Vector3 m_sitTargetPosition; |
251 | private string m_sitAnimation = "SIT"; | 268 | private string m_sitAnimation = "SIT"; |
269 | private bool m_occupied; // KF if any av is sitting on this prim | ||
252 | private string m_text = String.Empty; | 270 | private string m_text = String.Empty; |
253 | private string m_touchName = String.Empty; | 271 | private string m_touchName = String.Empty; |
254 | private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); | 272 | private UndoRedoState m_UndoRedo = null; |
255 | private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5); | ||
256 | 273 | ||
257 | private bool m_passTouches = false; | 274 | private bool m_passTouches = false; |
258 | private bool m_passCollisions = false; | 275 | private bool m_passCollisions = false; |
@@ -281,7 +298,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
281 | protected Vector3 m_lastAcceleration; | 298 | protected Vector3 m_lastAcceleration; |
282 | protected Vector3 m_lastAngularVelocity; | 299 | protected Vector3 m_lastAngularVelocity; |
283 | protected int m_lastTerseSent; | 300 | protected int m_lastTerseSent; |
284 | 301 | protected float m_buoyancy = 0.0f; | |
302 | protected Vector3 m_force; | ||
303 | protected Vector3 m_torque; | ||
304 | |||
305 | protected byte m_physicsShapeType = (byte)PhysShapeType.prim; | ||
306 | protected float m_density = 1000.0f; // in kg/m^3 | ||
307 | protected float m_gravitymod = 1.0f; | ||
308 | protected float m_friction = 0.6f; // wood | ||
309 | protected float m_bounce = 0.5f; // wood | ||
310 | |||
311 | |||
312 | protected bool m_isSelected = false; | ||
313 | |||
285 | /// <summary> | 314 | /// <summary> |
286 | /// Stores media texture data | 315 | /// Stores media texture data |
287 | /// </summary> | 316 | /// </summary> |
@@ -297,6 +326,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
297 | private UUID m_collisionSound; | 326 | private UUID m_collisionSound; |
298 | private float m_collisionSoundVolume; | 327 | private float m_collisionSoundVolume; |
299 | 328 | ||
329 | |||
330 | private SOPVehicle m_vehicle = null; | ||
331 | |||
332 | private KeyframeMotion m_keyframeMotion = null; | ||
333 | |||
334 | public KeyframeMotion KeyframeMotion | ||
335 | { | ||
336 | get; set; | ||
337 | } | ||
338 | |||
339 | |||
300 | #endregion Fields | 340 | #endregion Fields |
301 | 341 | ||
302 | // ~SceneObjectPart() | 342 | // ~SceneObjectPart() |
@@ -339,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
339 | UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, | 379 | UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, |
340 | Quaternion rotationOffset, Vector3 offsetPosition) : this() | 380 | Quaternion rotationOffset, Vector3 offsetPosition) : this() |
341 | { | 381 | { |
342 | m_name = "Primitive"; | 382 | m_name = "Object"; |
343 | 383 | ||
344 | CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); | 384 | CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); |
345 | LastOwnerID = CreatorID = OwnerID = ownerID; | 385 | LastOwnerID = CreatorID = OwnerID = ownerID; |
@@ -379,7 +419,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
379 | private uint _ownerMask = (uint)PermissionMask.All; | 419 | private uint _ownerMask = (uint)PermissionMask.All; |
380 | private uint _groupMask = (uint)PermissionMask.None; | 420 | private uint _groupMask = (uint)PermissionMask.None; |
381 | private uint _everyoneMask = (uint)PermissionMask.None; | 421 | private uint _everyoneMask = (uint)PermissionMask.None; |
382 | private uint _nextOwnerMask = (uint)PermissionMask.All; | 422 | private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer); |
383 | private PrimFlags _flags = PrimFlags.None; | 423 | private PrimFlags _flags = PrimFlags.None; |
384 | private DateTime m_expires; | 424 | private DateTime m_expires; |
385 | private DateTime m_rezzed; | 425 | private DateTime m_rezzed; |
@@ -473,12 +513,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
473 | } | 513 | } |
474 | 514 | ||
475 | /// <value> | 515 | /// <value> |
476 | /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes | 516 | /// Get the inventory list |
477 | /// </value> | 517 | /// </value> |
478 | public TaskInventoryDictionary TaskInventory | 518 | public TaskInventoryDictionary TaskInventory |
479 | { | 519 | { |
480 | get { return m_inventory.Items; } | 520 | get { |
481 | set { m_inventory.Items = value; } | 521 | return m_inventory.Items; |
522 | } | ||
523 | set { | ||
524 | m_inventory.Items = value; | ||
525 | } | ||
482 | } | 526 | } |
483 | 527 | ||
484 | /// <summary> | 528 | /// <summary> |
@@ -528,20 +572,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
528 | } | 572 | } |
529 | } | 573 | } |
530 | 574 | ||
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] | 575 | [XmlIgnore] |
546 | public bool PassTouches | 576 | public bool PassTouches |
547 | { | 577 | { |
@@ -567,6 +597,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
567 | } | 597 | } |
568 | } | 598 | } |
569 | 599 | ||
600 | public bool IsSelected | ||
601 | { | ||
602 | get { return m_isSelected; } | ||
603 | set | ||
604 | { | ||
605 | m_isSelected = value; | ||
606 | if (ParentGroup != null) | ||
607 | ParentGroup.PartSelectChanged(value); | ||
608 | } | ||
609 | } | ||
610 | |||
611 | |||
570 | public Dictionary<int, string> CollisionFilter | 612 | public Dictionary<int, string> CollisionFilter |
571 | { | 613 | { |
572 | get { return m_CollisionFilter; } | 614 | get { return m_CollisionFilter; } |
@@ -635,14 +677,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
635 | set { m_LoopSoundSlavePrims = value; } | 677 | set { m_LoopSoundSlavePrims = value; } |
636 | } | 678 | } |
637 | 679 | ||
638 | |||
639 | public Byte[] TextureAnimation | 680 | public Byte[] TextureAnimation |
640 | { | 681 | { |
641 | get { return m_TextureAnimation; } | 682 | get { return m_TextureAnimation; } |
642 | set { m_TextureAnimation = value; } | 683 | set { m_TextureAnimation = value; } |
643 | } | 684 | } |
644 | 685 | ||
645 | |||
646 | public Byte[] ParticleSystem | 686 | public Byte[] ParticleSystem |
647 | { | 687 | { |
648 | get { return m_particleSystem; } | 688 | get { return m_particleSystem; } |
@@ -679,8 +719,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
679 | { | 719 | { |
680 | // If this is a linkset, we don't want the physics engine mucking up our group position here. | 720 | // If this is a linkset, we don't want the physics engine mucking up our group position here. |
681 | PhysicsActor actor = PhysActor; | 721 | PhysicsActor actor = PhysActor; |
682 | if (actor != null && ParentID == 0) | 722 | if (ParentID == 0) |
683 | m_groupPosition = actor.Position; | 723 | { |
724 | if (actor != null) | ||
725 | m_groupPosition = actor.Position; | ||
726 | return m_groupPosition; | ||
727 | } | ||
684 | 728 | ||
685 | if (ParentGroup.IsAttachment) | 729 | if (ParentGroup.IsAttachment) |
686 | { | 730 | { |
@@ -689,12 +733,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
689 | return sp.AbsolutePosition; | 733 | return sp.AbsolutePosition; |
690 | } | 734 | } |
691 | 735 | ||
736 | // use root prim's group position. Physics may have updated it | ||
737 | if (ParentGroup.RootPart != this) | ||
738 | m_groupPosition = ParentGroup.RootPart.GroupPosition; | ||
692 | return m_groupPosition; | 739 | return m_groupPosition; |
693 | } | 740 | } |
694 | set | 741 | set |
695 | { | 742 | { |
696 | m_groupPosition = value; | 743 | m_groupPosition = value; |
697 | |||
698 | PhysicsActor actor = PhysActor; | 744 | PhysicsActor actor = PhysActor; |
699 | if (actor != null) | 745 | if (actor != null) |
700 | { | 746 | { |
@@ -720,16 +766,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
720 | m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); | 766 | m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); |
721 | } | 767 | } |
722 | } | 768 | } |
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 | } | 769 | } |
734 | } | 770 | } |
735 | 771 | ||
@@ -738,7 +774,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
738 | get { return m_offsetPosition; } | 774 | get { return m_offsetPosition; } |
739 | set | 775 | set |
740 | { | 776 | { |
741 | // StoreUndoState(); | 777 | Vector3 oldpos = m_offsetPosition; |
742 | m_offsetPosition = value; | 778 | m_offsetPosition = value; |
743 | 779 | ||
744 | if (ParentGroup != null && !ParentGroup.IsDeleted) | 780 | if (ParentGroup != null && !ParentGroup.IsDeleted) |
@@ -753,7 +789,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
753 | if (ParentGroup.Scene != null) | 789 | if (ParentGroup.Scene != null) |
754 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); | 790 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); |
755 | } | 791 | } |
792 | |||
793 | if (!m_parentGroup.m_dupeInProgress) | ||
794 | { | ||
795 | List<ScenePresence> avs = ParentGroup.GetLinkedAvatars(); | ||
796 | foreach (ScenePresence av in avs) | ||
797 | { | ||
798 | if (av.ParentID == m_localId) | ||
799 | { | ||
800 | Vector3 offset = (m_offsetPosition - oldpos); | ||
801 | av.AbsolutePosition += offset; | ||
802 | av.SendAvatarDataToAllAgents(); | ||
803 | } | ||
804 | } | ||
805 | } | ||
756 | } | 806 | } |
807 | TriggerScriptChangedEvent(Changed.POSITION); | ||
757 | } | 808 | } |
758 | } | 809 | } |
759 | 810 | ||
@@ -802,7 +853,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
802 | 853 | ||
803 | set | 854 | set |
804 | { | 855 | { |
805 | StoreUndoState(); | 856 | // StoreUndoState(); |
806 | m_rotationOffset = value; | 857 | m_rotationOffset = value; |
807 | 858 | ||
808 | PhysicsActor actor = PhysActor; | 859 | PhysicsActor actor = PhysActor; |
@@ -890,7 +941,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
890 | get | 941 | get |
891 | { | 942 | { |
892 | PhysicsActor actor = PhysActor; | 943 | PhysicsActor actor = PhysActor; |
893 | if ((actor != null) && actor.IsPhysical) | 944 | if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this) |
894 | { | 945 | { |
895 | m_angularVelocity = actor.RotationalVelocity; | 946 | m_angularVelocity = actor.RotationalVelocity; |
896 | } | 947 | } |
@@ -902,7 +953,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
902 | /// <summary></summary> | 953 | /// <summary></summary> |
903 | public Vector3 Acceleration | 954 | public Vector3 Acceleration |
904 | { | 955 | { |
905 | get { return m_acceleration; } | 956 | get |
957 | { | ||
958 | PhysicsActor actor = PhysActor; | ||
959 | if (actor != null) | ||
960 | { | ||
961 | m_acceleration = actor.Acceleration; | ||
962 | } | ||
963 | return m_acceleration; | ||
964 | } | ||
965 | |||
906 | set { m_acceleration = value; } | 966 | set { m_acceleration = value; } |
907 | } | 967 | } |
908 | 968 | ||
@@ -959,7 +1019,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
959 | public PrimitiveBaseShape Shape | 1019 | public PrimitiveBaseShape Shape |
960 | { | 1020 | { |
961 | get { return m_shape; } | 1021 | get { return m_shape; } |
962 | set { m_shape = value;} | 1022 | set |
1023 | { | ||
1024 | m_shape = value; | ||
1025 | } | ||
963 | } | 1026 | } |
964 | 1027 | ||
965 | /// <summary> | 1028 | /// <summary> |
@@ -972,7 +1035,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
972 | { | 1035 | { |
973 | if (m_shape != null) | 1036 | if (m_shape != null) |
974 | { | 1037 | { |
975 | StoreUndoState(); | ||
976 | 1038 | ||
977 | m_shape.Scale = value; | 1039 | m_shape.Scale = value; |
978 | 1040 | ||
@@ -999,6 +1061,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
999 | } | 1061 | } |
1000 | 1062 | ||
1001 | public UpdateRequired UpdateFlag { get; set; } | 1063 | public UpdateRequired UpdateFlag { get; set; } |
1064 | public bool UpdatePhysRequired { get; set; } | ||
1002 | 1065 | ||
1003 | /// <summary> | 1066 | /// <summary> |
1004 | /// Used for media on a prim. | 1067 | /// Used for media on a prim. |
@@ -1039,10 +1102,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1039 | { | 1102 | { |
1040 | get | 1103 | get |
1041 | { | 1104 | { |
1042 | if (ParentGroup.IsAttachment) | 1105 | return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset); |
1043 | return GroupPosition; | ||
1044 | |||
1045 | return m_offsetPosition + m_groupPosition; | ||
1046 | } | 1106 | } |
1047 | } | 1107 | } |
1048 | 1108 | ||
@@ -1220,6 +1280,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1220 | _flags = value; | 1280 | _flags = value; |
1221 | } | 1281 | } |
1222 | } | 1282 | } |
1283 | |||
1284 | [XmlIgnore] | ||
1285 | public bool IsOccupied // KF If an av is sittingon this prim | ||
1286 | { | ||
1287 | get { return m_occupied; } | ||
1288 | set { m_occupied = value; } | ||
1289 | } | ||
1223 | 1290 | ||
1224 | /// <summary> | 1291 | /// <summary> |
1225 | /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero | 1292 | /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero |
@@ -1279,6 +1346,316 @@ namespace OpenSim.Region.Framework.Scenes | |||
1279 | set { m_collisionSoundVolume = value; } | 1346 | set { m_collisionSoundVolume = value; } |
1280 | } | 1347 | } |
1281 | 1348 | ||
1349 | public float Buoyancy | ||
1350 | { | ||
1351 | get | ||
1352 | { | ||
1353 | if (ParentGroup.RootPart == this) | ||
1354 | return m_buoyancy; | ||
1355 | |||
1356 | return ParentGroup.RootPart.Buoyancy; | ||
1357 | } | ||
1358 | set | ||
1359 | { | ||
1360 | if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this) | ||
1361 | { | ||
1362 | ParentGroup.RootPart.Buoyancy = value; | ||
1363 | return; | ||
1364 | } | ||
1365 | m_buoyancy = value; | ||
1366 | if (PhysActor != null) | ||
1367 | PhysActor.Buoyancy = value; | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1371 | public Vector3 Force | ||
1372 | { | ||
1373 | get | ||
1374 | { | ||
1375 | if (ParentGroup.RootPart == this) | ||
1376 | return m_force; | ||
1377 | |||
1378 | return ParentGroup.RootPart.Force; | ||
1379 | } | ||
1380 | |||
1381 | set | ||
1382 | { | ||
1383 | if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this) | ||
1384 | { | ||
1385 | ParentGroup.RootPart.Force = value; | ||
1386 | return; | ||
1387 | } | ||
1388 | m_force = value; | ||
1389 | if (PhysActor != null) | ||
1390 | PhysActor.Force = value; | ||
1391 | } | ||
1392 | } | ||
1393 | |||
1394 | public Vector3 Torque | ||
1395 | { | ||
1396 | get | ||
1397 | { | ||
1398 | if (ParentGroup.RootPart == this) | ||
1399 | return m_torque; | ||
1400 | |||
1401 | return ParentGroup.RootPart.Torque; | ||
1402 | } | ||
1403 | |||
1404 | set | ||
1405 | { | ||
1406 | if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this) | ||
1407 | { | ||
1408 | ParentGroup.RootPart.Torque = value; | ||
1409 | return; | ||
1410 | } | ||
1411 | m_torque = value; | ||
1412 | if (PhysActor != null) | ||
1413 | PhysActor.Torque = value; | ||
1414 | } | ||
1415 | } | ||
1416 | |||
1417 | public byte Material | ||
1418 | { | ||
1419 | get { return (byte)m_material; } | ||
1420 | set | ||
1421 | { | ||
1422 | if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial) | ||
1423 | { | ||
1424 | bool update = false; | ||
1425 | |||
1426 | if (m_material != (Material)value) | ||
1427 | { | ||
1428 | update = true; | ||
1429 | m_material = (Material)value; | ||
1430 | } | ||
1431 | |||
1432 | if (m_friction != SOPMaterialData.friction(m_material)) | ||
1433 | { | ||
1434 | update = true; | ||
1435 | m_friction = SOPMaterialData.friction(m_material); | ||
1436 | } | ||
1437 | |||
1438 | if (m_bounce != SOPMaterialData.bounce(m_material)) | ||
1439 | { | ||
1440 | update = true; | ||
1441 | m_bounce = SOPMaterialData.bounce(m_material); | ||
1442 | } | ||
1443 | |||
1444 | if (update) | ||
1445 | { | ||
1446 | if (PhysActor != null) | ||
1447 | { | ||
1448 | PhysActor.SetMaterial((int)value); | ||
1449 | } | ||
1450 | if(ParentGroup != null) | ||
1451 | ParentGroup.HasGroupChanged = true; | ||
1452 | ScheduleFullUpdateIfNone(); | ||
1453 | UpdatePhysRequired = true; | ||
1454 | } | ||
1455 | } | ||
1456 | } | ||
1457 | } | ||
1458 | |||
1459 | // not a propriety to move to methods place later | ||
1460 | private bool HasMesh() | ||
1461 | { | ||
1462 | if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh)) | ||
1463 | return true; | ||
1464 | return false; | ||
1465 | } | ||
1466 | |||
1467 | // not a propriety to move to methods place later | ||
1468 | public byte DefaultPhysicsShapeType() | ||
1469 | { | ||
1470 | byte type; | ||
1471 | |||
1472 | if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh)) | ||
1473 | type = (byte)PhysShapeType.convex; | ||
1474 | else | ||
1475 | type = (byte)PhysShapeType.prim; | ||
1476 | |||
1477 | return type; | ||
1478 | } | ||
1479 | |||
1480 | [XmlIgnore] | ||
1481 | public bool UsesComplexCost | ||
1482 | { | ||
1483 | get | ||
1484 | { | ||
1485 | byte pst = PhysicsShapeType; | ||
1486 | if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh()) | ||
1487 | return true; | ||
1488 | return false; | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | [XmlIgnore] | ||
1493 | public float PhysicsCost | ||
1494 | { | ||
1495 | get | ||
1496 | { | ||
1497 | if(PhysicsShapeType == (byte)PhysShapeType.none) | ||
1498 | return 0; | ||
1499 | |||
1500 | float cost = 0.1f; | ||
1501 | if (PhysActor != null) | ||
1502 | // cost += PhysActor.Cost; | ||
1503 | |||
1504 | if ((Flags & PrimFlags.Physics) != 0) | ||
1505 | cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3 | ||
1506 | return cost; | ||
1507 | } | ||
1508 | } | ||
1509 | |||
1510 | [XmlIgnore] | ||
1511 | public float StreamingCost | ||
1512 | { | ||
1513 | get | ||
1514 | { | ||
1515 | |||
1516 | |||
1517 | return 0.1f; | ||
1518 | } | ||
1519 | } | ||
1520 | |||
1521 | [XmlIgnore] | ||
1522 | public float SimulationCost | ||
1523 | { | ||
1524 | get | ||
1525 | { | ||
1526 | // ignoring scripts. Don't like considering them for this | ||
1527 | if((Flags & PrimFlags.Physics) != 0) | ||
1528 | return 1.0f; | ||
1529 | |||
1530 | return 0.5f; | ||
1531 | } | ||
1532 | } | ||
1533 | |||
1534 | public byte PhysicsShapeType | ||
1535 | { | ||
1536 | get { return m_physicsShapeType; } | ||
1537 | set | ||
1538 | { | ||
1539 | byte oldv = m_physicsShapeType; | ||
1540 | |||
1541 | if (value >= 0 && value <= (byte)PhysShapeType.convex) | ||
1542 | { | ||
1543 | if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this) | ||
1544 | m_physicsShapeType = DefaultPhysicsShapeType(); | ||
1545 | else | ||
1546 | m_physicsShapeType = value; | ||
1547 | } | ||
1548 | else | ||
1549 | m_physicsShapeType = DefaultPhysicsShapeType(); | ||
1550 | |||
1551 | if (m_physicsShapeType != oldv && ParentGroup != null) | ||
1552 | { | ||
1553 | if (m_physicsShapeType == (byte)PhysShapeType.none) | ||
1554 | { | ||
1555 | if (PhysActor != null) | ||
1556 | { | ||
1557 | Velocity = new Vector3(0, 0, 0); | ||
1558 | Acceleration = new Vector3(0, 0, 0); | ||
1559 | if (ParentGroup.RootPart == this) | ||
1560 | AngularVelocity = new Vector3(0, 0, 0); | ||
1561 | ParentGroup.Scene.RemovePhysicalPrim(1); | ||
1562 | RemoveFromPhysics(); | ||
1563 | } | ||
1564 | } | ||
1565 | else if (PhysActor == null) | ||
1566 | ApplyPhysics((uint)Flags, VolumeDetectActive, false); | ||
1567 | else | ||
1568 | { | ||
1569 | PhysActor.PhysicsShapeType = m_physicsShapeType; | ||
1570 | if (Shape.SculptEntry) | ||
1571 | CheckSculptAndLoad(); | ||
1572 | } | ||
1573 | |||
1574 | if (ParentGroup != null) | ||
1575 | ParentGroup.HasGroupChanged = true; | ||
1576 | } | ||
1577 | |||
1578 | if (m_physicsShapeType != value) | ||
1579 | { | ||
1580 | UpdatePhysRequired = true; | ||
1581 | } | ||
1582 | } | ||
1583 | } | ||
1584 | |||
1585 | public float Density // in kg/m^3 | ||
1586 | { | ||
1587 | get { return m_density; } | ||
1588 | set | ||
1589 | { | ||
1590 | if (value >=1 && value <= 22587.0) | ||
1591 | { | ||
1592 | m_density = value; | ||
1593 | UpdatePhysRequired = true; | ||
1594 | } | ||
1595 | |||
1596 | ScheduleFullUpdateIfNone(); | ||
1597 | |||
1598 | if (ParentGroup != null) | ||
1599 | ParentGroup.HasGroupChanged = true; | ||
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | public float GravityModifier | ||
1604 | { | ||
1605 | get { return m_gravitymod; } | ||
1606 | set | ||
1607 | { | ||
1608 | if( value >= -1 && value <=28.0f) | ||
1609 | { | ||
1610 | m_gravitymod = value; | ||
1611 | UpdatePhysRequired = true; | ||
1612 | } | ||
1613 | |||
1614 | ScheduleFullUpdateIfNone(); | ||
1615 | |||
1616 | if (ParentGroup != null) | ||
1617 | ParentGroup.HasGroupChanged = true; | ||
1618 | |||
1619 | } | ||
1620 | } | ||
1621 | |||
1622 | public float Friction | ||
1623 | { | ||
1624 | get { return m_friction; } | ||
1625 | set | ||
1626 | { | ||
1627 | if (value >= 0 && value <= 255.0f) | ||
1628 | { | ||
1629 | m_friction = value; | ||
1630 | UpdatePhysRequired = true; | ||
1631 | } | ||
1632 | |||
1633 | ScheduleFullUpdateIfNone(); | ||
1634 | |||
1635 | if (ParentGroup != null) | ||
1636 | ParentGroup.HasGroupChanged = true; | ||
1637 | } | ||
1638 | } | ||
1639 | |||
1640 | public float Bounciness | ||
1641 | { | ||
1642 | get { return m_bounce; } | ||
1643 | set | ||
1644 | { | ||
1645 | if (value >= 0 && value <= 1.0f) | ||
1646 | { | ||
1647 | m_bounce = value; | ||
1648 | UpdatePhysRequired = true; | ||
1649 | } | ||
1650 | |||
1651 | ScheduleFullUpdateIfNone(); | ||
1652 | |||
1653 | if (ParentGroup != null) | ||
1654 | ParentGroup.HasGroupChanged = true; | ||
1655 | } | ||
1656 | } | ||
1657 | |||
1658 | |||
1282 | #endregion Public Properties with only Get | 1659 | #endregion Public Properties with only Get |
1283 | 1660 | ||
1284 | private uint ApplyMask(uint val, bool set, uint mask) | 1661 | private uint ApplyMask(uint val, bool set, uint mask) |
@@ -1444,7 +1821,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1444 | impulse = newimpulse; | 1821 | impulse = newimpulse; |
1445 | } | 1822 | } |
1446 | 1823 | ||
1447 | ParentGroup.applyAngularImpulse(impulse); | 1824 | ParentGroup.ApplyAngularImpulse(impulse); |
1448 | } | 1825 | } |
1449 | 1826 | ||
1450 | /// <summary> | 1827 | /// <summary> |
@@ -1454,20 +1831,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1454 | /// </summary> | 1831 | /// </summary> |
1455 | /// <param name="impulsei">Vector force</param> | 1832 | /// <param name="impulsei">Vector force</param> |
1456 | /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> | 1833 | /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> |
1457 | public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) | 1834 | |
1835 | // this is actualy Set Torque.. keeping naming so not to edit lslapi also | ||
1836 | public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF) | ||
1458 | { | 1837 | { |
1459 | Vector3 impulse = impulsei; | 1838 | Vector3 torque = torquei; |
1460 | 1839 | ||
1461 | if (localGlobalTF) | 1840 | if (localGlobalTF) |
1462 | { | 1841 | { |
1842 | /* | ||
1463 | Quaternion grot = GetWorldRotation(); | 1843 | Quaternion grot = GetWorldRotation(); |
1464 | Quaternion AXgrot = grot; | 1844 | Quaternion AXgrot = grot; |
1465 | Vector3 AXimpulsei = impulsei; | 1845 | Vector3 AXimpulsei = impulsei; |
1466 | Vector3 newimpulse = AXimpulsei * AXgrot; | 1846 | Vector3 newimpulse = AXimpulsei * AXgrot; |
1467 | impulse = newimpulse; | 1847 | */ |
1848 | torque *= GetWorldRotation(); | ||
1468 | } | 1849 | } |
1469 | 1850 | ||
1470 | ParentGroup.setAngularImpulse(impulse); | 1851 | Torque = torque; |
1471 | } | 1852 | } |
1472 | 1853 | ||
1473 | /// <summary> | 1854 | /// <summary> |
@@ -1475,17 +1856,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
1475 | /// </summary> | 1856 | /// </summary> |
1476 | /// <param name="rootObjectFlags"></param> | 1857 | /// <param name="rootObjectFlags"></param> |
1477 | /// <param name="VolumeDetectActive"></param> | 1858 | /// <param name="VolumeDetectActive"></param> |
1478 | public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) | 1859 | /// <param name="building"></param> |
1860 | |||
1861 | public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building) | ||
1479 | { | 1862 | { |
1863 | VolumeDetectActive = _VolumeDetectActive; | ||
1864 | |||
1480 | if (!ParentGroup.Scene.CollidablePrims) | 1865 | if (!ParentGroup.Scene.CollidablePrims) |
1481 | return; | 1866 | return; |
1482 | 1867 | ||
1483 | // m_log.DebugFormat( | 1868 | if (PhysicsShapeType == (byte)PhysShapeType.none) |
1484 | // "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", | 1869 | return; |
1485 | // Name, LocalId, UUID, m_physicalPrim); | 1870 | |
1871 | bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0; | ||
1872 | bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0; | ||
1486 | 1873 | ||
1487 | bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; | 1874 | if (_VolumeDetectActive) |
1488 | bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; | 1875 | isPhantom = true; |
1489 | 1876 | ||
1490 | if (IsJoint()) | 1877 | if (IsJoint()) |
1491 | { | 1878 | { |
@@ -1493,22 +1880,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1493 | } | 1880 | } |
1494 | else | 1881 | else |
1495 | { | 1882 | { |
1496 | // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored | 1883 | if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment |
1497 | if (VolumeDetectActive) | 1884 | && !(Shape.PathCurve == (byte)Extrusion.Flexible)) |
1498 | isPhantom = false; | 1885 | AddToPhysics(isPhysical, isPhantom, building, isPhysical); |
1499 | 1886 | else | |
1500 | // 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 | 1887 | PhysActor = null; // just to be sure |
1501 | // or flexible | ||
1502 | if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) | ||
1503 | { | ||
1504 | // Added clarification.. since A rigid body is an object that you can kick around, etc. | ||
1505 | bool rigidBody = isPhysical && !isPhantom; | ||
1506 | |||
1507 | PhysicsActor pa = AddToPhysics(rigidBody); | ||
1508 | |||
1509 | if (pa != null) | ||
1510 | pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0); | ||
1511 | } | ||
1512 | } | 1888 | } |
1513 | } | 1889 | } |
1514 | 1890 | ||
@@ -1560,6 +1936,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1560 | dupe.Category = Category; | 1936 | dupe.Category = Category; |
1561 | dupe.m_rezzed = m_rezzed; | 1937 | dupe.m_rezzed = m_rezzed; |
1562 | 1938 | ||
1939 | dupe.m_UndoRedo = null; | ||
1940 | dupe.m_isSelected = false; | ||
1941 | |||
1942 | dupe.IgnoreUndoUpdate = false; | ||
1943 | dupe.Undoing = false; | ||
1944 | |||
1563 | dupe.m_inventory = new SceneObjectPartInventory(dupe); | 1945 | dupe.m_inventory = new SceneObjectPartInventory(dupe); |
1564 | dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); | 1946 | dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); |
1565 | 1947 | ||
@@ -1575,6 +1957,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1575 | 1957 | ||
1576 | // Move afterwards ResetIDs as it clears the localID | 1958 | // Move afterwards ResetIDs as it clears the localID |
1577 | dupe.LocalId = localID; | 1959 | dupe.LocalId = localID; |
1960 | |||
1578 | // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. | 1961 | // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. |
1579 | dupe.LastOwnerID = OwnerID; | 1962 | dupe.LastOwnerID = OwnerID; |
1580 | 1963 | ||
@@ -1594,6 +1977,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1594 | dupe.DoPhysicsPropertyUpdate(UsePhysics, true); | 1977 | dupe.DoPhysicsPropertyUpdate(UsePhysics, true); |
1595 | } | 1978 | } |
1596 | 1979 | ||
1980 | if (dupe.PhysActor != null) | ||
1981 | dupe.PhysActor.LocalID = localID; | ||
1982 | |||
1597 | ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); | 1983 | ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); |
1598 | 1984 | ||
1599 | // m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); | 1985 | // m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); |
@@ -1713,6 +2099,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1713 | 2099 | ||
1714 | /// <summary> | 2100 | /// <summary> |
1715 | /// Do a physics propery update for this part. | 2101 | /// Do a physics propery update for this part. |
2102 | /// now also updates phantom and volume detector | ||
1716 | /// </summary> | 2103 | /// </summary> |
1717 | /// <param name="UsePhysics"></param> | 2104 | /// <param name="UsePhysics"></param> |
1718 | /// <param name="isNew"></param> | 2105 | /// <param name="isNew"></param> |
@@ -1738,61 +2125,69 @@ namespace OpenSim.Region.Framework.Scenes | |||
1738 | { | 2125 | { |
1739 | if (pa.IsPhysical) // implies UsePhysics==false for this block | 2126 | if (pa.IsPhysical) // implies UsePhysics==false for this block |
1740 | { | 2127 | { |
1741 | if (!isNew) | 2128 | if (!isNew) // implies UsePhysics==false for this block |
2129 | { | ||
1742 | ParentGroup.Scene.RemovePhysicalPrim(1); | 2130 | ParentGroup.Scene.RemovePhysicalPrim(1); |
1743 | 2131 | ||
1744 | pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; | 2132 | Velocity = new Vector3(0, 0, 0); |
1745 | pa.OnOutOfBounds -= PhysicsOutOfBounds; | 2133 | Acceleration = new Vector3(0, 0, 0); |
1746 | pa.delink(); | 2134 | if (ParentGroup.RootPart == this) |
2135 | AngularVelocity = new Vector3(0, 0, 0); | ||
1747 | 2136 | ||
1748 | if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) | 2137 | if (pa.Phantom && !VolumeDetectActive) |
1749 | { | 2138 | { |
1750 | // destroy all joints connected to this now deactivated body | 2139 | RemoveFromPhysics(); |
1751 | ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); | 2140 | return; |
1752 | } | 2141 | } |
1753 | 2142 | ||
1754 | // stop client-side interpolation of all joint proxy objects that have just been deleted | 2143 | pa.IsPhysical = UsePhysics; |
1755 | // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, | 2144 | pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; |
1756 | // which stops client-side interpolation of deactivated joint proxy objects. | 2145 | pa.OnOutOfBounds -= PhysicsOutOfBounds; |
2146 | pa.delink(); | ||
2147 | if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | ||
2148 | { | ||
2149 | // destroy all joints connected to this now deactivated body | ||
2150 | ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); | ||
2151 | } | ||
2152 | } | ||
1757 | } | 2153 | } |
1758 | 2154 | ||
1759 | if (!UsePhysics && !isNew) | 2155 | if (pa.IsPhysical != UsePhysics) |
1760 | { | 2156 | pa.IsPhysical = UsePhysics; |
1761 | // reset velocity to 0 on physics switch-off. Without that, the client thinks the | ||
1762 | // prim still has velocity and continues to interpolate its position along the old | ||
1763 | // velocity-vector. | ||
1764 | Velocity = new Vector3(0, 0, 0); | ||
1765 | Acceleration = new Vector3(0, 0, 0); | ||
1766 | AngularVelocity = new Vector3(0, 0, 0); | ||
1767 | //RotationalVelocity = new Vector3(0, 0, 0); | ||
1768 | } | ||
1769 | 2157 | ||
1770 | pa.IsPhysical = UsePhysics; | 2158 | if (UsePhysics) |
2159 | { | ||
2160 | if (ParentGroup.RootPart.KeyframeMotion != null) | ||
2161 | ParentGroup.RootPart.KeyframeMotion.Stop(); | ||
2162 | ParentGroup.RootPart.KeyframeMotion = null; | ||
2163 | ParentGroup.Scene.AddPhysicalPrim(1); | ||
1771 | 2164 | ||
1772 | // If we're not what we're supposed to be in the physics scene, recreate ourselves. | 2165 | PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; |
1773 | //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); | 2166 | PhysActor.OnOutOfBounds += PhysicsOutOfBounds; |
1774 | /// that's not wholesome. Had to make Scene public | ||
1775 | //PhysActor = null; | ||
1776 | 2167 | ||
1777 | if ((Flags & PrimFlags.Phantom) == 0) | 2168 | if (ParentID != 0 && ParentID != LocalId) |
1778 | { | ||
1779 | if (UsePhysics) | ||
1780 | { | 2169 | { |
1781 | ParentGroup.Scene.AddPhysicalPrim(1); | 2170 | PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; |
1782 | 2171 | ||
1783 | pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; | 2172 | if (parentPa != null) |
1784 | pa.OnOutOfBounds += PhysicsOutOfBounds; | ||
1785 | if (ParentID != 0 && ParentID != LocalId) | ||
1786 | { | 2173 | { |
1787 | PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; | 2174 | pa.link(parentPa); |
1788 | |||
1789 | if (parentPa != null) | ||
1790 | { | ||
1791 | pa.link(parentPa); | ||
1792 | } | ||
1793 | } | 2175 | } |
1794 | } | 2176 | } |
1795 | } | 2177 | } |
2178 | } | ||
2179 | |||
2180 | bool phan = ((Flags & PrimFlags.Phantom) != 0); | ||
2181 | if (pa.Phantom != phan) | ||
2182 | pa.Phantom = phan; | ||
2183 | |||
2184 | // some engines dont' have this check still | ||
2185 | // if (VolumeDetectActive != pa.IsVolumeDtc) | ||
2186 | { | ||
2187 | if (VolumeDetectActive) | ||
2188 | pa.SetVolumeDetect(1); | ||
2189 | else | ||
2190 | pa.SetVolumeDetect(0); | ||
1796 | } | 2191 | } |
1797 | 2192 | ||
1798 | // If this part is a sculpt then delay the physics update until we've asynchronously loaded the | 2193 | // If this part is a sculpt then delay the physics update until we've asynchronously loaded the |
@@ -1911,12 +2306,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
1911 | 2306 | ||
1912 | public Vector3 GetGeometricCenter() | 2307 | public Vector3 GetGeometricCenter() |
1913 | { | 2308 | { |
1914 | PhysicsActor pa = PhysActor; | 2309 | // this is not real geometric center but a average of positions relative to root prim acording to |
1915 | 2310 | // http://wiki.secondlife.com/wiki/llGetGeometricCenter | |
1916 | if (pa != null) | 2311 | // ignoring tortured prims details since sl also seems to ignore |
1917 | return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); | 2312 | // so no real use in doing it on physics |
1918 | else | 2313 | if (ParentGroup.IsDeleted) |
1919 | return new Vector3(0, 0, 0); | 2314 | return new Vector3(0, 0, 0); |
2315 | |||
2316 | return ParentGroup.GetGeometricCenter(); | ||
2317 | |||
2318 | /* | ||
2319 | PhysicsActor pa = PhysActor; | ||
2320 | |||
2321 | if (pa != null) | ||
2322 | { | ||
2323 | Vector3 vtmp = pa.CenterOfMass; | ||
2324 | return vtmp; | ||
2325 | } | ||
2326 | else | ||
2327 | return new Vector3(0, 0, 0); | ||
2328 | */ | ||
1920 | } | 2329 | } |
1921 | 2330 | ||
1922 | public float GetMass() | 2331 | public float GetMass() |
@@ -1929,14 +2338,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
1929 | return 0; | 2338 | return 0; |
1930 | } | 2339 | } |
1931 | 2340 | ||
1932 | public Vector3 GetForce() | 2341 | public Vector3 GetCenterOfMass() |
1933 | { | 2342 | { |
2343 | if (ParentGroup.RootPart == this) | ||
2344 | { | ||
2345 | if (ParentGroup.IsDeleted) | ||
2346 | return AbsolutePosition; | ||
2347 | return ParentGroup.GetCenterOfMass(); | ||
2348 | } | ||
2349 | |||
1934 | PhysicsActor pa = PhysActor; | 2350 | PhysicsActor pa = PhysActor; |
1935 | 2351 | ||
1936 | if (pa != null) | 2352 | if (pa != null) |
1937 | return pa.Force; | 2353 | { |
2354 | Vector3 tmp = pa.CenterOfMass; | ||
2355 | return tmp; | ||
2356 | } | ||
1938 | else | 2357 | else |
1939 | return Vector3.Zero; | 2358 | return AbsolutePosition; |
2359 | } | ||
2360 | |||
2361 | public Vector3 GetPartCenterOfMass() | ||
2362 | { | ||
2363 | PhysicsActor pa = PhysActor; | ||
2364 | |||
2365 | if (pa != null) | ||
2366 | { | ||
2367 | Vector3 tmp = pa.CenterOfMass; | ||
2368 | return tmp; | ||
2369 | } | ||
2370 | else | ||
2371 | return AbsolutePosition; | ||
2372 | } | ||
2373 | |||
2374 | |||
2375 | public Vector3 GetForce() | ||
2376 | { | ||
2377 | return Force; | ||
1940 | } | 2378 | } |
1941 | 2379 | ||
1942 | /// <summary> | 2380 | /// <summary> |
@@ -2228,9 +2666,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2228 | Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); | 2666 | Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); |
2229 | 2667 | ||
2230 | if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) | 2668 | if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) |
2231 | | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) | 2669 | || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) |
2232 | | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) | 2670 | || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) |
2233 | | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) | 2671 | || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) |
2234 | { | 2672 | { |
2235 | ParentGroup.AbsolutePosition = newpos; | 2673 | ParentGroup.AbsolutePosition = newpos; |
2236 | return; | 2674 | return; |
@@ -2252,17 +2690,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2252 | //Trys to fetch sound id from prim's inventory. | 2690 | //Trys to fetch sound id from prim's inventory. |
2253 | //Prim's inventory doesn't support non script items yet | 2691 | //Prim's inventory doesn't support non script items yet |
2254 | 2692 | ||
2255 | lock (TaskInventory) | 2693 | TaskInventory.LockItemsForRead(true); |
2694 | |||
2695 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) | ||
2256 | { | 2696 | { |
2257 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) | 2697 | if (item.Value.Name == sound) |
2258 | { | 2698 | { |
2259 | if (item.Value.Name == sound) | 2699 | soundID = item.Value.ItemID; |
2260 | { | 2700 | break; |
2261 | soundID = item.Value.ItemID; | ||
2262 | break; | ||
2263 | } | ||
2264 | } | 2701 | } |
2265 | } | 2702 | } |
2703 | |||
2704 | TaskInventory.LockItemsForRead(false); | ||
2266 | } | 2705 | } |
2267 | 2706 | ||
2268 | ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) | 2707 | ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) |
@@ -2385,6 +2824,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
2385 | APIDTarget = Quaternion.Identity; | 2824 | APIDTarget = Quaternion.Identity; |
2386 | } | 2825 | } |
2387 | 2826 | ||
2827 | |||
2828 | |||
2829 | public void ScheduleFullUpdateIfNone() | ||
2830 | { | ||
2831 | if (ParentGroup == null) | ||
2832 | return; | ||
2833 | |||
2834 | // ??? ParentGroup.HasGroupChanged = true; | ||
2835 | |||
2836 | if (UpdateFlag != UpdateRequired.FULL) | ||
2837 | ScheduleFullUpdate(); | ||
2838 | } | ||
2839 | |||
2388 | /// <summary> | 2840 | /// <summary> |
2389 | /// Schedules this prim for a full update | 2841 | /// Schedules this prim for a full update |
2390 | /// </summary> | 2842 | /// </summary> |
@@ -2586,8 +3038,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2586 | { | 3038 | { |
2587 | const float ROTATION_TOLERANCE = 0.01f; | 3039 | const float ROTATION_TOLERANCE = 0.01f; |
2588 | const float VELOCITY_TOLERANCE = 0.001f; | 3040 | const float VELOCITY_TOLERANCE = 0.001f; |
2589 | const float POSITION_TOLERANCE = 0.05f; | 3041 | const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary |
2590 | const int TIME_MS_TOLERANCE = 3000; | 3042 | const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds. |
2591 | 3043 | ||
2592 | switch (UpdateFlag) | 3044 | switch (UpdateFlag) |
2593 | { | 3045 | { |
@@ -2649,17 +3101,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
2649 | if (!UUID.TryParse(sound, out soundID)) | 3101 | if (!UUID.TryParse(sound, out soundID)) |
2650 | { | 3102 | { |
2651 | // search sound file from inventory | 3103 | // search sound file from inventory |
2652 | lock (TaskInventory) | 3104 | TaskInventory.LockItemsForRead(true); |
3105 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) | ||
2653 | { | 3106 | { |
2654 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) | 3107 | if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) |
2655 | { | 3108 | { |
2656 | if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) | 3109 | soundID = item.Value.ItemID; |
2657 | { | 3110 | break; |
2658 | soundID = item.Value.ItemID; | ||
2659 | break; | ||
2660 | } | ||
2661 | } | 3111 | } |
2662 | } | 3112 | } |
3113 | TaskInventory.LockItemsForRead(false); | ||
2663 | } | 3114 | } |
2664 | 3115 | ||
2665 | if (soundID == UUID.Zero) | 3116 | if (soundID == UUID.Zero) |
@@ -2744,10 +3195,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2744 | 3195 | ||
2745 | public void SetBuoyancy(float fvalue) | 3196 | public void SetBuoyancy(float fvalue) |
2746 | { | 3197 | { |
2747 | PhysicsActor pa = PhysActor; | 3198 | Buoyancy = fvalue; |
2748 | 3199 | /* | |
2749 | if (pa != null) | 3200 | if (PhysActor != null) |
2750 | pa.Buoyancy = fvalue; | 3201 | { |
3202 | PhysActor.Buoyancy = fvalue; | ||
3203 | } | ||
3204 | */ | ||
2751 | } | 3205 | } |
2752 | 3206 | ||
2753 | public void SetDieAtEdge(bool p) | 3207 | public void SetDieAtEdge(bool p) |
@@ -2763,47 +3217,111 @@ namespace OpenSim.Region.Framework.Scenes | |||
2763 | PhysicsActor pa = PhysActor; | 3217 | PhysicsActor pa = PhysActor; |
2764 | 3218 | ||
2765 | if (pa != null) | 3219 | if (pa != null) |
2766 | pa.FloatOnWater = floatYN == 1; | 3220 | pa.FloatOnWater = (floatYN == 1); |
2767 | } | 3221 | } |
2768 | 3222 | ||
2769 | public void SetForce(Vector3 force) | 3223 | public void SetForce(Vector3 force) |
2770 | { | 3224 | { |
2771 | PhysicsActor pa = PhysActor; | 3225 | Force = force; |
3226 | } | ||
2772 | 3227 | ||
2773 | if (pa != null) | 3228 | public SOPVehicle sopVehicle |
2774 | pa.Force = force; | 3229 | { |
3230 | get | ||
3231 | { | ||
3232 | return m_vehicle; | ||
3233 | } | ||
3234 | set | ||
3235 | { | ||
3236 | m_vehicle = value; | ||
3237 | } | ||
3238 | } | ||
3239 | |||
3240 | |||
3241 | public int VehicleType | ||
3242 | { | ||
3243 | get | ||
3244 | { | ||
3245 | if (m_vehicle == null) | ||
3246 | return (int)Vehicle.TYPE_NONE; | ||
3247 | else | ||
3248 | return (int)m_vehicle.Type; | ||
3249 | } | ||
3250 | set | ||
3251 | { | ||
3252 | SetVehicleType(value); | ||
3253 | } | ||
2775 | } | 3254 | } |
2776 | 3255 | ||
2777 | public void SetVehicleType(int type) | 3256 | public void SetVehicleType(int type) |
2778 | { | 3257 | { |
2779 | PhysicsActor pa = PhysActor; | 3258 | m_vehicle = null; |
3259 | |||
3260 | if (type == (int)Vehicle.TYPE_NONE) | ||
3261 | { | ||
3262 | if (_parentID ==0 && PhysActor != null) | ||
3263 | PhysActor.VehicleType = (int)Vehicle.TYPE_NONE; | ||
3264 | return; | ||
3265 | } | ||
3266 | m_vehicle = new SOPVehicle(); | ||
3267 | m_vehicle.ProcessTypeChange((Vehicle)type); | ||
3268 | { | ||
3269 | if (_parentID ==0 && PhysActor != null) | ||
3270 | PhysActor.VehicleType = type; | ||
3271 | return; | ||
3272 | } | ||
3273 | } | ||
2780 | 3274 | ||
2781 | if (pa != null) | 3275 | public void SetVehicleFlags(int param, bool remove) |
2782 | pa.VehicleType = type; | 3276 | { |
3277 | if (m_vehicle == null) | ||
3278 | return; | ||
3279 | |||
3280 | m_vehicle.ProcessVehicleFlags(param, remove); | ||
3281 | |||
3282 | if (_parentID ==0 && PhysActor != null) | ||
3283 | { | ||
3284 | PhysActor.VehicleFlags(param, remove); | ||
3285 | } | ||
2783 | } | 3286 | } |
2784 | 3287 | ||
2785 | public void SetVehicleFloatParam(int param, float value) | 3288 | public void SetVehicleFloatParam(int param, float value) |
2786 | { | 3289 | { |
2787 | PhysicsActor pa = PhysActor; | 3290 | if (m_vehicle == null) |
3291 | return; | ||
2788 | 3292 | ||
2789 | if (pa != null) | 3293 | m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value); |
2790 | pa.VehicleFloatParam(param, value); | 3294 | |
3295 | if (_parentID == 0 && PhysActor != null) | ||
3296 | { | ||
3297 | PhysActor.VehicleFloatParam(param, value); | ||
3298 | } | ||
2791 | } | 3299 | } |
2792 | 3300 | ||
2793 | public void SetVehicleVectorParam(int param, Vector3 value) | 3301 | public void SetVehicleVectorParam(int param, Vector3 value) |
2794 | { | 3302 | { |
2795 | PhysicsActor pa = PhysActor; | 3303 | if (m_vehicle == null) |
3304 | return; | ||
2796 | 3305 | ||
2797 | if (pa != null) | 3306 | m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value); |
2798 | pa.VehicleVectorParam(param, value); | 3307 | |
3308 | if (_parentID == 0 && PhysActor != null) | ||
3309 | { | ||
3310 | PhysActor.VehicleVectorParam(param, value); | ||
3311 | } | ||
2799 | } | 3312 | } |
2800 | 3313 | ||
2801 | public void SetVehicleRotationParam(int param, Quaternion rotation) | 3314 | public void SetVehicleRotationParam(int param, Quaternion rotation) |
2802 | { | 3315 | { |
2803 | PhysicsActor pa = PhysActor; | 3316 | if (m_vehicle == null) |
3317 | return; | ||
2804 | 3318 | ||
2805 | if (pa != null) | 3319 | m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); |
2806 | pa.VehicleRotationParam(param, rotation); | 3320 | |
3321 | if (_parentID == 0 && PhysActor != null) | ||
3322 | { | ||
3323 | PhysActor.VehicleRotationParam(param, rotation); | ||
3324 | } | ||
2807 | } | 3325 | } |
2808 | 3326 | ||
2809 | /// <summary> | 3327 | /// <summary> |
@@ -2987,14 +3505,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2987 | hasProfileCut = hasDimple; // is it the same thing? | 3505 | hasProfileCut = hasDimple; // is it the same thing? |
2988 | } | 3506 | } |
2989 | 3507 | ||
2990 | public void SetVehicleFlags(int param, bool remove) | ||
2991 | { | ||
2992 | PhysicsActor pa = PhysActor; | ||
2993 | |||
2994 | if (pa != null) | ||
2995 | pa.VehicleFlags(param, remove); | ||
2996 | } | ||
2997 | |||
2998 | public void SetGroup(UUID groupID, IClientAPI client) | 3508 | public void SetGroup(UUID groupID, IClientAPI client) |
2999 | { | 3509 | { |
3000 | // Scene.AddNewPrims() calls with client == null so can't use this. | 3510 | // Scene.AddNewPrims() calls with client == null so can't use this. |
@@ -3098,68 +3608,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
3098 | //ParentGroup.ScheduleGroupForFullUpdate(); | 3608 | //ParentGroup.ScheduleGroupForFullUpdate(); |
3099 | } | 3609 | } |
3100 | 3610 | ||
3101 | public void StoreUndoState() | 3611 | public void StoreUndoState(ObjectChangeType change) |
3102 | { | 3612 | { |
3103 | StoreUndoState(false); | 3613 | if (m_UndoRedo == null) |
3104 | } | 3614 | m_UndoRedo = new UndoRedoState(5); |
3105 | 3615 | ||
3106 | public void StoreUndoState(bool forGroup) | 3616 | lock (m_UndoRedo) |
3107 | { | ||
3108 | if (!Undoing) | ||
3109 | { | 3617 | { |
3110 | if (!IgnoreUndoUpdate) | 3618 | if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended |
3111 | { | 3619 | { |
3112 | if (ParentGroup != null) | 3620 | m_UndoRedo.StoreUndo(this, change); |
3113 | { | ||
3114 | lock (m_undo) | ||
3115 | { | ||
3116 | if (m_undo.Count > 0) | ||
3117 | { | ||
3118 | UndoState last = m_undo.Peek(); | ||
3119 | if (last != null) | ||
3120 | { | ||
3121 | // TODO: May need to fix for group comparison | ||
3122 | if (last.Compare(this)) | ||
3123 | { | ||
3124 | // m_log.DebugFormat( | ||
3125 | // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", | ||
3126 | // Name, LocalId, m_undo.Count); | ||
3127 | |||
3128 | return; | ||
3129 | } | ||
3130 | } | ||
3131 | } | ||
3132 | |||
3133 | // m_log.DebugFormat( | ||
3134 | // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", | ||
3135 | // Name, LocalId, forGroup, m_undo.Count); | ||
3136 | |||
3137 | if (ParentGroup.GetSceneMaxUndo() > 0) | ||
3138 | { | ||
3139 | UndoState nUndo = new UndoState(this, forGroup); | ||
3140 | |||
3141 | m_undo.Push(nUndo); | ||
3142 | |||
3143 | if (m_redo.Count > 0) | ||
3144 | m_redo.Clear(); | ||
3145 | |||
3146 | // m_log.DebugFormat( | ||
3147 | // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", | ||
3148 | // Name, LocalId, forGroup, m_undo.Count); | ||
3149 | } | ||
3150 | } | ||
3151 | } | ||
3152 | } | 3621 | } |
3153 | // else | ||
3154 | // { | ||
3155 | // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); | ||
3156 | // } | ||
3157 | } | 3622 | } |
3158 | // else | ||
3159 | // { | ||
3160 | // m_log.DebugFormat( | ||
3161 | // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); | ||
3162 | // } | ||
3163 | } | 3623 | } |
3164 | 3624 | ||
3165 | /// <summary> | 3625 | /// <summary> |
@@ -3169,84 +3629,46 @@ namespace OpenSim.Region.Framework.Scenes | |||
3169 | { | 3629 | { |
3170 | get | 3630 | get |
3171 | { | 3631 | { |
3172 | lock (m_undo) | 3632 | if (m_UndoRedo == null) |
3173 | return m_undo.Count; | 3633 | return 0; |
3634 | return m_UndoRedo.Count; | ||
3174 | } | 3635 | } |
3175 | } | 3636 | } |
3176 | 3637 | ||
3177 | public void Undo() | 3638 | public void Undo() |
3178 | { | 3639 | { |
3179 | lock (m_undo) | 3640 | if (m_UndoRedo == null || Undoing || ParentGroup == null) |
3180 | { | 3641 | return; |
3181 | // m_log.DebugFormat( | ||
3182 | // "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}", | ||
3183 | // Name, LocalId, m_undo.Count); | ||
3184 | |||
3185 | if (m_undo.Count > 0) | ||
3186 | { | ||
3187 | UndoState goback = m_undo.Pop(); | ||
3188 | |||
3189 | if (goback != null) | ||
3190 | { | ||
3191 | UndoState nUndo = null; | ||
3192 | |||
3193 | if (ParentGroup.GetSceneMaxUndo() > 0) | ||
3194 | { | ||
3195 | nUndo = new UndoState(this, goback.ForGroup); | ||
3196 | } | ||
3197 | |||
3198 | goback.PlaybackState(this); | ||
3199 | |||
3200 | if (nUndo != null) | ||
3201 | m_redo.Push(nUndo); | ||
3202 | } | ||
3203 | } | ||
3204 | 3642 | ||
3205 | // m_log.DebugFormat( | 3643 | lock (m_UndoRedo) |
3206 | // "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", | 3644 | { |
3207 | // Name, LocalId, m_undo.Count); | 3645 | Undoing = true; |
3646 | m_UndoRedo.Undo(this); | ||
3647 | Undoing = false; | ||
3208 | } | 3648 | } |
3209 | } | 3649 | } |
3210 | 3650 | ||
3211 | public void Redo() | 3651 | public void Redo() |
3212 | { | 3652 | { |
3213 | lock (m_undo) | 3653 | if (m_UndoRedo == null || Undoing || ParentGroup == null) |
3214 | { | 3654 | return; |
3215 | // m_log.DebugFormat( | ||
3216 | // "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", | ||
3217 | // Name, LocalId, m_redo.Count); | ||
3218 | |||
3219 | if (m_redo.Count > 0) | ||
3220 | { | ||
3221 | UndoState gofwd = m_redo.Pop(); | ||
3222 | |||
3223 | if (gofwd != null) | ||
3224 | { | ||
3225 | if (ParentGroup.GetSceneMaxUndo() > 0) | ||
3226 | { | ||
3227 | UndoState nUndo = new UndoState(this, gofwd.ForGroup); | ||
3228 | |||
3229 | m_undo.Push(nUndo); | ||
3230 | } | ||
3231 | |||
3232 | gofwd.PlayfwdState(this); | ||
3233 | } | ||
3234 | 3655 | ||
3235 | // m_log.DebugFormat( | 3656 | lock (m_UndoRedo) |
3236 | // "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", | 3657 | { |
3237 | // Name, LocalId, m_redo.Count); | 3658 | Undoing = true; |
3238 | } | 3659 | m_UndoRedo.Redo(this); |
3660 | Undoing = false; | ||
3239 | } | 3661 | } |
3240 | } | 3662 | } |
3241 | 3663 | ||
3242 | public void ClearUndoState() | 3664 | public void ClearUndoState() |
3243 | { | 3665 | { |
3244 | // m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); | 3666 | if (m_UndoRedo == null || Undoing) |
3667 | return; | ||
3245 | 3668 | ||
3246 | lock (m_undo) | 3669 | lock (m_UndoRedo) |
3247 | { | 3670 | { |
3248 | m_undo.Clear(); | 3671 | m_UndoRedo.Clear(); |
3249 | m_redo.Clear(); | ||
3250 | } | 3672 | } |
3251 | } | 3673 | } |
3252 | 3674 | ||
@@ -3876,6 +4298,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
3876 | } | 4298 | } |
3877 | } | 4299 | } |
3878 | 4300 | ||
4301 | |||
4302 | public void UpdateExtraPhysics(ExtraPhysicsData physdata) | ||
4303 | { | ||
4304 | if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) | ||
4305 | return; | ||
4306 | |||
4307 | if (PhysicsShapeType != (byte)physdata.PhysShapeType) | ||
4308 | { | ||
4309 | PhysicsShapeType = (byte)physdata.PhysShapeType; | ||
4310 | |||
4311 | } | ||
4312 | |||
4313 | if(Density != physdata.Density) | ||
4314 | Density = physdata.Density; | ||
4315 | if(GravityModifier != physdata.GravitationModifier) | ||
4316 | GravityModifier = physdata.GravitationModifier; | ||
4317 | if(Friction != physdata.Friction) | ||
4318 | Friction = physdata.Friction; | ||
4319 | if(Bounciness != physdata.Bounce) | ||
4320 | Bounciness = physdata.Bounce; | ||
4321 | } | ||
3879 | /// <summary> | 4322 | /// <summary> |
3880 | /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. | 4323 | /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. |
3881 | /// </summary> | 4324 | /// </summary> |
@@ -3883,7 +4326,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3883 | /// <param name="SetTemporary"></param> | 4326 | /// <param name="SetTemporary"></param> |
3884 | /// <param name="SetPhantom"></param> | 4327 | /// <param name="SetPhantom"></param> |
3885 | /// <param name="SetVD"></param> | 4328 | /// <param name="SetVD"></param> |
3886 | public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) | 4329 | public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building) |
3887 | { | 4330 | { |
3888 | bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); | 4331 | bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); |
3889 | bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); | 4332 | bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); |
@@ -3893,225 +4336,205 @@ namespace OpenSim.Region.Framework.Scenes | |||
3893 | if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) | 4336 | if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) |
3894 | return; | 4337 | return; |
3895 | 4338 | ||
3896 | PhysicsActor pa = PhysActor; | 4339 | VolumeDetectActive = SetVD; |
3897 | 4340 | ||
3898 | // Special cases for VD. VD can only be called from a script | 4341 | // volume detector implies phantom |
3899 | // and can't be combined with changes to other states. So we can rely | 4342 | if (VolumeDetectActive) |
3900 | // that... | ||
3901 | // ... if VD is changed, all others are not. | ||
3902 | // ... if one of the others is changed, VD is not. | ||
3903 | if (SetVD) // VD is active, special logic applies | ||
3904 | { | ||
3905 | // State machine logic for VolumeDetect | ||
3906 | // More logic below | ||
3907 | bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom; | ||
3908 | |||
3909 | if (phanReset) // Phantom changes from on to off switch VD off too | ||
3910 | { | ||
3911 | SetVD = false; // Switch it of for the course of this routine | ||
3912 | VolumeDetectActive = false; // and also permanently | ||
3913 | |||
3914 | if (pa != null) | ||
3915 | pa.SetVolumeDetect(0); // Let physics know about it too | ||
3916 | } | ||
3917 | else | ||
3918 | { | ||
3919 | // If volumedetect is active we don't want phantom to be applied. | ||
3920 | // If this is a new call to VD out of the state "phantom" | ||
3921 | // this will also cause the prim to be visible to physics | ||
3922 | SetPhantom = false; | ||
3923 | } | ||
3924 | } | ||
3925 | |||
3926 | if (UsePhysics && IsJoint()) | ||
3927 | { | ||
3928 | SetPhantom = true; | 4343 | SetPhantom = true; |
3929 | } | ||
3930 | 4344 | ||
3931 | if (UsePhysics) | 4345 | if (UsePhysics) |
3932 | { | ||
3933 | AddFlag(PrimFlags.Physics); | 4346 | AddFlag(PrimFlags.Physics); |
3934 | if (!wasUsingPhysics) | ||
3935 | { | ||
3936 | DoPhysicsPropertyUpdate(UsePhysics, false); | ||
3937 | |||
3938 | if (!ParentGroup.IsDeleted) | ||
3939 | { | ||
3940 | if (LocalId == ParentGroup.RootPart.LocalId) | ||
3941 | { | ||
3942 | ParentGroup.CheckSculptAndLoad(); | ||
3943 | } | ||
3944 | } | ||
3945 | } | ||
3946 | } | ||
3947 | else | 4347 | else |
3948 | { | ||
3949 | RemFlag(PrimFlags.Physics); | 4348 | RemFlag(PrimFlags.Physics); |
3950 | if (wasUsingPhysics) | ||
3951 | { | ||
3952 | DoPhysicsPropertyUpdate(UsePhysics, false); | ||
3953 | } | ||
3954 | } | ||
3955 | 4349 | ||
3956 | if (SetPhantom | 4350 | if (SetPhantom) |
3957 | || ParentGroup.IsAttachment | ||
3958 | || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints | ||
3959 | { | ||
3960 | AddFlag(PrimFlags.Phantom); | 4351 | AddFlag(PrimFlags.Phantom); |
4352 | else | ||
4353 | RemFlag(PrimFlags.Phantom); | ||
3961 | 4354 | ||
3962 | if (PhysActor != null) | 4355 | if (SetTemporary) |
4356 | AddFlag(PrimFlags.TemporaryOnRez); | ||
4357 | else | ||
4358 | RemFlag(PrimFlags.TemporaryOnRez); | ||
4359 | |||
4360 | |||
4361 | if (ParentGroup.Scene == null) | ||
4362 | return; | ||
4363 | |||
4364 | PhysicsActor pa = PhysActor; | ||
4365 | |||
4366 | if (pa != null && building && pa.Building != building) | ||
4367 | pa.Building = building; | ||
4368 | |||
4369 | if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none | ||
4370 | || (Shape.PathCurve == (byte)Extrusion.Flexible)) | ||
4371 | { | ||
4372 | if (pa != null) | ||
3963 | { | 4373 | { |
4374 | ParentGroup.Scene.RemovePhysicalPrim(1); | ||
3964 | RemoveFromPhysics(); | 4375 | RemoveFromPhysics(); |
3965 | pa = null; | ||
3966 | } | 4376 | } |
4377 | |||
4378 | Velocity = new Vector3(0, 0, 0); | ||
4379 | Acceleration = new Vector3(0, 0, 0); | ||
4380 | if (ParentGroup.RootPart == this) | ||
4381 | AngularVelocity = new Vector3(0, 0, 0); | ||
3967 | } | 4382 | } |
3968 | else // Not phantom | 4383 | else |
3969 | { | 4384 | { |
3970 | RemFlag(PrimFlags.Phantom); | 4385 | if (ParentGroup.Scene.CollidablePrims) |
3971 | |||
3972 | if (ParentGroup.Scene == null) | ||
3973 | return; | ||
3974 | |||
3975 | if (ParentGroup.Scene.CollidablePrims && pa == null) | ||
3976 | { | 4386 | { |
3977 | pa = AddToPhysics(UsePhysics); | 4387 | if (pa == null) |
3978 | |||
3979 | if (pa != null) | ||
3980 | { | 4388 | { |
3981 | pa.SetMaterial(Material); | 4389 | AddToPhysics(UsePhysics, SetPhantom, building , false); |
3982 | DoPhysicsPropertyUpdate(UsePhysics, true); | 4390 | pa = PhysActor; |
3983 | 4391 | ||
3984 | if (!ParentGroup.IsDeleted) | 4392 | if (pa != null) |
3985 | { | 4393 | { |
3986 | if (LocalId == ParentGroup.RootPart.LocalId) | 4394 | if ( |
4395 | // ((AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
4396 | // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4397 | // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4398 | // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4399 | // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4400 | // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4401 | ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero) | ||
4402 | // (CollisionSound != UUID.Zero) | ||
4403 | ) | ||
3987 | { | 4404 | { |
3988 | ParentGroup.CheckSculptAndLoad(); | 4405 | pa.OnCollisionUpdate += PhysicsCollision; |
4406 | pa.SubscribeEvents(1000); | ||
3989 | } | 4407 | } |
3990 | } | 4408 | } |
3991 | |||
3992 | if ( | ||
3993 | ((AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
3994 | ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
3995 | ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
3996 | ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
3997 | ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
3998 | ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
3999 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
4000 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4001 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4002 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4003 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4004 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4005 | (CollisionSound != UUID.Zero) | ||
4006 | ) | ||
4007 | { | ||
4008 | pa.OnCollisionUpdate += PhysicsCollision; | ||
4009 | pa.SubscribeEvents(1000); | ||
4010 | } | ||
4011 | } | 4409 | } |
4012 | } | 4410 | else // it already has a physical representation |
4013 | else // it already has a physical representation | ||
4014 | { | ||
4015 | DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim | ||
4016 | |||
4017 | if (!ParentGroup.IsDeleted) | ||
4018 | { | 4411 | { |
4019 | if (LocalId == ParentGroup.RootPart.LocalId) | 4412 | DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. |
4020 | { | 4413 | /* moved into DoPhysicsPropertyUpdate |
4021 | ParentGroup.CheckSculptAndLoad(); | 4414 | if(VolumeDetectActive) |
4022 | } | 4415 | pa.SetVolumeDetect(1); |
4416 | else | ||
4417 | pa.SetVolumeDetect(0); | ||
4418 | */ | ||
4419 | if (pa.Building != building) | ||
4420 | pa.Building = building; | ||
4023 | } | 4421 | } |
4024 | } | 4422 | } |
4025 | } | 4423 | } |
4026 | |||
4027 | if (SetVD) | ||
4028 | { | ||
4029 | // If the above logic worked (this is urgent candidate to unit tests!) | ||
4030 | // we now have a physicsactor. | ||
4031 | // Defensive programming calls for a check here. | ||
4032 | // Better would be throwing an exception that could be catched by a unit test as the internal | ||
4033 | // logic should make sure, this Physactor is always here. | ||
4034 | if (pa != null) | ||
4035 | { | ||
4036 | pa.SetVolumeDetect(1); | ||
4037 | AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active | ||
4038 | VolumeDetectActive = true; | ||
4039 | } | ||
4040 | } | ||
4041 | else | ||
4042 | { | ||
4043 | // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like | ||
4044 | // (mumbles, well, at least if you have infinte CPU powers :-)) | ||
4045 | if (pa != null) | ||
4046 | pa.SetVolumeDetect(0); | ||
4047 | |||
4048 | VolumeDetectActive = false; | ||
4049 | } | ||
4050 | |||
4051 | if (SetTemporary) | ||
4052 | { | ||
4053 | AddFlag(PrimFlags.TemporaryOnRez); | ||
4054 | } | ||
4055 | else | ||
4056 | { | ||
4057 | RemFlag(PrimFlags.TemporaryOnRez); | ||
4058 | } | ||
4059 | 4424 | ||
4060 | // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); | 4425 | // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); |
4061 | 4426 | ||
4427 | // and last in case we have a new actor and not building | ||
4428 | |||
4062 | if (ParentGroup != null) | 4429 | if (ParentGroup != null) |
4063 | { | 4430 | { |
4064 | ParentGroup.HasGroupChanged = true; | 4431 | ParentGroup.HasGroupChanged = true; |
4065 | ScheduleFullUpdate(); | 4432 | ScheduleFullUpdate(); |
4066 | } | 4433 | } |
4067 | 4434 | ||
4068 | // m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); | 4435 | // m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); |
4069 | } | 4436 | } |
4070 | 4437 | ||
4071 | /// <summary> | 4438 | /// <summary> |
4072 | /// Adds this part to the physics scene. | 4439 | /// Adds this part to the physics scene. |
4440 | /// and sets the PhysActor property | ||
4073 | /// </summary> | 4441 | /// </summary> |
4074 | /// <remarks>This method also sets the PhysActor property.</remarks> | 4442 | /// <param name="isPhysical">Add this prim as physical.</param> |
4075 | /// <param name="rigidBody">Add this prim with a rigid body.</param> | 4443 | /// <param name="isPhantom">Add this prim as phantom.</param> |
4076 | /// <returns> | 4444 | /// <param name="building">tells physics to delay full construction of object</param> |
4077 | /// The physics actor. null if there was a failure. | 4445 | /// <param name="applyDynamics">applies velocities, force and torque</param> |
4078 | /// </returns> | 4446 | private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics) |
4079 | private PhysicsActor AddToPhysics(bool rigidBody) | 4447 | { |
4080 | { | ||
4081 | PhysicsActor pa; | 4448 | PhysicsActor pa; |
4082 | 4449 | ||
4450 | Vector3 velocity = Velocity; | ||
4451 | Vector3 rotationalVelocity = AngularVelocity;; | ||
4452 | |||
4083 | try | 4453 | try |
4084 | { | 4454 | { |
4085 | pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( | 4455 | pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( |
4086 | string.Format("{0}/{1}", Name, UUID), | 4456 | string.Format("{0}/{1}", Name, UUID), |
4087 | Shape, | 4457 | Shape, |
4088 | AbsolutePosition, | 4458 | AbsolutePosition, |
4089 | Scale, | 4459 | Scale, |
4090 | RotationOffset, | 4460 | GetWorldRotation(), |
4091 | rigidBody, | 4461 | isPhysical, |
4092 | m_localId); | 4462 | isPhantom, |
4463 | PhysicsShapeType, | ||
4464 | m_localId); | ||
4093 | } | 4465 | } |
4094 | catch | 4466 | catch (Exception ex) |
4095 | { | 4467 | { |
4096 | m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); | 4468 | m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message); |
4097 | pa = null; | 4469 | pa = null; |
4098 | } | 4470 | } |
4099 | 4471 | ||
4100 | // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical | ||
4101 | // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor | ||
4102 | // being set. | ||
4103 | PhysActor = pa; | ||
4104 | |||
4105 | // Basic Physics can also return null as well as an exception catch. | ||
4106 | if (pa != null) | 4472 | if (pa != null) |
4107 | { | 4473 | { |
4108 | pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info | 4474 | pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info |
4109 | pa.SetMaterial(Material); | 4475 | pa.SetMaterial(Material); |
4110 | DoPhysicsPropertyUpdate(rigidBody, true); | 4476 | |
4477 | if (VolumeDetectActive) // change if not the default only | ||
4478 | pa.SetVolumeDetect(1); | ||
4479 | |||
4480 | if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId) | ||
4481 | m_vehicle.SetVehicle(pa); | ||
4482 | |||
4483 | // we are going to tell rest of code about physics so better have this here | ||
4484 | PhysActor = pa; | ||
4485 | |||
4486 | // DoPhysicsPropertyUpdate(isPhysical, true); | ||
4487 | // lets expand it here just with what it really needs to do | ||
4488 | |||
4489 | if (isPhysical) | ||
4490 | { | ||
4491 | if (ParentGroup.RootPart.KeyframeMotion != null) | ||
4492 | ParentGroup.RootPart.KeyframeMotion.Stop(); | ||
4493 | ParentGroup.RootPart.KeyframeMotion = null; | ||
4494 | ParentGroup.Scene.AddPhysicalPrim(1); | ||
4495 | |||
4496 | pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; | ||
4497 | pa.OnOutOfBounds += PhysicsOutOfBounds; | ||
4498 | |||
4499 | if (ParentID != 0 && ParentID != LocalId) | ||
4500 | { | ||
4501 | PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; | ||
4502 | |||
4503 | if (parentPa != null) | ||
4504 | { | ||
4505 | pa.link(parentPa); | ||
4506 | } | ||
4507 | } | ||
4508 | } | ||
4509 | |||
4510 | if (applyDynamics) | ||
4511 | // do independent of isphysical so parameters get setted (at least some) | ||
4512 | { | ||
4513 | Velocity = velocity; | ||
4514 | AngularVelocity = rotationalVelocity; | ||
4515 | // pa.Velocity = velocity; | ||
4516 | pa.RotationalVelocity = rotationalVelocity; | ||
4517 | |||
4518 | // if not vehicle and root part apply force and torque | ||
4519 | if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE) | ||
4520 | && LocalId == ParentGroup.RootPart.LocalId) | ||
4521 | { | ||
4522 | pa.Force = Force; | ||
4523 | pa.Torque = Torque; | ||
4524 | } | ||
4525 | } | ||
4526 | |||
4527 | if (Shape.SculptEntry) | ||
4528 | CheckSculptAndLoad(); | ||
4529 | else | ||
4530 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); | ||
4531 | |||
4532 | if (!building) | ||
4533 | pa.Building = false; | ||
4111 | } | 4534 | } |
4112 | 4535 | ||
4113 | return pa; | 4536 | PhysActor = pa; |
4114 | } | 4537 | } |
4115 | 4538 | ||
4116 | /// <summary> | 4539 | /// <summary> |
4117 | /// This removes the part from the physics scene. | 4540 | /// This removes the part from the physics scene. |
@@ -4321,39 +4744,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
4321 | } | 4744 | } |
4322 | 4745 | ||
4323 | PhysicsActor pa = PhysActor; | 4746 | PhysicsActor pa = PhysActor; |
4324 | 4747 | if (pa != null) | |
4325 | if ( | ||
4326 | ((AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
4327 | ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4328 | ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4329 | ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4330 | ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4331 | ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4332 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
4333 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4334 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4335 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4336 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4337 | ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4338 | (CollisionSound != UUID.Zero) | ||
4339 | ) | ||
4340 | { | 4748 | { |
4341 | // subscribe to physics updates. | 4749 | if ( |
4342 | if (pa != null) | 4750 | // ((AggregateScriptEvents & scriptEvents.collision) != 0) || |
4751 | // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4752 | // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4753 | // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4754 | // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4755 | // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4756 | ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero) | ||
4757 | ) | ||
4343 | { | 4758 | { |
4759 | // subscribe to physics updates. | ||
4344 | pa.OnCollisionUpdate += PhysicsCollision; | 4760 | pa.OnCollisionUpdate += PhysicsCollision; |
4345 | pa.SubscribeEvents(1000); | 4761 | pa.SubscribeEvents(1000); |
4346 | } | 4762 | } |
4347 | } | 4763 | else |
4348 | else | ||
4349 | { | ||
4350 | if (pa != null) | ||
4351 | { | 4764 | { |
4352 | pa.UnSubscribeEvents(); | 4765 | pa.UnSubscribeEvents(); |
4353 | pa.OnCollisionUpdate -= PhysicsCollision; | 4766 | pa.OnCollisionUpdate -= PhysicsCollision; |
4354 | } | 4767 | } |
4355 | } | 4768 | } |
4356 | |||
4357 | //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) | 4769 | //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) |
4358 | //{ | 4770 | //{ |
4359 | // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting; | 4771 | // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting; |
@@ -4480,5 +4892,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
4480 | Color color = Color; | 4892 | Color color = Color; |
4481 | return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); | 4893 | return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); |
4482 | } | 4894 | } |
4895 | |||
4896 | public void ResetOwnerChangeFlag() | ||
4897 | { | ||
4898 | List<UUID> inv = Inventory.GetInventoryList(); | ||
4899 | |||
4900 | foreach (UUID itemID in inv) | ||
4901 | { | ||
4902 | TaskInventoryItem item = Inventory.GetInventoryItem(itemID); | ||
4903 | item.OwnerChanged = false; | ||
4904 | Inventory.UpdateInventoryItem(item, false, false); | ||
4905 | } | ||
4906 | } | ||
4483 | } | 4907 | } |
4484 | } | 4908 | } |