aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
1 files changed, 167 insertions, 63 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 734ba22..e8cf4f4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -123,13 +132,18 @@ namespace OpenSim.Region.Framework.Scenes
123 132
124 protected internal void Close() 133 protected internal void Close()
125 { 134 {
126 lock (m_presenceLock) 135 m_scenePresencesLock.EnterWriteLock();
136 try
127 { 137 {
128 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
129 List<ScenePresence> newlist = new List<ScenePresence>(); 139 List<ScenePresence> newlist = new List<ScenePresence>();
130 m_scenePresenceMap = newmap; 140 m_scenePresenceMap = newmap;
131 m_scenePresenceArray = newlist; 141 m_scenePresenceArray = newlist;
132 } 142 }
143 finally
144 {
145 m_scenePresencesLock.ExitWriteLock();
146 }
133 147
134 lock (SceneObjectGroupsByFullID) 148 lock (SceneObjectGroupsByFullID)
135 SceneObjectGroupsByFullID.Clear(); 149 SceneObjectGroupsByFullID.Clear();
@@ -259,6 +273,33 @@ namespace OpenSim.Region.Framework.Scenes
259 protected internal bool AddRestoredSceneObject( 273 protected internal bool AddRestoredSceneObject(
260 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 274 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
261 { 275 {
276 if (!m_parentScene.CombineRegions)
277 {
278 // KF: Check for out-of-region, move inside and make static.
279 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
280 sceneObject.RootPart.GroupPosition.Y,
281 sceneObject.RootPart.GroupPosition.Z);
282 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
283 npos.X > Constants.RegionSize ||
284 npos.Y > Constants.RegionSize))
285 {
286 if (npos.X < 0.0) npos.X = 1.0f;
287 if (npos.Y < 0.0) npos.Y = 1.0f;
288 if (npos.Z < 0.0) npos.Z = 0.0f;
289 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
290 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
291
292 foreach (SceneObjectPart part in sceneObject.Parts)
293 {
294 part.GroupPosition = npos;
295 }
296 sceneObject.RootPart.Velocity = Vector3.Zero;
297 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
298 sceneObject.RootPart.Acceleration = Vector3.Zero;
299 sceneObject.RootPart.Velocity = Vector3.Zero;
300 }
301 }
302
262 if (attachToBackup && (!alreadyPersisted)) 303 if (attachToBackup && (!alreadyPersisted))
263 { 304 {
264 sceneObject.ForceInventoryPersistence(); 305 sceneObject.ForceInventoryPersistence();
@@ -458,6 +499,30 @@ namespace OpenSim.Region.Framework.Scenes
458 m_updateList[obj.UUID] = obj; 499 m_updateList[obj.UUID] = obj;
459 } 500 }
460 501
502 public void FireAttachToBackup(SceneObjectGroup obj)
503 {
504 if (OnAttachToBackup != null)
505 {
506 OnAttachToBackup(obj);
507 }
508 }
509
510 public void FireDetachFromBackup(SceneObjectGroup obj)
511 {
512 if (OnDetachFromBackup != null)
513 {
514 OnDetachFromBackup(obj);
515 }
516 }
517
518 public void FireChangeBackup(SceneObjectGroup obj)
519 {
520 if (OnChangeBackup != null)
521 {
522 OnChangeBackup(obj);
523 }
524 }
525
461 /// <summary> 526 /// <summary>
462 /// Process all pending updates 527 /// Process all pending updates
463 /// </summary> 528 /// </summary>
@@ -593,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes
593 658
594 Entities[presence.UUID] = presence; 659 Entities[presence.UUID] = presence;
595 660
596 lock (m_presenceLock) 661 m_scenePresencesLock.EnterWriteLock();
662 try
597 { 663 {
598 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
599 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -617,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
617 m_scenePresenceMap = newmap; 683 m_scenePresenceMap = newmap;
618 m_scenePresenceArray = newlist; 684 m_scenePresenceArray = newlist;
619 } 685 }
686 finally
687 {
688 m_scenePresencesLock.ExitWriteLock();
689 }
620 } 690 }
621 691
622 /// <summary> 692 /// <summary>
@@ -631,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes
631 agentID); 701 agentID);
632 } 702 }
633 703
634 lock (m_presenceLock) 704 m_scenePresencesLock.EnterWriteLock();
705 try
635 { 706 {
636 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 707 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
637 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 708 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -653,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes
653 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 724 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
654 } 725 }
655 } 726 }
727 finally
728 {
729 m_scenePresencesLock.ExitWriteLock();
730 }
656 } 731 }
657 732
658 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 733 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -776,6 +851,11 @@ namespace OpenSim.Region.Framework.Scenes
776 return m_scenePresenceArray; 851 return m_scenePresenceArray;
777 } 852 }
778 853
854 public int GetNumberOfScenePresences()
855 {
856 return m_scenePresenceArray.Count;
857 }
858
779 /// <summary> 859 /// <summary>
780 /// Request a scene presence by UUID. Fast, indexed lookup. 860 /// Request a scene presence by UUID. Fast, indexed lookup.
781 /// </summary> 861 /// </summary>
@@ -1069,9 +1149,11 @@ namespace OpenSim.Region.Framework.Scenes
1069 /// <param name="action"></param> 1149 /// <param name="action"></param>
1070 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1150 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1071 { 1151 {
1072 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1152 EntityBase[] objlist = Entities.GetAllByType<SceneObjectGroup>();
1073 foreach (SceneObjectGroup obj in objlist) 1153 foreach (EntityBase ent in objlist)
1074 { 1154 {
1155 SceneObjectGroup obj = (SceneObjectGroup)ent;
1156
1075 try 1157 try
1076 { 1158 {
1077 action(obj); 1159 action(obj);
@@ -1282,8 +1364,13 @@ namespace OpenSim.Region.Framework.Scenes
1282 { 1364 {
1283 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1365 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1284 { 1366 {
1285 if (m_parentScene.AttachmentsModule != null) 1367 // Set the new attachment point data in the object
1286 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1368 byte attachmentPoint = group.GetAttachmentPoint();
1369 group.UpdateGroupPosition(pos);
1370 group.RootPart.IsAttachment = false;
1371 group.AbsolutePosition = group.RootPart.AttachedPos;
1372 group.SetAttachmentPoint(attachmentPoint);
1373 group.HasGroupChanged = true;
1287 } 1374 }
1288 else 1375 else
1289 { 1376 {
@@ -1527,10 +1614,13 @@ namespace OpenSim.Region.Framework.Scenes
1527 /// <param name="childPrims"></param> 1614 /// <param name="childPrims"></param>
1528 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1615 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1529 { 1616 {
1617 SceneObjectGroup parentGroup = root.ParentGroup;
1618 if (parentGroup == null) return;
1530 Monitor.Enter(m_updateLock); 1619 Monitor.Enter(m_updateLock);
1620
1531 try 1621 try
1532 { 1622 {
1533 SceneObjectGroup parentGroup = root.ParentGroup; 1623 parentGroup.areUpdatesSuspended = true;
1534 1624
1535 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1625 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1536 if (parentGroup != null) 1626 if (parentGroup != null)
@@ -1542,11 +1632,6 @@ namespace OpenSim.Region.Framework.Scenes
1542 1632
1543 if (child != null) 1633 if (child != null)
1544 { 1634 {
1545 // Make sure no child prim is set for sale
1546 // So that, on delink, no prims are unwittingly
1547 // left for sale and sold off
1548 child.RootPart.ObjectSaleType = 0;
1549 child.RootPart.SalePrice = 10;
1550 childGroups.Add(child); 1635 childGroups.Add(child);
1551 } 1636 }
1552 } 1637 }
@@ -1569,12 +1654,13 @@ namespace OpenSim.Region.Framework.Scenes
1569 // occur on link to invoke this elsewhere (such as object selection) 1654 // occur on link to invoke this elsewhere (such as object selection)
1570 parentGroup.RootPart.CreateSelected = true; 1655 parentGroup.RootPart.CreateSelected = true;
1571 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1656 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1572 parentGroup.HasGroupChanged = true;
1573 parentGroup.ScheduleGroupForFullUpdate();
1574
1575 } 1657 }
1576 finally 1658 finally
1577 { 1659 {
1660 parentGroup.areUpdatesSuspended = false;
1661 parentGroup.HasGroupChanged = true;
1662 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1663 parentGroup.ScheduleGroupForFullUpdate();
1578 Monitor.Exit(m_updateLock); 1664 Monitor.Exit(m_updateLock);
1579 } 1665 }
1580 } 1666 }
@@ -1606,21 +1692,24 @@ namespace OpenSim.Region.Framework.Scenes
1606 1692
1607 SceneObjectGroup group = part.ParentGroup; 1693 SceneObjectGroup group = part.ParentGroup;
1608 if (!affectedGroups.Contains(group)) 1694 if (!affectedGroups.Contains(group))
1695 {
1696 group.areUpdatesSuspended = true;
1609 affectedGroups.Add(group); 1697 affectedGroups.Add(group);
1698 }
1610 } 1699 }
1611 } 1700 }
1612 } 1701 }
1613 1702
1614 foreach (SceneObjectPart child in childParts) 1703 if (childParts.Count > 0)
1615 { 1704 {
1616 // Unlink all child parts from their groups 1705 foreach (SceneObjectPart child in childParts)
1617 // 1706 {
1618 child.ParentGroup.DelinkFromGroup(child, true); 1707 // Unlink all child parts from their groups
1619 1708 //
1620 // These are not in affected groups and will not be 1709 child.ParentGroup.DelinkFromGroup(child, true);
1621 // handled further. Do the honors here. 1710 child.ParentGroup.HasGroupChanged = true;
1622 child.ParentGroup.HasGroupChanged = true; 1711 child.ParentGroup.ScheduleGroupForFullUpdate();
1623 child.ParentGroup.ScheduleGroupForFullUpdate(); 1712 }
1624 } 1713 }
1625 1714
1626 foreach (SceneObjectPart root in rootParts) 1715 foreach (SceneObjectPart root in rootParts)
@@ -1630,56 +1719,68 @@ namespace OpenSim.Region.Framework.Scenes
1630 // However, editing linked parts and unlinking may be different 1719 // However, editing linked parts and unlinking may be different
1631 // 1720 //
1632 SceneObjectGroup group = root.ParentGroup; 1721 SceneObjectGroup group = root.ParentGroup;
1722 group.areUpdatesSuspended = true;
1633 1723
1634 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1724 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1635 int numChildren = newSet.Count; 1725 int numChildren = newSet.Count;
1636 1726
1727 if (numChildren == 1)
1728 break;
1729
1637 // If there are prims left in a link set, but the root is 1730 // If there are prims left in a link set, but the root is
1638 // slated for unlink, we need to do this 1731 // slated for unlink, we need to do this
1732 // Unlink the remaining set
1639 // 1733 //
1640 if (numChildren != 1) 1734 bool sendEventsToRemainder = true;
1641 { 1735 if (numChildren > 1)
1642 // Unlink the remaining set 1736 sendEventsToRemainder = false;
1643 //
1644 bool sendEventsToRemainder = true;
1645 if (numChildren > 1)
1646 sendEventsToRemainder = false;
1647 1737
1648 foreach (SceneObjectPart p in newSet) 1738 foreach (SceneObjectPart p in newSet)
1739 {
1740 if (p != group.RootPart)
1649 { 1741 {
1650 if (p != group.RootPart) 1742 group.DelinkFromGroup(p, sendEventsToRemainder);
1651 group.DelinkFromGroup(p, sendEventsToRemainder); 1743 if (numChildren > 2)
1744 {
1745 p.ParentGroup.areUpdatesSuspended = true;
1746 }
1747 else
1748 {
1749 p.ParentGroup.HasGroupChanged = true;
1750 p.ParentGroup.ScheduleGroupForFullUpdate();
1751 }
1652 } 1752 }
1753 }
1754
1755 // If there is more than one prim remaining, we
1756 // need to re-link
1757 //
1758 if (numChildren > 2)
1759 {
1760 // Remove old root
1761 //
1762 if (newSet.Contains(root))
1763 newSet.Remove(root);
1653 1764
1654 // If there is more than one prim remaining, we 1765 // Preserve link ordering
1655 // need to re-link
1656 // 1766 //
1657 if (numChildren > 2) 1767 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1658 { 1768 {
1659 // Remove old root 1769 return a.LinkNum.CompareTo(b.LinkNum);
1660 // 1770 });
1661 if (newSet.Contains(root))
1662 newSet.Remove(root);
1663
1664 // Preserve link ordering
1665 //
1666 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1667 {
1668 return a.LinkNum.CompareTo(b.LinkNum);
1669 });
1670 1771
1671 // Determine new root 1772 // Determine new root
1672 // 1773 //
1673 SceneObjectPart newRoot = newSet[0]; 1774 SceneObjectPart newRoot = newSet[0];
1674 newSet.RemoveAt(0); 1775 newSet.RemoveAt(0);
1675 1776
1676 foreach (SceneObjectPart newChild in newSet) 1777 foreach (SceneObjectPart newChild in newSet)
1677 newChild.UpdateFlag = 0; 1778 newChild.UpdateFlag = 0;
1678 1779
1679 LinkObjects(newRoot, newSet); 1780 newRoot.ParentGroup.areUpdatesSuspended = true;
1680 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1781 LinkObjects(newRoot, newSet);
1681 affectedGroups.Add(newRoot.ParentGroup); 1782 if (!affectedGroups.Contains(newRoot.ParentGroup))
1682 } 1783 affectedGroups.Add(newRoot.ParentGroup);
1683 } 1784 }
1684 } 1785 }
1685 1786
@@ -1687,8 +1788,14 @@ namespace OpenSim.Region.Framework.Scenes
1687 // 1788 //
1688 foreach (SceneObjectGroup g in affectedGroups) 1789 foreach (SceneObjectGroup g in affectedGroups)
1689 { 1790 {
1791 // Child prims that have been unlinked and deleted will
1792 // return unless the root is deleted. This will remove them
1793 // from the database. They will be rewritten immediately,
1794 // minus the rows for the unlinked child prims.
1795 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1690 g.TriggerScriptChangedEvent(Changed.LINK); 1796 g.TriggerScriptChangedEvent(Changed.LINK);
1691 g.HasGroupChanged = true; // Persist 1797 g.HasGroupChanged = true; // Persist
1798 g.areUpdatesSuspended = false;
1692 g.ScheduleGroupForFullUpdate(); 1799 g.ScheduleGroupForFullUpdate();
1693 } 1800 }
1694 } 1801 }
@@ -1803,9 +1910,6 @@ namespace OpenSim.Region.Framework.Scenes
1803 child.ApplyNextOwnerPermissions(); 1910 child.ApplyNextOwnerPermissions();
1804 } 1911 }
1805 } 1912 }
1806
1807 copy.RootPart.ObjectSaleType = 0;
1808 copy.RootPart.SalePrice = 10;
1809 } 1913 }
1810 1914
1811 Entities.Add(copy); 1915 Entities.Add(copy);