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