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.cs303
1 files changed, 248 insertions, 55 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 67eb0fe..f6f6a1a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -123,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
123 133
124 protected internal void Close() 134 protected internal void Close()
125 { 135 {
126 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
127 { 138 {
128 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
129 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
130 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
131 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
132 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
133 148
134 lock (SceneObjectGroupsByFullID) 149 lock (SceneObjectGroupsByFullID)
135 SceneObjectGroupsByFullID.Clear(); 150 SceneObjectGroupsByFullID.Clear();
@@ -250,6 +265,33 @@ namespace OpenSim.Region.Framework.Scenes
250 protected internal bool AddRestoredSceneObject( 265 protected internal bool AddRestoredSceneObject(
251 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
252 { 267 {
268 if (!m_parentScene.CombineRegions)
269 {
270 // KF: Check for out-of-region, move inside and make static.
271 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
272 sceneObject.RootPart.GroupPosition.Y,
273 sceneObject.RootPart.GroupPosition.Z);
274 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 ||
275 npos.X > Constants.RegionSize ||
276 npos.Y > Constants.RegionSize))
277 {
278 if (npos.X < 0.0) npos.X = 1.0f;
279 if (npos.Y < 0.0) npos.Y = 1.0f;
280 if (npos.Z < 0.0) npos.Z = 0.0f;
281 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
282 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
283
284 foreach (SceneObjectPart part in sceneObject.Parts)
285 {
286 part.GroupPosition = npos;
287 }
288 sceneObject.RootPart.Velocity = Vector3.Zero;
289 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
290 sceneObject.RootPart.Acceleration = Vector3.Zero;
291 sceneObject.RootPart.Velocity = Vector3.Zero;
292 }
293 }
294
253 if (attachToBackup && (!alreadyPersisted)) 295 if (attachToBackup && (!alreadyPersisted))
254 { 296 {
255 sceneObject.ForceInventoryPersistence(); 297 sceneObject.ForceInventoryPersistence();
@@ -340,6 +382,11 @@ namespace OpenSim.Region.Framework.Scenes
340 /// </returns> 382 /// </returns>
341 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 383 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
342 { 384 {
385 if (sceneObject == null)
386 {
387 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
388 return false;
389 }
343 if (sceneObject.UUID == UUID.Zero) 390 if (sceneObject.UUID == UUID.Zero)
344 { 391 {
345 m_log.ErrorFormat( 392 m_log.ErrorFormat(
@@ -474,6 +521,30 @@ namespace OpenSim.Region.Framework.Scenes
474 m_updateList[obj.UUID] = obj; 521 m_updateList[obj.UUID] = obj;
475 } 522 }
476 523
524 public void FireAttachToBackup(SceneObjectGroup obj)
525 {
526 if (OnAttachToBackup != null)
527 {
528 OnAttachToBackup(obj);
529 }
530 }
531
532 public void FireDetachFromBackup(SceneObjectGroup obj)
533 {
534 if (OnDetachFromBackup != null)
535 {
536 OnDetachFromBackup(obj);
537 }
538 }
539
540 public void FireChangeBackup(SceneObjectGroup obj)
541 {
542 if (OnChangeBackup != null)
543 {
544 OnChangeBackup(obj);
545 }
546 }
547
477 /// <summary> 548 /// <summary>
478 /// Process all pending updates 549 /// Process all pending updates
479 /// </summary> 550 /// </summary>
@@ -591,7 +662,8 @@ namespace OpenSim.Region.Framework.Scenes
591 662
592 Entities[presence.UUID] = presence; 663 Entities[presence.UUID] = presence;
593 664
594 lock (m_presenceLock) 665 m_scenePresencesLock.EnterWriteLock();
666 try
595 { 667 {
596 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
597 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -615,6 +687,10 @@ namespace OpenSim.Region.Framework.Scenes
615 m_scenePresenceMap = newmap; 687 m_scenePresenceMap = newmap;
616 m_scenePresenceArray = newlist; 688 m_scenePresenceArray = newlist;
617 } 689 }
690 finally
691 {
692 m_scenePresencesLock.ExitWriteLock();
693 }
618 } 694 }
619 695
620 /// <summary> 696 /// <summary>
@@ -629,7 +705,8 @@ namespace OpenSim.Region.Framework.Scenes
629 agentID); 705 agentID);
630 } 706 }
631 707
632 lock (m_presenceLock) 708 m_scenePresencesLock.EnterWriteLock();
709 try
633 { 710 {
634 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 711 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
635 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 712 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -651,6 +728,10 @@ namespace OpenSim.Region.Framework.Scenes
651 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 728 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
652 } 729 }
653 } 730 }
731 finally
732 {
733 m_scenePresencesLock.ExitWriteLock();
734 }
654 } 735 }
655 736
656 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 737 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1183,6 +1264,25 @@ namespace OpenSim.Region.Framework.Scenes
1183 1264
1184 #region Client Event handlers 1265 #region Client Event handlers
1185 1266
1267 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1268 {
1269 SceneObjectPart part = GetSceneObjectPart(localID);
1270 ObjectChangeData data = (ObjectChangeData)odata;
1271
1272 if (part != null)
1273 {
1274 SceneObjectGroup grp = part.ParentGroup;
1275 if (grp != null)
1276 {
1277 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1278 {
1279 part.StoreUndoState(data.change); // lets test only saving what we changed
1280 grp.doChangeObject(part, (ObjectChangeData)data);
1281 }
1282 }
1283 }
1284 }
1285
1186 /// <summary> 1286 /// <summary>
1187 /// Update the scale of an individual prim. 1287 /// Update the scale of an individual prim.
1188 /// </summary> 1288 /// </summary>
@@ -1197,7 +1297,17 @@ namespace OpenSim.Region.Framework.Scenes
1197 { 1297 {
1198 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1298 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1199 { 1299 {
1300 bool physbuild = false;
1301 if (part.ParentGroup.RootPart.PhysActor != null)
1302 {
1303 part.ParentGroup.RootPart.PhysActor.Building = true;
1304 physbuild = true;
1305 }
1306
1200 part.Resize(scale); 1307 part.Resize(scale);
1308
1309 if (physbuild)
1310 part.ParentGroup.RootPart.PhysActor.Building = false;
1201 } 1311 }
1202 } 1312 }
1203 } 1313 }
@@ -1209,7 +1319,17 @@ namespace OpenSim.Region.Framework.Scenes
1209 { 1319 {
1210 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1320 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1211 { 1321 {
1322 bool physbuild = false;
1323 if (group.RootPart.PhysActor != null)
1324 {
1325 group.RootPart.PhysActor.Building = true;
1326 physbuild = true;
1327 }
1328
1212 group.GroupResize(scale); 1329 group.GroupResize(scale);
1330
1331 if (physbuild)
1332 group.RootPart.PhysActor.Building = false;
1213 } 1333 }
1214 } 1334 }
1215 } 1335 }
@@ -1337,8 +1457,13 @@ namespace OpenSim.Region.Framework.Scenes
1337 { 1457 {
1338 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))
1339 { 1459 {
1340 if (m_parentScene.AttachmentsModule != null) 1460 // Set the new attachment point data in the object
1341 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;
1342 } 1467 }
1343 else 1468 else
1344 { 1469 {
@@ -1386,7 +1511,7 @@ namespace OpenSim.Region.Framework.Scenes
1386 /// <param name="SetPhantom"></param> 1511 /// <param name="SetPhantom"></param>
1387 /// <param name="remoteClient"></param> 1512 /// <param name="remoteClient"></param>
1388 protected internal void UpdatePrimFlags( 1513 protected internal void UpdatePrimFlags(
1389 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1514 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1390 { 1515 {
1391 SceneObjectGroup group = GetGroupByPrim(localID); 1516 SceneObjectGroup group = GetGroupByPrim(localID);
1392 if (group != null) 1517 if (group != null)
@@ -1394,7 +1519,28 @@ namespace OpenSim.Region.Framework.Scenes
1394 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1519 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1395 { 1520 {
1396 // VolumeDetect can't be set via UI and will always be off when a change is made there 1521 // VolumeDetect can't be set via UI and will always be off when a change is made there
1397 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1522 // now only change volume dtc if phantom off
1523
1524 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1525 {
1526 bool vdtc;
1527 if (SetPhantom) // if phantom keep volumedtc
1528 vdtc = group.RootPart.VolumeDetectActive;
1529 else // else turn it off
1530 vdtc = false;
1531
1532 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc);
1533 }
1534 else
1535 {
1536 SceneObjectPart part = GetSceneObjectPart(localID);
1537 if (part != null)
1538 {
1539 part.UpdateExtraPhysics(PhysData);
1540 if (part.UpdatePhysRequired)
1541 remoteClient.SendPartPhysicsProprieties(part);
1542 }
1543 }
1398 } 1544 }
1399 } 1545 }
1400 } 1546 }
@@ -1538,6 +1684,7 @@ namespace OpenSim.Region.Framework.Scenes
1538 { 1684 {
1539 part.Material = Convert.ToByte(material); 1685 part.Material = Convert.ToByte(material);
1540 group.HasGroupChanged = true; 1686 group.HasGroupChanged = true;
1687 remoteClient.SendPartPhysicsProprieties(part);
1541 } 1688 }
1542 } 1689 }
1543 } 1690 }
@@ -1602,6 +1749,12 @@ namespace OpenSim.Region.Framework.Scenes
1602 /// <param name="childPrims"></param> 1749 /// <param name="childPrims"></param>
1603 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1750 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1604 { 1751 {
1752 if (root.KeyframeMotion != null)
1753 {
1754 root.KeyframeMotion.Stop();
1755 root.KeyframeMotion = null;
1756 }
1757
1605 SceneObjectGroup parentGroup = root.ParentGroup; 1758 SceneObjectGroup parentGroup = root.ParentGroup;
1606 if (parentGroup == null) return; 1759 if (parentGroup == null) return;
1607 1760
@@ -1610,8 +1763,11 @@ namespace OpenSim.Region.Framework.Scenes
1610 return; 1763 return;
1611 1764
1612 Monitor.Enter(m_updateLock); 1765 Monitor.Enter(m_updateLock);
1766
1613 try 1767 try
1614 { 1768 {
1769 parentGroup.areUpdatesSuspended = true;
1770
1615 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1771 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1616 1772
1617 // We do this in reverse to get the link order of the prims correct 1773 // We do this in reverse to get the link order of the prims correct
@@ -1626,9 +1782,13 @@ namespace OpenSim.Region.Framework.Scenes
1626 // Make sure no child prim is set for sale 1782 // Make sure no child prim is set for sale
1627 // So that, on delink, no prims are unwittingly 1783 // So that, on delink, no prims are unwittingly
1628 // left for sale and sold off 1784 // left for sale and sold off
1629 child.RootPart.ObjectSaleType = 0; 1785
1630 child.RootPart.SalePrice = 10; 1786 if (child != null)
1631 childGroups.Add(child); 1787 {
1788 child.RootPart.ObjectSaleType = 0;
1789 child.RootPart.SalePrice = 10;
1790 childGroups.Add(child);
1791 }
1632 } 1792 }
1633 1793
1634 foreach (SceneObjectGroup child in childGroups) 1794 foreach (SceneObjectGroup child in childGroups)
@@ -1655,6 +1815,16 @@ namespace OpenSim.Region.Framework.Scenes
1655 } 1815 }
1656 finally 1816 finally
1657 { 1817 {
1818 lock (SceneObjectGroupsByLocalPartID)
1819 {
1820 foreach (SceneObjectPart part in parentGroup.Parts)
1821 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1822 }
1823
1824 parentGroup.areUpdatesSuspended = false;
1825 parentGroup.HasGroupChanged = true;
1826 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1827 parentGroup.ScheduleGroupForFullUpdate();
1658 Monitor.Exit(m_updateLock); 1828 Monitor.Exit(m_updateLock);
1659 } 1829 }
1660 } 1830 }
@@ -1677,6 +1847,11 @@ namespace OpenSim.Region.Framework.Scenes
1677 { 1847 {
1678 if (part != null) 1848 if (part != null)
1679 { 1849 {
1850 if (part.KeyframeMotion != null)
1851 {
1852 part.KeyframeMotion.Stop();
1853 part.KeyframeMotion = null;
1854 }
1680 if (part.ParentGroup.PrimCount != 1) // Skip single 1855 if (part.ParentGroup.PrimCount != 1) // Skip single
1681 { 1856 {
1682 if (part.LinkNum < 2) // Root 1857 if (part.LinkNum < 2) // Root
@@ -1691,21 +1866,24 @@ namespace OpenSim.Region.Framework.Scenes
1691 1866
1692 SceneObjectGroup group = part.ParentGroup; 1867 SceneObjectGroup group = part.ParentGroup;
1693 if (!affectedGroups.Contains(group)) 1868 if (!affectedGroups.Contains(group))
1869 {
1870 group.areUpdatesSuspended = true;
1694 affectedGroups.Add(group); 1871 affectedGroups.Add(group);
1872 }
1695 } 1873 }
1696 } 1874 }
1697 } 1875 }
1698 1876
1699 foreach (SceneObjectPart child in childParts) 1877 if (childParts.Count > 0)
1700 { 1878 {
1701 // Unlink all child parts from their groups 1879 foreach (SceneObjectPart child in childParts)
1702 // 1880 {
1703 child.ParentGroup.DelinkFromGroup(child, true); 1881 // Unlink all child parts from their groups
1704 1882 //
1705 // These are not in affected groups and will not be 1883 child.ParentGroup.DelinkFromGroup(child, true);
1706 // handled further. Do the honors here. 1884 child.ParentGroup.HasGroupChanged = true;
1707 child.ParentGroup.HasGroupChanged = true; 1885 child.ParentGroup.ScheduleGroupForFullUpdate();
1708 child.ParentGroup.ScheduleGroupForFullUpdate(); 1886 }
1709 } 1887 }
1710 1888
1711 foreach (SceneObjectPart root in rootParts) 1889 foreach (SceneObjectPart root in rootParts)
@@ -1715,56 +1893,68 @@ namespace OpenSim.Region.Framework.Scenes
1715 // However, editing linked parts and unlinking may be different 1893 // However, editing linked parts and unlinking may be different
1716 // 1894 //
1717 SceneObjectGroup group = root.ParentGroup; 1895 SceneObjectGroup group = root.ParentGroup;
1896 group.areUpdatesSuspended = true;
1718 1897
1719 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1898 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1720 int numChildren = newSet.Count; 1899 int numChildren = newSet.Count;
1721 1900
1901 if (numChildren == 1)
1902 break;
1903
1722 // If there are prims left in a link set, but the root is 1904 // If there are prims left in a link set, but the root is
1723 // slated for unlink, we need to do this 1905 // slated for unlink, we need to do this
1906 // Unlink the remaining set
1724 // 1907 //
1725 if (numChildren != 1) 1908 bool sendEventsToRemainder = true;
1726 { 1909 if (numChildren > 1)
1727 // Unlink the remaining set 1910 sendEventsToRemainder = false;
1728 //
1729 bool sendEventsToRemainder = true;
1730 if (numChildren > 1)
1731 sendEventsToRemainder = false;
1732 1911
1733 foreach (SceneObjectPart p in newSet) 1912 foreach (SceneObjectPart p in newSet)
1913 {
1914 if (p != group.RootPart)
1734 { 1915 {
1735 if (p != group.RootPart) 1916 group.DelinkFromGroup(p, sendEventsToRemainder);
1736 group.DelinkFromGroup(p, sendEventsToRemainder); 1917 if (numChildren > 2)
1918 {
1919 p.ParentGroup.areUpdatesSuspended = true;
1920 }
1921 else
1922 {
1923 p.ParentGroup.HasGroupChanged = true;
1924 p.ParentGroup.ScheduleGroupForFullUpdate();
1925 }
1737 } 1926 }
1927 }
1738 1928
1739 // If there is more than one prim remaining, we 1929 // If there is more than one prim remaining, we
1740 // need to re-link 1930 // need to re-link
1931 //
1932 if (numChildren > 2)
1933 {
1934 // Remove old root
1741 // 1935 //
1742 if (numChildren > 2) 1936 if (newSet.Contains(root))
1937 newSet.Remove(root);
1938
1939 // Preserve link ordering
1940 //
1941 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1743 { 1942 {
1744 // Remove old root 1943 return a.LinkNum.CompareTo(b.LinkNum);
1745 // 1944 });
1746 if (newSet.Contains(root))
1747 newSet.Remove(root);
1748
1749 // Preserve link ordering
1750 //
1751 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1752 {
1753 return a.LinkNum.CompareTo(b.LinkNum);
1754 });
1755 1945
1756 // Determine new root 1946 // Determine new root
1757 // 1947 //
1758 SceneObjectPart newRoot = newSet[0]; 1948 SceneObjectPart newRoot = newSet[0];
1759 newSet.RemoveAt(0); 1949 newSet.RemoveAt(0);
1760 1950
1761 foreach (SceneObjectPart newChild in newSet) 1951 foreach (SceneObjectPart newChild in newSet)
1762 newChild.ClearUpdateSchedule(); 1952 newChild.ClearUpdateSchedule();
1763 1953
1764 LinkObjects(newRoot, newSet); 1954 newRoot.ParentGroup.areUpdatesSuspended = true;
1765 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1955 LinkObjects(newRoot, newSet);
1766 affectedGroups.Add(newRoot.ParentGroup); 1956 if (!affectedGroups.Contains(newRoot.ParentGroup))
1767 } 1957 affectedGroups.Add(newRoot.ParentGroup);
1768 } 1958 }
1769 } 1959 }
1770 1960
@@ -1772,8 +1962,14 @@ namespace OpenSim.Region.Framework.Scenes
1772 // 1962 //
1773 foreach (SceneObjectGroup g in affectedGroups) 1963 foreach (SceneObjectGroup g in affectedGroups)
1774 { 1964 {
1965 // Child prims that have been unlinked and deleted will
1966 // return unless the root is deleted. This will remove them
1967 // from the database. They will be rewritten immediately,
1968 // minus the rows for the unlinked child prims.
1969 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1775 g.TriggerScriptChangedEvent(Changed.LINK); 1970 g.TriggerScriptChangedEvent(Changed.LINK);
1776 g.HasGroupChanged = true; // Persist 1971 g.HasGroupChanged = true; // Persist
1972 g.areUpdatesSuspended = false;
1777 g.ScheduleGroupForFullUpdate(); 1973 g.ScheduleGroupForFullUpdate();
1778 } 1974 }
1779 } 1975 }
@@ -1875,9 +2071,6 @@ namespace OpenSim.Region.Framework.Scenes
1875 child.ApplyNextOwnerPermissions(); 2071 child.ApplyNextOwnerPermissions();
1876 } 2072 }
1877 } 2073 }
1878
1879 copy.RootPart.ObjectSaleType = 0;
1880 copy.RootPart.SalePrice = 10;
1881 } 2074 }
1882 2075
1883 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2076 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()