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.cs224
1 files changed, 168 insertions, 56 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 1e2901b..6c57d57 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();
@@ -491,6 +532,30 @@ namespace OpenSim.Region.Framework.Scenes
491 m_updateList[obj.UUID] = obj; 532 m_updateList[obj.UUID] = obj;
492 } 533 }
493 534
535 public void FireAttachToBackup(SceneObjectGroup obj)
536 {
537 if (OnAttachToBackup != null)
538 {
539 OnAttachToBackup(obj);
540 }
541 }
542
543 public void FireDetachFromBackup(SceneObjectGroup obj)
544 {
545 if (OnDetachFromBackup != null)
546 {
547 OnDetachFromBackup(obj);
548 }
549 }
550
551 public void FireChangeBackup(SceneObjectGroup obj)
552 {
553 if (OnChangeBackup != null)
554 {
555 OnChangeBackup(obj);
556 }
557 }
558
494 /// <summary> 559 /// <summary>
495 /// Process all pending updates 560 /// Process all pending updates
496 /// </summary> 561 /// </summary>
@@ -608,7 +673,8 @@ namespace OpenSim.Region.Framework.Scenes
608 673
609 Entities[presence.UUID] = presence; 674 Entities[presence.UUID] = presence;
610 675
611 lock (m_presenceLock) 676 m_scenePresencesLock.EnterWriteLock();
677 try
612 { 678 {
613 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 679 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
614 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 680 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -632,6 +698,10 @@ namespace OpenSim.Region.Framework.Scenes
632 m_scenePresenceMap = newmap; 698 m_scenePresenceMap = newmap;
633 m_scenePresenceArray = newlist; 699 m_scenePresenceArray = newlist;
634 } 700 }
701 finally
702 {
703 m_scenePresencesLock.ExitWriteLock();
704 }
635 } 705 }
636 706
637 /// <summary> 707 /// <summary>
@@ -646,7 +716,8 @@ namespace OpenSim.Region.Framework.Scenes
646 agentID); 716 agentID);
647 } 717 }
648 718
649 lock (m_presenceLock) 719 m_scenePresencesLock.EnterWriteLock();
720 try
650 { 721 {
651 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 722 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
652 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 723 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -668,6 +739,10 @@ namespace OpenSim.Region.Framework.Scenes
668 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 739 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
669 } 740 }
670 } 741 }
742 finally
743 {
744 m_scenePresencesLock.ExitWriteLock();
745 }
671 } 746 }
672 747
673 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 748 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1381,8 +1456,13 @@ namespace OpenSim.Region.Framework.Scenes
1381 { 1456 {
1382 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1457 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1383 { 1458 {
1384 if (m_parentScene.AttachmentsModule != null) 1459 // Set the new attachment point data in the object
1385 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1460 byte attachmentPoint = group.GetAttachmentPoint();
1461 group.UpdateGroupPosition(pos);
1462 group.IsAttachment = false;
1463 group.AbsolutePosition = group.RootPart.AttachedPos;
1464 group.AttachmentPoint = attachmentPoint;
1465 group.HasGroupChanged = true;
1386 } 1466 }
1387 else 1467 else
1388 { 1468 {
@@ -1654,8 +1734,11 @@ namespace OpenSim.Region.Framework.Scenes
1654 return; 1734 return;
1655 1735
1656 Monitor.Enter(m_updateLock); 1736 Monitor.Enter(m_updateLock);
1737
1657 try 1738 try
1658 { 1739 {
1740 parentGroup.areUpdatesSuspended = true;
1741
1659 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1742 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1660 1743
1661 // We do this in reverse to get the link order of the prims correct 1744 // We do this in reverse to get the link order of the prims correct
@@ -1666,9 +1749,13 @@ namespace OpenSim.Region.Framework.Scenes
1666 // Make sure no child prim is set for sale 1749 // Make sure no child prim is set for sale
1667 // So that, on delink, no prims are unwittingly 1750 // So that, on delink, no prims are unwittingly
1668 // left for sale and sold off 1751 // left for sale and sold off
1669 child.RootPart.ObjectSaleType = 0; 1752
1670 child.RootPart.SalePrice = 10; 1753 if (child != null)
1671 childGroups.Add(child); 1754 {
1755 child.RootPart.ObjectSaleType = 0;
1756 child.RootPart.SalePrice = 10;
1757 childGroups.Add(child);
1758 }
1672 } 1759 }
1673 1760
1674 foreach (SceneObjectGroup child in childGroups) 1761 foreach (SceneObjectGroup child in childGroups)
@@ -1687,12 +1774,19 @@ namespace OpenSim.Region.Framework.Scenes
1687 // occur on link to invoke this elsewhere (such as object selection) 1774 // occur on link to invoke this elsewhere (such as object selection)
1688 parentGroup.RootPart.CreateSelected = true; 1775 parentGroup.RootPart.CreateSelected = true;
1689 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1776 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1690 parentGroup.HasGroupChanged = true;
1691 parentGroup.ScheduleGroupForFullUpdate();
1692
1693 } 1777 }
1694 finally 1778 finally
1695 { 1779 {
1780 lock (SceneObjectGroupsByLocalPartID)
1781 {
1782 foreach (SceneObjectPart part in parentGroup.Parts)
1783 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1784 }
1785
1786 parentGroup.areUpdatesSuspended = false;
1787 parentGroup.HasGroupChanged = true;
1788 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1789 parentGroup.ScheduleGroupForFullUpdate();
1696 Monitor.Exit(m_updateLock); 1790 Monitor.Exit(m_updateLock);
1697 } 1791 }
1698 } 1792 }
@@ -1729,21 +1823,24 @@ namespace OpenSim.Region.Framework.Scenes
1729 1823
1730 SceneObjectGroup group = part.ParentGroup; 1824 SceneObjectGroup group = part.ParentGroup;
1731 if (!affectedGroups.Contains(group)) 1825 if (!affectedGroups.Contains(group))
1826 {
1827 group.areUpdatesSuspended = true;
1732 affectedGroups.Add(group); 1828 affectedGroups.Add(group);
1829 }
1733 } 1830 }
1734 } 1831 }
1735 } 1832 }
1736 1833
1737 foreach (SceneObjectPart child in childParts) 1834 if (childParts.Count > 0)
1738 { 1835 {
1739 // Unlink all child parts from their groups 1836 foreach (SceneObjectPart child in childParts)
1740 // 1837 {
1741 child.ParentGroup.DelinkFromGroup(child, true); 1838 // Unlink all child parts from their groups
1742 1839 //
1743 // These are not in affected groups and will not be 1840 child.ParentGroup.DelinkFromGroup(child, true);
1744 // handled further. Do the honors here. 1841 child.ParentGroup.HasGroupChanged = true;
1745 child.ParentGroup.HasGroupChanged = true; 1842 child.ParentGroup.ScheduleGroupForFullUpdate();
1746 child.ParentGroup.ScheduleGroupForFullUpdate(); 1843 }
1747 } 1844 }
1748 1845
1749 foreach (SceneObjectPart root in rootParts) 1846 foreach (SceneObjectPart root in rootParts)
@@ -1753,56 +1850,68 @@ namespace OpenSim.Region.Framework.Scenes
1753 // However, editing linked parts and unlinking may be different 1850 // However, editing linked parts and unlinking may be different
1754 // 1851 //
1755 SceneObjectGroup group = root.ParentGroup; 1852 SceneObjectGroup group = root.ParentGroup;
1853 group.areUpdatesSuspended = true;
1756 1854
1757 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1855 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1758 int numChildren = newSet.Count; 1856 int numChildren = newSet.Count;
1759 1857
1858 if (numChildren == 1)
1859 break;
1860
1760 // If there are prims left in a link set, but the root is 1861 // If there are prims left in a link set, but the root is
1761 // slated for unlink, we need to do this 1862 // slated for unlink, we need to do this
1863 // Unlink the remaining set
1762 // 1864 //
1763 if (numChildren != 1) 1865 bool sendEventsToRemainder = true;
1764 { 1866 if (numChildren > 1)
1765 // Unlink the remaining set 1867 sendEventsToRemainder = false;
1766 //
1767 bool sendEventsToRemainder = true;
1768 if (numChildren > 1)
1769 sendEventsToRemainder = false;
1770 1868
1771 foreach (SceneObjectPart p in newSet) 1869 foreach (SceneObjectPart p in newSet)
1870 {
1871 if (p != group.RootPart)
1772 { 1872 {
1773 if (p != group.RootPart) 1873 group.DelinkFromGroup(p, sendEventsToRemainder);
1774 group.DelinkFromGroup(p, sendEventsToRemainder); 1874 if (numChildren > 2)
1875 {
1876 p.ParentGroup.areUpdatesSuspended = true;
1877 }
1878 else
1879 {
1880 p.ParentGroup.HasGroupChanged = true;
1881 p.ParentGroup.ScheduleGroupForFullUpdate();
1882 }
1775 } 1883 }
1884 }
1885
1886 // If there is more than one prim remaining, we
1887 // need to re-link
1888 //
1889 if (numChildren > 2)
1890 {
1891 // Remove old root
1892 //
1893 if (newSet.Contains(root))
1894 newSet.Remove(root);
1776 1895
1777 // If there is more than one prim remaining, we 1896 // Preserve link ordering
1778 // need to re-link
1779 // 1897 //
1780 if (numChildren > 2) 1898 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1781 { 1899 {
1782 // Remove old root 1900 return a.LinkNum.CompareTo(b.LinkNum);
1783 // 1901 });
1784 if (newSet.Contains(root))
1785 newSet.Remove(root);
1786
1787 // Preserve link ordering
1788 //
1789 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1790 {
1791 return a.LinkNum.CompareTo(b.LinkNum);
1792 });
1793 1902
1794 // Determine new root 1903 // Determine new root
1795 // 1904 //
1796 SceneObjectPart newRoot = newSet[0]; 1905 SceneObjectPart newRoot = newSet[0];
1797 newSet.RemoveAt(0); 1906 newSet.RemoveAt(0);
1798 1907
1799 foreach (SceneObjectPart newChild in newSet) 1908 foreach (SceneObjectPart newChild in newSet)
1800 newChild.ClearUpdateSchedule(); 1909 newChild.ClearUpdateSchedule();
1801 1910
1802 LinkObjects(newRoot, newSet); 1911 newRoot.ParentGroup.areUpdatesSuspended = true;
1803 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1912 LinkObjects(newRoot, newSet);
1804 affectedGroups.Add(newRoot.ParentGroup); 1913 if (!affectedGroups.Contains(newRoot.ParentGroup))
1805 } 1914 affectedGroups.Add(newRoot.ParentGroup);
1806 } 1915 }
1807 } 1916 }
1808 1917
@@ -1810,8 +1919,14 @@ namespace OpenSim.Region.Framework.Scenes
1810 // 1919 //
1811 foreach (SceneObjectGroup g in affectedGroups) 1920 foreach (SceneObjectGroup g in affectedGroups)
1812 { 1921 {
1922 // Child prims that have been unlinked and deleted will
1923 // return unless the root is deleted. This will remove them
1924 // from the database. They will be rewritten immediately,
1925 // minus the rows for the unlinked child prims.
1926 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1813 g.TriggerScriptChangedEvent(Changed.LINK); 1927 g.TriggerScriptChangedEvent(Changed.LINK);
1814 g.HasGroupChanged = true; // Persist 1928 g.HasGroupChanged = true; // Persist
1929 g.areUpdatesSuspended = false;
1815 g.ScheduleGroupForFullUpdate(); 1930 g.ScheduleGroupForFullUpdate();
1816 } 1931 }
1817 } 1932 }
@@ -1929,9 +2044,6 @@ namespace OpenSim.Region.Framework.Scenes
1929 child.ApplyNextOwnerPermissions(); 2044 child.ApplyNextOwnerPermissions();
1930 } 2045 }
1931 } 2046 }
1932
1933 copy.RootPart.ObjectSaleType = 0;
1934 copy.RootPart.SalePrice = 10;
1935 } 2047 }
1936 2048
1937 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2049 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()