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.cs228
1 files changed, 170 insertions, 58 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 82ded28..e1fde64 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
@@ -130,13 +139,18 @@ namespace OpenSim.Region.Framework.Scenes
130 139
131 protected internal void Close() 140 protected internal void Close()
132 { 141 {
133 lock (m_presenceLock) 142 m_scenePresencesLock.EnterWriteLock();
143 try
134 { 144 {
135 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 145 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
136 List<ScenePresence> newlist = new List<ScenePresence>(); 146 List<ScenePresence> newlist = new List<ScenePresence>();
137 m_scenePresenceMap = newmap; 147 m_scenePresenceMap = newmap;
138 m_scenePresenceArray = newlist; 148 m_scenePresenceArray = newlist;
139 } 149 }
150 finally
151 {
152 m_scenePresencesLock.ExitWriteLock();
153 }
140 154
141 lock (SceneObjectGroupsByFullID) 155 lock (SceneObjectGroupsByFullID)
142 SceneObjectGroupsByFullID.Clear(); 156 SceneObjectGroupsByFullID.Clear();
@@ -275,6 +289,33 @@ namespace OpenSim.Region.Framework.Scenes
275 protected internal bool AddRestoredSceneObject( 289 protected internal bool AddRestoredSceneObject(
276 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 290 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
277 { 291 {
292 if (!m_parentScene.CombineRegions)
293 {
294 // KF: Check for out-of-region, move inside and make static.
295 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
296 sceneObject.RootPart.GroupPosition.Y,
297 sceneObject.RootPart.GroupPosition.Z);
298 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 ||
299 npos.X > Constants.RegionSize ||
300 npos.Y > Constants.RegionSize))
301 {
302 if (npos.X < 0.0) npos.X = 1.0f;
303 if (npos.Y < 0.0) npos.Y = 1.0f;
304 if (npos.Z < 0.0) npos.Z = 0.0f;
305 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
306 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
307
308 foreach (SceneObjectPart part in sceneObject.Parts)
309 {
310 part.GroupPosition = npos;
311 }
312 sceneObject.RootPart.Velocity = Vector3.Zero;
313 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
314 sceneObject.RootPart.Acceleration = Vector3.Zero;
315 sceneObject.RootPart.Velocity = Vector3.Zero;
316 }
317 }
318
278 if (attachToBackup && (!alreadyPersisted)) 319 if (attachToBackup && (!alreadyPersisted))
279 { 320 {
280 sceneObject.ForceInventoryPersistence(); 321 sceneObject.ForceInventoryPersistence();
@@ -492,6 +533,30 @@ namespace OpenSim.Region.Framework.Scenes
492 m_updateList[obj.UUID] = obj; 533 m_updateList[obj.UUID] = obj;
493 } 534 }
494 535
536 public void FireAttachToBackup(SceneObjectGroup obj)
537 {
538 if (OnAttachToBackup != null)
539 {
540 OnAttachToBackup(obj);
541 }
542 }
543
544 public void FireDetachFromBackup(SceneObjectGroup obj)
545 {
546 if (OnDetachFromBackup != null)
547 {
548 OnDetachFromBackup(obj);
549 }
550 }
551
552 public void FireChangeBackup(SceneObjectGroup obj)
553 {
554 if (OnChangeBackup != null)
555 {
556 OnChangeBackup(obj);
557 }
558 }
559
495 /// <summary> 560 /// <summary>
496 /// Process all pending updates 561 /// Process all pending updates
497 /// </summary> 562 /// </summary>
@@ -623,7 +688,8 @@ namespace OpenSim.Region.Framework.Scenes
623 688
624 Entities[presence.UUID] = presence; 689 Entities[presence.UUID] = presence;
625 690
626 lock (m_presenceLock) 691 m_scenePresencesLock.EnterWriteLock();
692 try
627 { 693 {
628 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 694 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
629 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 695 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -647,6 +713,10 @@ namespace OpenSim.Region.Framework.Scenes
647 m_scenePresenceMap = newmap; 713 m_scenePresenceMap = newmap;
648 m_scenePresenceArray = newlist; 714 m_scenePresenceArray = newlist;
649 } 715 }
716 finally
717 {
718 m_scenePresencesLock.ExitWriteLock();
719 }
650 } 720 }
651 721
652 /// <summary> 722 /// <summary>
@@ -661,7 +731,8 @@ namespace OpenSim.Region.Framework.Scenes
661 agentID); 731 agentID);
662 } 732 }
663 733
664 lock (m_presenceLock) 734 m_scenePresencesLock.EnterWriteLock();
735 try
665 { 736 {
666 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 737 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
667 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 738 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -683,6 +754,10 @@ namespace OpenSim.Region.Framework.Scenes
683 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 754 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
684 } 755 }
685 } 756 }
757 finally
758 {
759 m_scenePresencesLock.ExitWriteLock();
760 }
686 } 761 }
687 762
688 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 763 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1396,8 +1471,13 @@ namespace OpenSim.Region.Framework.Scenes
1396 { 1471 {
1397 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1472 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1398 { 1473 {
1399 if (m_parentScene.AttachmentsModule != null) 1474 // Set the new attachment point data in the object
1400 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1475 byte attachmentPoint = group.GetAttachmentPoint();
1476 group.UpdateGroupPosition(pos);
1477 group.IsAttachment = false;
1478 group.AbsolutePosition = group.RootPart.AttachedPos;
1479 group.AttachmentPoint = attachmentPoint;
1480 group.HasGroupChanged = true;
1401 } 1481 }
1402 else 1482 else
1403 { 1483 {
@@ -1661,24 +1741,31 @@ namespace OpenSim.Region.Framework.Scenes
1661 /// <param name="childPrims"></param> 1741 /// <param name="childPrims"></param>
1662 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1742 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1663 { 1743 {
1744 SceneObjectGroup parentGroup = root.ParentGroup;
1745 if (parentGroup == null) return;
1664 Monitor.Enter(m_updateLock); 1746 Monitor.Enter(m_updateLock);
1747
1665 try 1748 try
1666 { 1749 {
1667 SceneObjectGroup parentGroup = root.ParentGroup; 1750 parentGroup.areUpdatesSuspended = true;
1668 1751
1669 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1752 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1670 1753
1671 // We do this in reverse to get the link order of the prims correct 1754 // We do this in reverse to get the link order of the prims correct
1672 for (int i = children.Count - 1; i >= 0; i--) 1755 for (int i = 0 ; i < children.Count ; i++)
1673 { 1756 {
1674 SceneObjectGroup child = children[i].ParentGroup; 1757 SceneObjectGroup child = children[i].ParentGroup;
1675 1758
1676 // Make sure no child prim is set for sale 1759 // Make sure no child prim is set for sale
1677 // So that, on delink, no prims are unwittingly 1760 // So that, on delink, no prims are unwittingly
1678 // left for sale and sold off 1761 // left for sale and sold off
1679 child.RootPart.ObjectSaleType = 0; 1762
1680 child.RootPart.SalePrice = 10; 1763 if (child != null)
1681 childGroups.Add(child); 1764 {
1765 child.RootPart.ObjectSaleType = 0;
1766 child.RootPart.SalePrice = 10;
1767 childGroups.Add(child);
1768 }
1682 } 1769 }
1683 1770
1684 foreach (SceneObjectGroup child in childGroups) 1771 foreach (SceneObjectGroup child in childGroups)
@@ -1694,12 +1781,19 @@ namespace OpenSim.Region.Framework.Scenes
1694 // occur on link to invoke this elsewhere (such as object selection) 1781 // occur on link to invoke this elsewhere (such as object selection)
1695 parentGroup.RootPart.CreateSelected = true; 1782 parentGroup.RootPart.CreateSelected = true;
1696 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1783 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1697 parentGroup.HasGroupChanged = true;
1698 parentGroup.ScheduleGroupForFullUpdate();
1699
1700 } 1784 }
1701 finally 1785 finally
1702 { 1786 {
1787 lock (SceneObjectGroupsByLocalPartID)
1788 {
1789 foreach (SceneObjectPart part in parentGroup.Parts)
1790 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1791 }
1792
1793 parentGroup.areUpdatesSuspended = false;
1794 parentGroup.HasGroupChanged = true;
1795 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1796 parentGroup.ScheduleGroupForFullUpdate();
1703 Monitor.Exit(m_updateLock); 1797 Monitor.Exit(m_updateLock);
1704 } 1798 }
1705 } 1799 }
@@ -1731,21 +1825,24 @@ namespace OpenSim.Region.Framework.Scenes
1731 1825
1732 SceneObjectGroup group = part.ParentGroup; 1826 SceneObjectGroup group = part.ParentGroup;
1733 if (!affectedGroups.Contains(group)) 1827 if (!affectedGroups.Contains(group))
1828 {
1829 group.areUpdatesSuspended = true;
1734 affectedGroups.Add(group); 1830 affectedGroups.Add(group);
1831 }
1735 } 1832 }
1736 } 1833 }
1737 } 1834 }
1738 1835
1739 foreach (SceneObjectPart child in childParts) 1836 if (childParts.Count > 0)
1740 { 1837 {
1741 // Unlink all child parts from their groups 1838 foreach (SceneObjectPart child in childParts)
1742 // 1839 {
1743 child.ParentGroup.DelinkFromGroup(child, true); 1840 // Unlink all child parts from their groups
1744 1841 //
1745 // These are not in affected groups and will not be 1842 child.ParentGroup.DelinkFromGroup(child, true);
1746 // handled further. Do the honors here. 1843 child.ParentGroup.HasGroupChanged = true;
1747 child.ParentGroup.HasGroupChanged = true; 1844 child.ParentGroup.ScheduleGroupForFullUpdate();
1748 child.ParentGroup.ScheduleGroupForFullUpdate(); 1845 }
1749 } 1846 }
1750 1847
1751 foreach (SceneObjectPart root in rootParts) 1848 foreach (SceneObjectPart root in rootParts)
@@ -1755,56 +1852,68 @@ namespace OpenSim.Region.Framework.Scenes
1755 // However, editing linked parts and unlinking may be different 1852 // However, editing linked parts and unlinking may be different
1756 // 1853 //
1757 SceneObjectGroup group = root.ParentGroup; 1854 SceneObjectGroup group = root.ParentGroup;
1855 group.areUpdatesSuspended = true;
1758 1856
1759 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1857 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1760 int numChildren = newSet.Count; 1858 int numChildren = newSet.Count;
1761 1859
1860 if (numChildren == 1)
1861 break;
1862
1762 // If there are prims left in a link set, but the root is 1863 // If there are prims left in a link set, but the root is
1763 // slated for unlink, we need to do this 1864 // slated for unlink, we need to do this
1865 // Unlink the remaining set
1764 // 1866 //
1765 if (numChildren != 1) 1867 bool sendEventsToRemainder = true;
1766 { 1868 if (numChildren > 1)
1767 // Unlink the remaining set 1869 sendEventsToRemainder = false;
1768 //
1769 bool sendEventsToRemainder = true;
1770 if (numChildren > 1)
1771 sendEventsToRemainder = false;
1772 1870
1773 foreach (SceneObjectPart p in newSet) 1871 foreach (SceneObjectPart p in newSet)
1872 {
1873 if (p != group.RootPart)
1774 { 1874 {
1775 if (p != group.RootPart) 1875 group.DelinkFromGroup(p, sendEventsToRemainder);
1776 group.DelinkFromGroup(p, sendEventsToRemainder); 1876 if (numChildren > 2)
1877 {
1878 p.ParentGroup.areUpdatesSuspended = true;
1879 }
1880 else
1881 {
1882 p.ParentGroup.HasGroupChanged = true;
1883 p.ParentGroup.ScheduleGroupForFullUpdate();
1884 }
1777 } 1885 }
1886 }
1887
1888 // If there is more than one prim remaining, we
1889 // need to re-link
1890 //
1891 if (numChildren > 2)
1892 {
1893 // Remove old root
1894 //
1895 if (newSet.Contains(root))
1896 newSet.Remove(root);
1778 1897
1779 // If there is more than one prim remaining, we 1898 // Preserve link ordering
1780 // need to re-link
1781 // 1899 //
1782 if (numChildren > 2) 1900 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1783 { 1901 {
1784 // Remove old root 1902 return a.LinkNum.CompareTo(b.LinkNum);
1785 // 1903 });
1786 if (newSet.Contains(root))
1787 newSet.Remove(root);
1788
1789 // Preserve link ordering
1790 //
1791 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1792 {
1793 return a.LinkNum.CompareTo(b.LinkNum);
1794 });
1795 1904
1796 // Determine new root 1905 // Determine new root
1797 // 1906 //
1798 SceneObjectPart newRoot = newSet[0]; 1907 SceneObjectPart newRoot = newSet[0];
1799 newSet.RemoveAt(0); 1908 newSet.RemoveAt(0);
1800 1909
1801 foreach (SceneObjectPart newChild in newSet) 1910 foreach (SceneObjectPart newChild in newSet)
1802 newChild.ClearUpdateSchedule(); 1911 newChild.ClearUpdateSchedule();
1803 1912
1804 LinkObjects(newRoot, newSet); 1913 newRoot.ParentGroup.areUpdatesSuspended = true;
1805 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1914 LinkObjects(newRoot, newSet);
1806 affectedGroups.Add(newRoot.ParentGroup); 1915 if (!affectedGroups.Contains(newRoot.ParentGroup))
1807 } 1916 affectedGroups.Add(newRoot.ParentGroup);
1808 } 1917 }
1809 } 1918 }
1810 1919
@@ -1812,8 +1921,14 @@ namespace OpenSim.Region.Framework.Scenes
1812 // 1921 //
1813 foreach (SceneObjectGroup g in affectedGroups) 1922 foreach (SceneObjectGroup g in affectedGroups)
1814 { 1923 {
1924 // Child prims that have been unlinked and deleted will
1925 // return unless the root is deleted. This will remove them
1926 // from the database. They will be rewritten immediately,
1927 // minus the rows for the unlinked child prims.
1928 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1815 g.TriggerScriptChangedEvent(Changed.LINK); 1929 g.TriggerScriptChangedEvent(Changed.LINK);
1816 g.HasGroupChanged = true; // Persist 1930 g.HasGroupChanged = true; // Persist
1931 g.areUpdatesSuspended = false;
1817 g.ScheduleGroupForFullUpdate(); 1932 g.ScheduleGroupForFullUpdate();
1818 } 1933 }
1819 } 1934 }
@@ -1931,9 +2046,6 @@ namespace OpenSim.Region.Framework.Scenes
1931 child.ApplyNextOwnerPermissions(); 2046 child.ApplyNextOwnerPermissions();
1932 } 2047 }
1933 } 2048 }
1934
1935 copy.RootPart.ObjectSaleType = 0;
1936 copy.RootPart.SalePrice = 10;
1937 } 2049 }
1938 2050
1939 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2051 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()