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.cs219
1 files changed, 158 insertions, 61 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index cdb4e41..c0236f4 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
@@ -135,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
135 144
136 protected internal void Close() 145 protected internal void Close()
137 { 146 {
138 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
139 { 149 {
140 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
141 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
142 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
143 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
144 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
145 159
146 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
147 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -273,6 +287,33 @@ namespace OpenSim.Region.Framework.Scenes
273 protected internal bool AddRestoredSceneObject( 287 protected internal bool AddRestoredSceneObject(
274 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 288 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
275 { 289 {
290 if (!m_parentScene.CombineRegions)
291 {
292 // KF: Check for out-of-region, move inside and make static.
293 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
294 sceneObject.RootPart.GroupPosition.Y,
295 sceneObject.RootPart.GroupPosition.Z);
296 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 ||
297 npos.X > Constants.RegionSize ||
298 npos.Y > Constants.RegionSize))
299 {
300 if (npos.X < 0.0) npos.X = 1.0f;
301 if (npos.Y < 0.0) npos.Y = 1.0f;
302 if (npos.Z < 0.0) npos.Z = 0.0f;
303 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
304 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
305
306 foreach (SceneObjectPart part in sceneObject.Parts)
307 {
308 part.GroupPosition = npos;
309 }
310 sceneObject.RootPart.Velocity = Vector3.Zero;
311 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
312 sceneObject.RootPart.Acceleration = Vector3.Zero;
313 sceneObject.RootPart.Velocity = Vector3.Zero;
314 }
315 }
316
276 if (attachToBackup && (!alreadyPersisted)) 317 if (attachToBackup && (!alreadyPersisted))
277 { 318 {
278 sceneObject.ForceInventoryPersistence(); 319 sceneObject.ForceInventoryPersistence();
@@ -486,6 +527,30 @@ namespace OpenSim.Region.Framework.Scenes
486 m_updateList[obj.UUID] = obj; 527 m_updateList[obj.UUID] = obj;
487 } 528 }
488 529
530 public void FireAttachToBackup(SceneObjectGroup obj)
531 {
532 if (OnAttachToBackup != null)
533 {
534 OnAttachToBackup(obj);
535 }
536 }
537
538 public void FireDetachFromBackup(SceneObjectGroup obj)
539 {
540 if (OnDetachFromBackup != null)
541 {
542 OnDetachFromBackup(obj);
543 }
544 }
545
546 public void FireChangeBackup(SceneObjectGroup obj)
547 {
548 if (OnChangeBackup != null)
549 {
550 OnChangeBackup(obj);
551 }
552 }
553
489 /// <summary> 554 /// <summary>
490 /// Process all pending updates 555 /// Process all pending updates
491 /// </summary> 556 /// </summary>
@@ -621,7 +686,8 @@ namespace OpenSim.Region.Framework.Scenes
621 686
622 Entities[presence.UUID] = presence; 687 Entities[presence.UUID] = presence;
623 688
624 lock (m_presenceLock) 689 m_scenePresencesLock.EnterWriteLock();
690 try
625 { 691 {
626 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 692 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
627 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 693 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -645,6 +711,10 @@ namespace OpenSim.Region.Framework.Scenes
645 m_scenePresenceMap = newmap; 711 m_scenePresenceMap = newmap;
646 m_scenePresenceArray = newlist; 712 m_scenePresenceArray = newlist;
647 } 713 }
714 finally
715 {
716 m_scenePresencesLock.ExitWriteLock();
717 }
648 } 718 }
649 719
650 /// <summary> 720 /// <summary>
@@ -659,7 +729,8 @@ namespace OpenSim.Region.Framework.Scenes
659 agentID); 729 agentID);
660 } 730 }
661 731
662 lock (m_presenceLock) 732 m_scenePresencesLock.EnterWriteLock();
733 try
663 { 734 {
664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 735 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 736 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -681,6 +752,10 @@ namespace OpenSim.Region.Framework.Scenes
681 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 752 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
682 } 753 }
683 } 754 }
755 finally
756 {
757 m_scenePresencesLock.ExitWriteLock();
758 }
684 } 759 }
685 760
686 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 761 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1363,8 +1438,13 @@ namespace OpenSim.Region.Framework.Scenes
1363 { 1438 {
1364 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1439 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1365 { 1440 {
1366 if (m_parentScene.AttachmentsModule != null) 1441 // Set the new attachment point data in the object
1367 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1442 byte attachmentPoint = group.GetAttachmentPoint();
1443 group.UpdateGroupPosition(pos);
1444 group.RootPart.IsAttachment = false;
1445 group.AbsolutePosition = group.RootPart.AttachedPos;
1446 group.SetAttachmentPoint(attachmentPoint);
1447 group.HasGroupChanged = true;
1368 } 1448 }
1369 else 1449 else
1370 { 1450 {
@@ -1608,10 +1688,13 @@ namespace OpenSim.Region.Framework.Scenes
1608 /// <param name="childPrims"></param> 1688 /// <param name="childPrims"></param>
1609 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1689 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1610 { 1690 {
1691 SceneObjectGroup parentGroup = root.ParentGroup;
1692 if (parentGroup == null) return;
1611 Monitor.Enter(m_updateLock); 1693 Monitor.Enter(m_updateLock);
1694
1612 try 1695 try
1613 { 1696 {
1614 SceneObjectGroup parentGroup = root.ParentGroup; 1697 parentGroup.areUpdatesSuspended = true;
1615 1698
1616 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1699 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1617 if (parentGroup != null) 1700 if (parentGroup != null)
@@ -1623,11 +1706,6 @@ namespace OpenSim.Region.Framework.Scenes
1623 1706
1624 if (child != null) 1707 if (child != null)
1625 { 1708 {
1626 // Make sure no child prim is set for sale
1627 // So that, on delink, no prims are unwittingly
1628 // left for sale and sold off
1629 child.RootPart.ObjectSaleType = 0;
1630 child.RootPart.SalePrice = 10;
1631 childGroups.Add(child); 1709 childGroups.Add(child);
1632 } 1710 }
1633 } 1711 }
@@ -1650,12 +1728,13 @@ namespace OpenSim.Region.Framework.Scenes
1650 // occur on link to invoke this elsewhere (such as object selection) 1728 // occur on link to invoke this elsewhere (such as object selection)
1651 parentGroup.RootPart.CreateSelected = true; 1729 parentGroup.RootPart.CreateSelected = true;
1652 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1730 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1653 parentGroup.HasGroupChanged = true;
1654 parentGroup.ScheduleGroupForFullUpdate();
1655
1656 } 1731 }
1657 finally 1732 finally
1658 { 1733 {
1734 parentGroup.areUpdatesSuspended = false;
1735 parentGroup.HasGroupChanged = true;
1736 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1737 parentGroup.ScheduleGroupForFullUpdate();
1659 Monitor.Exit(m_updateLock); 1738 Monitor.Exit(m_updateLock);
1660 } 1739 }
1661 } 1740 }
@@ -1687,21 +1766,24 @@ namespace OpenSim.Region.Framework.Scenes
1687 1766
1688 SceneObjectGroup group = part.ParentGroup; 1767 SceneObjectGroup group = part.ParentGroup;
1689 if (!affectedGroups.Contains(group)) 1768 if (!affectedGroups.Contains(group))
1769 {
1770 group.areUpdatesSuspended = true;
1690 affectedGroups.Add(group); 1771 affectedGroups.Add(group);
1772 }
1691 } 1773 }
1692 } 1774 }
1693 } 1775 }
1694 1776
1695 foreach (SceneObjectPart child in childParts) 1777 if (childParts.Count > 0)
1696 { 1778 {
1697 // Unlink all child parts from their groups 1779 foreach (SceneObjectPart child in childParts)
1698 // 1780 {
1699 child.ParentGroup.DelinkFromGroup(child, true); 1781 // Unlink all child parts from their groups
1700 1782 //
1701 // These are not in affected groups and will not be 1783 child.ParentGroup.DelinkFromGroup(child, true);
1702 // handled further. Do the honors here. 1784 child.ParentGroup.HasGroupChanged = true;
1703 child.ParentGroup.HasGroupChanged = true; 1785 child.ParentGroup.ScheduleGroupForFullUpdate();
1704 child.ParentGroup.ScheduleGroupForFullUpdate(); 1786 }
1705 } 1787 }
1706 1788
1707 foreach (SceneObjectPart root in rootParts) 1789 foreach (SceneObjectPart root in rootParts)
@@ -1711,56 +1793,68 @@ namespace OpenSim.Region.Framework.Scenes
1711 // However, editing linked parts and unlinking may be different 1793 // However, editing linked parts and unlinking may be different
1712 // 1794 //
1713 SceneObjectGroup group = root.ParentGroup; 1795 SceneObjectGroup group = root.ParentGroup;
1796 group.areUpdatesSuspended = true;
1714 1797
1715 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1798 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1716 int numChildren = newSet.Count; 1799 int numChildren = newSet.Count;
1717 1800
1801 if (numChildren == 1)
1802 break;
1803
1718 // If there are prims left in a link set, but the root is 1804 // If there are prims left in a link set, but the root is
1719 // slated for unlink, we need to do this 1805 // slated for unlink, we need to do this
1806 // Unlink the remaining set
1720 // 1807 //
1721 if (numChildren != 1) 1808 bool sendEventsToRemainder = true;
1722 { 1809 if (numChildren > 1)
1723 // Unlink the remaining set 1810 sendEventsToRemainder = false;
1724 //
1725 bool sendEventsToRemainder = true;
1726 if (numChildren > 1)
1727 sendEventsToRemainder = false;
1728 1811
1729 foreach (SceneObjectPart p in newSet) 1812 foreach (SceneObjectPart p in newSet)
1813 {
1814 if (p != group.RootPart)
1730 { 1815 {
1731 if (p != group.RootPart) 1816 group.DelinkFromGroup(p, sendEventsToRemainder);
1732 group.DelinkFromGroup(p, sendEventsToRemainder); 1817 if (numChildren > 2)
1818 {
1819 p.ParentGroup.areUpdatesSuspended = true;
1820 }
1821 else
1822 {
1823 p.ParentGroup.HasGroupChanged = true;
1824 p.ParentGroup.ScheduleGroupForFullUpdate();
1825 }
1733 } 1826 }
1827 }
1734 1828
1735 // If there is more than one prim remaining, we 1829 // If there is more than one prim remaining, we
1736 // need to re-link 1830 // need to re-link
1831 //
1832 if (numChildren > 2)
1833 {
1834 // Remove old root
1835 //
1836 if (newSet.Contains(root))
1837 newSet.Remove(root);
1838
1839 // Preserve link ordering
1737 // 1840 //
1738 if (numChildren > 2) 1841 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1739 { 1842 {
1740 // Remove old root 1843 return a.LinkNum.CompareTo(b.LinkNum);
1741 // 1844 });
1742 if (newSet.Contains(root))
1743 newSet.Remove(root);
1744
1745 // Preserve link ordering
1746 //
1747 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1748 {
1749 return a.LinkNum.CompareTo(b.LinkNum);
1750 });
1751 1845
1752 // Determine new root 1846 // Determine new root
1753 // 1847 //
1754 SceneObjectPart newRoot = newSet[0]; 1848 SceneObjectPart newRoot = newSet[0];
1755 newSet.RemoveAt(0); 1849 newSet.RemoveAt(0);
1756 1850
1757 foreach (SceneObjectPart newChild in newSet) 1851 foreach (SceneObjectPart newChild in newSet)
1758 newChild.UpdateFlag = 0; 1852 newChild.UpdateFlag = 0;
1759 1853
1760 LinkObjects(newRoot, newSet); 1854 newRoot.ParentGroup.areUpdatesSuspended = true;
1761 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1855 LinkObjects(newRoot, newSet);
1762 affectedGroups.Add(newRoot.ParentGroup); 1856 if (!affectedGroups.Contains(newRoot.ParentGroup))
1763 } 1857 affectedGroups.Add(newRoot.ParentGroup);
1764 } 1858 }
1765 } 1859 }
1766 1860
@@ -1768,8 +1862,14 @@ namespace OpenSim.Region.Framework.Scenes
1768 // 1862 //
1769 foreach (SceneObjectGroup g in affectedGroups) 1863 foreach (SceneObjectGroup g in affectedGroups)
1770 { 1864 {
1865 // Child prims that have been unlinked and deleted will
1866 // return unless the root is deleted. This will remove them
1867 // from the database. They will be rewritten immediately,
1868 // minus the rows for the unlinked child prims.
1869 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1771 g.TriggerScriptChangedEvent(Changed.LINK); 1870 g.TriggerScriptChangedEvent(Changed.LINK);
1772 g.HasGroupChanged = true; // Persist 1871 g.HasGroupChanged = true; // Persist
1872 g.areUpdatesSuspended = false;
1773 g.ScheduleGroupForFullUpdate(); 1873 g.ScheduleGroupForFullUpdate();
1774 } 1874 }
1775 } 1875 }
@@ -1887,9 +1987,6 @@ namespace OpenSim.Region.Framework.Scenes
1887 child.ApplyNextOwnerPermissions(); 1987 child.ApplyNextOwnerPermissions();
1888 } 1988 }
1889 } 1989 }
1890
1891 copy.RootPart.ObjectSaleType = 0;
1892 copy.RootPart.SalePrice = 10;
1893 } 1990 }
1894 1991
1895 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 1992 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()