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 a078291..39d4a29 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 {
@@ -1617,10 +1697,13 @@ namespace OpenSim.Region.Framework.Scenes
1617 /// <param name="childPrims"></param> 1697 /// <param name="childPrims"></param>
1618 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1698 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1619 { 1699 {
1700 SceneObjectGroup parentGroup = root.ParentGroup;
1701 if (parentGroup == null) return;
1620 Monitor.Enter(m_updateLock); 1702 Monitor.Enter(m_updateLock);
1703
1621 try 1704 try
1622 { 1705 {
1623 SceneObjectGroup parentGroup = root.ParentGroup; 1706 parentGroup.areUpdatesSuspended = true;
1624 1707
1625 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1708 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1626 if (parentGroup != null) 1709 if (parentGroup != null)
@@ -1632,11 +1715,6 @@ namespace OpenSim.Region.Framework.Scenes
1632 1715
1633 if (child != null) 1716 if (child != null)
1634 { 1717 {
1635 // Make sure no child prim is set for sale
1636 // So that, on delink, no prims are unwittingly
1637 // left for sale and sold off
1638 child.RootPart.ObjectSaleType = 0;
1639 child.RootPart.SalePrice = 10;
1640 childGroups.Add(child); 1718 childGroups.Add(child);
1641 } 1719 }
1642 } 1720 }
@@ -1659,12 +1737,13 @@ namespace OpenSim.Region.Framework.Scenes
1659 // occur on link to invoke this elsewhere (such as object selection) 1737 // occur on link to invoke this elsewhere (such as object selection)
1660 parentGroup.RootPart.CreateSelected = true; 1738 parentGroup.RootPart.CreateSelected = true;
1661 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1739 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1662 parentGroup.HasGroupChanged = true;
1663 parentGroup.ScheduleGroupForFullUpdate();
1664
1665 } 1740 }
1666 finally 1741 finally
1667 { 1742 {
1743 parentGroup.areUpdatesSuspended = false;
1744 parentGroup.HasGroupChanged = true;
1745 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1746 parentGroup.ScheduleGroupForFullUpdate();
1668 Monitor.Exit(m_updateLock); 1747 Monitor.Exit(m_updateLock);
1669 } 1748 }
1670 } 1749 }
@@ -1696,21 +1775,24 @@ namespace OpenSim.Region.Framework.Scenes
1696 1775
1697 SceneObjectGroup group = part.ParentGroup; 1776 SceneObjectGroup group = part.ParentGroup;
1698 if (!affectedGroups.Contains(group)) 1777 if (!affectedGroups.Contains(group))
1778 {
1779 group.areUpdatesSuspended = true;
1699 affectedGroups.Add(group); 1780 affectedGroups.Add(group);
1781 }
1700 } 1782 }
1701 } 1783 }
1702 } 1784 }
1703 1785
1704 foreach (SceneObjectPart child in childParts) 1786 if (childParts.Count > 0)
1705 { 1787 {
1706 // Unlink all child parts from their groups 1788 foreach (SceneObjectPart child in childParts)
1707 // 1789 {
1708 child.ParentGroup.DelinkFromGroup(child, true); 1790 // Unlink all child parts from their groups
1709 1791 //
1710 // These are not in affected groups and will not be 1792 child.ParentGroup.DelinkFromGroup(child, true);
1711 // handled further. Do the honors here. 1793 child.ParentGroup.HasGroupChanged = true;
1712 child.ParentGroup.HasGroupChanged = true; 1794 child.ParentGroup.ScheduleGroupForFullUpdate();
1713 child.ParentGroup.ScheduleGroupForFullUpdate(); 1795 }
1714 } 1796 }
1715 1797
1716 foreach (SceneObjectPart root in rootParts) 1798 foreach (SceneObjectPart root in rootParts)
@@ -1720,56 +1802,68 @@ namespace OpenSim.Region.Framework.Scenes
1720 // However, editing linked parts and unlinking may be different 1802 // However, editing linked parts and unlinking may be different
1721 // 1803 //
1722 SceneObjectGroup group = root.ParentGroup; 1804 SceneObjectGroup group = root.ParentGroup;
1805 group.areUpdatesSuspended = true;
1723 1806
1724 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1807 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1725 int numChildren = newSet.Count; 1808 int numChildren = newSet.Count;
1726 1809
1810 if (numChildren == 1)
1811 break;
1812
1727 // If there are prims left in a link set, but the root is 1813 // If there are prims left in a link set, but the root is
1728 // slated for unlink, we need to do this 1814 // slated for unlink, we need to do this
1815 // Unlink the remaining set
1729 // 1816 //
1730 if (numChildren != 1) 1817 bool sendEventsToRemainder = true;
1731 { 1818 if (numChildren > 1)
1732 // Unlink the remaining set 1819 sendEventsToRemainder = false;
1733 //
1734 bool sendEventsToRemainder = true;
1735 if (numChildren > 1)
1736 sendEventsToRemainder = false;
1737 1820
1738 foreach (SceneObjectPart p in newSet) 1821 foreach (SceneObjectPart p in newSet)
1822 {
1823 if (p != group.RootPart)
1739 { 1824 {
1740 if (p != group.RootPart) 1825 group.DelinkFromGroup(p, sendEventsToRemainder);
1741 group.DelinkFromGroup(p, sendEventsToRemainder); 1826 if (numChildren > 2)
1827 {
1828 p.ParentGroup.areUpdatesSuspended = true;
1829 }
1830 else
1831 {
1832 p.ParentGroup.HasGroupChanged = true;
1833 p.ParentGroup.ScheduleGroupForFullUpdate();
1834 }
1742 } 1835 }
1836 }
1743 1837
1744 // If there is more than one prim remaining, we 1838 // If there is more than one prim remaining, we
1745 // need to re-link 1839 // need to re-link
1840 //
1841 if (numChildren > 2)
1842 {
1843 // Remove old root
1844 //
1845 if (newSet.Contains(root))
1846 newSet.Remove(root);
1847
1848 // Preserve link ordering
1746 // 1849 //
1747 if (numChildren > 2) 1850 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1748 { 1851 {
1749 // Remove old root 1852 return a.LinkNum.CompareTo(b.LinkNum);
1750 // 1853 });
1751 if (newSet.Contains(root))
1752 newSet.Remove(root);
1753
1754 // Preserve link ordering
1755 //
1756 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1757 {
1758 return a.LinkNum.CompareTo(b.LinkNum);
1759 });
1760 1854
1761 // Determine new root 1855 // Determine new root
1762 // 1856 //
1763 SceneObjectPart newRoot = newSet[0]; 1857 SceneObjectPart newRoot = newSet[0];
1764 newSet.RemoveAt(0); 1858 newSet.RemoveAt(0);
1765 1859
1766 foreach (SceneObjectPart newChild in newSet) 1860 foreach (SceneObjectPart newChild in newSet)
1767 newChild.UpdateFlag = 0; 1861 newChild.UpdateFlag = 0;
1768 1862
1769 LinkObjects(newRoot, newSet); 1863 newRoot.ParentGroup.areUpdatesSuspended = true;
1770 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1864 LinkObjects(newRoot, newSet);
1771 affectedGroups.Add(newRoot.ParentGroup); 1865 if (!affectedGroups.Contains(newRoot.ParentGroup))
1772 } 1866 affectedGroups.Add(newRoot.ParentGroup);
1773 } 1867 }
1774 } 1868 }
1775 1869
@@ -1777,8 +1871,14 @@ namespace OpenSim.Region.Framework.Scenes
1777 // 1871 //
1778 foreach (SceneObjectGroup g in affectedGroups) 1872 foreach (SceneObjectGroup g in affectedGroups)
1779 { 1873 {
1874 // Child prims that have been unlinked and deleted will
1875 // return unless the root is deleted. This will remove them
1876 // from the database. They will be rewritten immediately,
1877 // minus the rows for the unlinked child prims.
1878 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1780 g.TriggerScriptChangedEvent(Changed.LINK); 1879 g.TriggerScriptChangedEvent(Changed.LINK);
1781 g.HasGroupChanged = true; // Persist 1880 g.HasGroupChanged = true; // Persist
1881 g.areUpdatesSuspended = false;
1782 g.ScheduleGroupForFullUpdate(); 1882 g.ScheduleGroupForFullUpdate();
1783 } 1883 }
1784 } 1884 }
@@ -1896,9 +1996,6 @@ namespace OpenSim.Region.Framework.Scenes
1896 child.ApplyNextOwnerPermissions(); 1996 child.ApplyNextOwnerPermissions();
1897 } 1997 }
1898 } 1998 }
1899
1900 copy.RootPart.ObjectSaleType = 0;
1901 copy.RootPart.SalePrice = 10;
1902 } 1999 }
1903 2000
1904 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2001 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()