diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 288 |
1 files changed, 233 insertions, 55 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index bc3400a..7b77ea0 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 | ||
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
120 | 130 | ||
121 | protected internal void Close() | 131 | protected internal void Close() |
122 | { | 132 | { |
123 | lock (m_presenceLock) | 133 | m_scenePresencesLock.EnterWriteLock(); |
134 | try | ||
124 | { | 135 | { |
125 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 136 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
126 | List<ScenePresence> newlist = new List<ScenePresence>(); | 137 | List<ScenePresence> newlist = new List<ScenePresence>(); |
127 | m_scenePresenceMap = newmap; | 138 | m_scenePresenceMap = newmap; |
128 | m_scenePresenceArray = newlist; | 139 | m_scenePresenceArray = newlist; |
129 | } | 140 | } |
141 | finally | ||
142 | { | ||
143 | m_scenePresencesLock.ExitWriteLock(); | ||
144 | } | ||
130 | 145 | ||
131 | lock (SceneObjectGroupsByFullID) | 146 | lock (SceneObjectGroupsByFullID) |
132 | SceneObjectGroupsByFullID.Clear(); | 147 | SceneObjectGroupsByFullID.Clear(); |
@@ -247,6 +262,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
247 | protected internal bool AddRestoredSceneObject( | 262 | protected internal bool AddRestoredSceneObject( |
248 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 263 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
249 | { | 264 | { |
265 | if (!m_parentScene.CombineRegions) | ||
266 | { | ||
267 | // KF: Check for out-of-region, move inside and make static. | ||
268 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
269 | sceneObject.RootPart.GroupPosition.Y, | ||
270 | sceneObject.RootPart.GroupPosition.Z); | ||
271 | 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 || | ||
272 | npos.X > Constants.RegionSize || | ||
273 | npos.Y > Constants.RegionSize)) | ||
274 | { | ||
275 | if (npos.X < 0.0) npos.X = 1.0f; | ||
276 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
277 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
278 | if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; | ||
279 | if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; | ||
280 | |||
281 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
282 | { | ||
283 | part.GroupPosition = npos; | ||
284 | } | ||
285 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
286 | sceneObject.RootPart.AngularVelocity = Vector3.Zero; | ||
287 | sceneObject.RootPart.Acceleration = Vector3.Zero; | ||
288 | sceneObject.RootPart.Velocity = Vector3.Zero; | ||
289 | } | ||
290 | } | ||
291 | |||
250 | if (attachToBackup && (!alreadyPersisted)) | 292 | if (attachToBackup && (!alreadyPersisted)) |
251 | { | 293 | { |
252 | sceneObject.ForceInventoryPersistence(); | 294 | sceneObject.ForceInventoryPersistence(); |
@@ -336,6 +378,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
336 | /// </returns> | 378 | /// </returns> |
337 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 379 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
338 | { | 380 | { |
381 | if (sceneObject == null) | ||
382 | { | ||
383 | m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); | ||
384 | return false; | ||
385 | } | ||
339 | if (sceneObject.UUID == UUID.Zero) | 386 | if (sceneObject.UUID == UUID.Zero) |
340 | { | 387 | { |
341 | m_log.ErrorFormat( | 388 | m_log.ErrorFormat( |
@@ -470,6 +517,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
470 | m_updateList[obj.UUID] = obj; | 517 | m_updateList[obj.UUID] = obj; |
471 | } | 518 | } |
472 | 519 | ||
520 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
521 | { | ||
522 | if (OnAttachToBackup != null) | ||
523 | { | ||
524 | OnAttachToBackup(obj); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
529 | { | ||
530 | if (OnDetachFromBackup != null) | ||
531 | { | ||
532 | OnDetachFromBackup(obj); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | public void FireChangeBackup(SceneObjectGroup obj) | ||
537 | { | ||
538 | if (OnChangeBackup != null) | ||
539 | { | ||
540 | OnChangeBackup(obj); | ||
541 | } | ||
542 | } | ||
543 | |||
473 | /// <summary> | 544 | /// <summary> |
474 | /// Process all pending updates | 545 | /// Process all pending updates |
475 | /// </summary> | 546 | /// </summary> |
@@ -587,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
587 | 658 | ||
588 | Entities[presence.UUID] = presence; | 659 | Entities[presence.UUID] = presence; |
589 | 660 | ||
590 | lock (m_presenceLock) | 661 | m_scenePresencesLock.EnterWriteLock(); |
662 | try | ||
591 | { | 663 | { |
592 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 664 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
593 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 665 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -611,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
611 | m_scenePresenceMap = newmap; | 683 | m_scenePresenceMap = newmap; |
612 | m_scenePresenceArray = newlist; | 684 | m_scenePresenceArray = newlist; |
613 | } | 685 | } |
686 | finally | ||
687 | { | ||
688 | m_scenePresencesLock.ExitWriteLock(); | ||
689 | } | ||
614 | } | 690 | } |
615 | 691 | ||
616 | /// <summary> | 692 | /// <summary> |
@@ -625,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
625 | agentID); | 701 | agentID); |
626 | } | 702 | } |
627 | 703 | ||
628 | lock (m_presenceLock) | 704 | m_scenePresencesLock.EnterWriteLock(); |
705 | try | ||
629 | { | 706 | { |
630 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 707 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
631 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 708 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -647,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
647 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 724 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
648 | } | 725 | } |
649 | } | 726 | } |
727 | finally | ||
728 | { | ||
729 | m_scenePresencesLock.ExitWriteLock(); | ||
730 | } | ||
650 | } | 731 | } |
651 | 732 | ||
652 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 733 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -1208,6 +1289,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
1208 | 1289 | ||
1209 | #region Client Event handlers | 1290 | #region Client Event handlers |
1210 | 1291 | ||
1292 | protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) | ||
1293 | { | ||
1294 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1295 | ObjectChangeData data = (ObjectChangeData)odata; | ||
1296 | |||
1297 | if (part != null) | ||
1298 | { | ||
1299 | SceneObjectGroup grp = part.ParentGroup; | ||
1300 | if (grp != null) | ||
1301 | { | ||
1302 | if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId)) | ||
1303 | { | ||
1304 | part.StoreUndoState(data.change); // lets test only saving what we changed | ||
1305 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1306 | } | ||
1307 | } | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1211 | /// <summary> | 1311 | /// <summary> |
1212 | /// Update the scale of an individual prim. | 1312 | /// Update the scale of an individual prim. |
1213 | /// </summary> | 1313 | /// </summary> |
@@ -1222,7 +1322,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1222 | { | 1322 | { |
1223 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 1323 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) |
1224 | { | 1324 | { |
1325 | bool physbuild = false; | ||
1326 | if (part.ParentGroup.RootPart.PhysActor != null) | ||
1327 | { | ||
1328 | part.ParentGroup.RootPart.PhysActor.Building = true; | ||
1329 | physbuild = true; | ||
1330 | } | ||
1331 | |||
1225 | part.Resize(scale); | 1332 | part.Resize(scale); |
1333 | |||
1334 | if (physbuild) | ||
1335 | part.ParentGroup.RootPart.PhysActor.Building = false; | ||
1226 | } | 1336 | } |
1227 | } | 1337 | } |
1228 | } | 1338 | } |
@@ -1234,7 +1344,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1234 | { | 1344 | { |
1235 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1345 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1236 | { | 1346 | { |
1347 | bool physbuild = false; | ||
1348 | if (group.RootPart.PhysActor != null) | ||
1349 | { | ||
1350 | group.RootPart.PhysActor.Building = true; | ||
1351 | physbuild = true; | ||
1352 | } | ||
1353 | |||
1237 | group.GroupResize(scale); | 1354 | group.GroupResize(scale); |
1355 | |||
1356 | if (physbuild) | ||
1357 | group.RootPart.PhysActor.Building = false; | ||
1238 | } | 1358 | } |
1239 | } | 1359 | } |
1240 | } | 1360 | } |
@@ -1362,8 +1482,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1362 | { | 1482 | { |
1363 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1483 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1364 | { | 1484 | { |
1365 | if (m_parentScene.AttachmentsModule != null) | 1485 | // Set the new attachment point data in the object |
1366 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1486 | byte attachmentPoint = group.GetAttachmentPoint(); |
1487 | group.UpdateGroupPosition(pos); | ||
1488 | group.IsAttachment = false; | ||
1489 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1490 | group.AttachmentPoint = attachmentPoint; | ||
1491 | group.HasGroupChanged = true; | ||
1367 | } | 1492 | } |
1368 | else | 1493 | else |
1369 | { | 1494 | { |
@@ -1411,7 +1536,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1411 | /// <param name="SetPhantom"></param> | 1536 | /// <param name="SetPhantom"></param> |
1412 | /// <param name="remoteClient"></param> | 1537 | /// <param name="remoteClient"></param> |
1413 | protected internal void UpdatePrimFlags( | 1538 | protected internal void UpdatePrimFlags( |
1414 | uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) | 1539 | uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient) |
1415 | { | 1540 | { |
1416 | SceneObjectGroup group = GetGroupByPrim(localID); | 1541 | SceneObjectGroup group = GetGroupByPrim(localID); |
1417 | if (group != null) | 1542 | if (group != null) |
@@ -1419,7 +1544,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1419 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1544 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1420 | { | 1545 | { |
1421 | // VolumeDetect can't be set via UI and will always be off when a change is made there | 1546 | // VolumeDetect can't be set via UI and will always be off when a change is made there |
1422 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); | 1547 | if (PhysData.PhysShapeType == PhysShapeType.invalid) |
1548 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); | ||
1549 | else | ||
1550 | { | ||
1551 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1552 | if (part != null) | ||
1553 | part.UpdateExtraPhysics(PhysData); | ||
1554 | } | ||
1423 | } | 1555 | } |
1424 | } | 1556 | } |
1425 | } | 1557 | } |
@@ -1627,6 +1759,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1627 | /// <param name="childPrims"></param> | 1759 | /// <param name="childPrims"></param> |
1628 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) | 1760 | protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) |
1629 | { | 1761 | { |
1762 | if (root.KeyframeMotion != null) | ||
1763 | { | ||
1764 | root.KeyframeMotion.Stop(); | ||
1765 | root.KeyframeMotion = null; | ||
1766 | } | ||
1767 | |||
1630 | SceneObjectGroup parentGroup = root.ParentGroup; | 1768 | SceneObjectGroup parentGroup = root.ParentGroup; |
1631 | if (parentGroup == null) return; | 1769 | if (parentGroup == null) return; |
1632 | 1770 | ||
@@ -1635,8 +1773,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1635 | return; | 1773 | return; |
1636 | 1774 | ||
1637 | Monitor.Enter(m_updateLock); | 1775 | Monitor.Enter(m_updateLock); |
1776 | |||
1638 | try | 1777 | try |
1639 | { | 1778 | { |
1779 | parentGroup.areUpdatesSuspended = true; | ||
1780 | |||
1640 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1781 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1641 | 1782 | ||
1642 | // We do this in reverse to get the link order of the prims correct | 1783 | // We do this in reverse to get the link order of the prims correct |
@@ -1651,9 +1792,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1651 | // Make sure no child prim is set for sale | 1792 | // Make sure no child prim is set for sale |
1652 | // So that, on delink, no prims are unwittingly | 1793 | // So that, on delink, no prims are unwittingly |
1653 | // left for sale and sold off | 1794 | // left for sale and sold off |
1654 | child.RootPart.ObjectSaleType = 0; | 1795 | |
1655 | child.RootPart.SalePrice = 10; | 1796 | if (child != null) |
1656 | childGroups.Add(child); | 1797 | { |
1798 | child.RootPart.ObjectSaleType = 0; | ||
1799 | child.RootPart.SalePrice = 10; | ||
1800 | childGroups.Add(child); | ||
1801 | } | ||
1657 | } | 1802 | } |
1658 | 1803 | ||
1659 | foreach (SceneObjectGroup child in childGroups) | 1804 | foreach (SceneObjectGroup child in childGroups) |
@@ -1680,6 +1825,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1680 | } | 1825 | } |
1681 | finally | 1826 | finally |
1682 | { | 1827 | { |
1828 | lock (SceneObjectGroupsByLocalPartID) | ||
1829 | { | ||
1830 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1831 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1832 | } | ||
1833 | |||
1834 | parentGroup.areUpdatesSuspended = false; | ||
1835 | parentGroup.HasGroupChanged = true; | ||
1836 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1837 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1683 | Monitor.Exit(m_updateLock); | 1838 | Monitor.Exit(m_updateLock); |
1684 | } | 1839 | } |
1685 | } | 1840 | } |
@@ -1702,6 +1857,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1702 | { | 1857 | { |
1703 | if (part != null) | 1858 | if (part != null) |
1704 | { | 1859 | { |
1860 | if (part.KeyframeMotion != null) | ||
1861 | { | ||
1862 | part.KeyframeMotion.Stop(); | ||
1863 | part.KeyframeMotion = null; | ||
1864 | } | ||
1705 | if (part.ParentGroup.PrimCount != 1) // Skip single | 1865 | if (part.ParentGroup.PrimCount != 1) // Skip single |
1706 | { | 1866 | { |
1707 | if (part.LinkNum < 2) // Root | 1867 | if (part.LinkNum < 2) // Root |
@@ -1716,21 +1876,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1716 | 1876 | ||
1717 | SceneObjectGroup group = part.ParentGroup; | 1877 | SceneObjectGroup group = part.ParentGroup; |
1718 | if (!affectedGroups.Contains(group)) | 1878 | if (!affectedGroups.Contains(group)) |
1879 | { | ||
1880 | group.areUpdatesSuspended = true; | ||
1719 | affectedGroups.Add(group); | 1881 | affectedGroups.Add(group); |
1882 | } | ||
1720 | } | 1883 | } |
1721 | } | 1884 | } |
1722 | } | 1885 | } |
1723 | 1886 | ||
1724 | foreach (SceneObjectPart child in childParts) | 1887 | if (childParts.Count > 0) |
1725 | { | 1888 | { |
1726 | // Unlink all child parts from their groups | 1889 | foreach (SceneObjectPart child in childParts) |
1727 | // | 1890 | { |
1728 | child.ParentGroup.DelinkFromGroup(child, true); | 1891 | // Unlink all child parts from their groups |
1729 | 1892 | // | |
1730 | // These are not in affected groups and will not be | 1893 | child.ParentGroup.DelinkFromGroup(child, true); |
1731 | // handled further. Do the honors here. | 1894 | child.ParentGroup.HasGroupChanged = true; |
1732 | child.ParentGroup.HasGroupChanged = true; | 1895 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1733 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1896 | } |
1734 | } | 1897 | } |
1735 | 1898 | ||
1736 | foreach (SceneObjectPart root in rootParts) | 1899 | foreach (SceneObjectPart root in rootParts) |
@@ -1740,56 +1903,68 @@ namespace OpenSim.Region.Framework.Scenes | |||
1740 | // However, editing linked parts and unlinking may be different | 1903 | // However, editing linked parts and unlinking may be different |
1741 | // | 1904 | // |
1742 | SceneObjectGroup group = root.ParentGroup; | 1905 | SceneObjectGroup group = root.ParentGroup; |
1906 | group.areUpdatesSuspended = true; | ||
1743 | 1907 | ||
1744 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1908 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1745 | int numChildren = newSet.Count; | 1909 | int numChildren = newSet.Count; |
1746 | 1910 | ||
1911 | if (numChildren == 1) | ||
1912 | break; | ||
1913 | |||
1747 | // If there are prims left in a link set, but the root is | 1914 | // If there are prims left in a link set, but the root is |
1748 | // slated for unlink, we need to do this | 1915 | // slated for unlink, we need to do this |
1916 | // Unlink the remaining set | ||
1749 | // | 1917 | // |
1750 | if (numChildren != 1) | 1918 | bool sendEventsToRemainder = true; |
1751 | { | 1919 | if (numChildren > 1) |
1752 | // Unlink the remaining set | 1920 | sendEventsToRemainder = false; |
1753 | // | ||
1754 | bool sendEventsToRemainder = true; | ||
1755 | if (numChildren > 1) | ||
1756 | sendEventsToRemainder = false; | ||
1757 | 1921 | ||
1758 | foreach (SceneObjectPart p in newSet) | 1922 | foreach (SceneObjectPart p in newSet) |
1923 | { | ||
1924 | if (p != group.RootPart) | ||
1759 | { | 1925 | { |
1760 | if (p != group.RootPart) | 1926 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1761 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1927 | if (numChildren > 2) |
1928 | { | ||
1929 | p.ParentGroup.areUpdatesSuspended = true; | ||
1930 | } | ||
1931 | else | ||
1932 | { | ||
1933 | p.ParentGroup.HasGroupChanged = true; | ||
1934 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
1935 | } | ||
1762 | } | 1936 | } |
1937 | } | ||
1938 | |||
1939 | // If there is more than one prim remaining, we | ||
1940 | // need to re-link | ||
1941 | // | ||
1942 | if (numChildren > 2) | ||
1943 | { | ||
1944 | // Remove old root | ||
1945 | // | ||
1946 | if (newSet.Contains(root)) | ||
1947 | newSet.Remove(root); | ||
1763 | 1948 | ||
1764 | // If there is more than one prim remaining, we | 1949 | // Preserve link ordering |
1765 | // need to re-link | ||
1766 | // | 1950 | // |
1767 | if (numChildren > 2) | 1951 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) |
1768 | { | 1952 | { |
1769 | // Remove old root | 1953 | return a.LinkNum.CompareTo(b.LinkNum); |
1770 | // | 1954 | }); |
1771 | if (newSet.Contains(root)) | ||
1772 | newSet.Remove(root); | ||
1773 | |||
1774 | // Preserve link ordering | ||
1775 | // | ||
1776 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1777 | { | ||
1778 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1779 | }); | ||
1780 | 1955 | ||
1781 | // Determine new root | 1956 | // Determine new root |
1782 | // | 1957 | // |
1783 | SceneObjectPart newRoot = newSet[0]; | 1958 | SceneObjectPart newRoot = newSet[0]; |
1784 | newSet.RemoveAt(0); | 1959 | newSet.RemoveAt(0); |
1785 | 1960 | ||
1786 | foreach (SceneObjectPart newChild in newSet) | 1961 | foreach (SceneObjectPart newChild in newSet) |
1787 | newChild.ClearUpdateSchedule(); | 1962 | newChild.ClearUpdateSchedule(); |
1788 | 1963 | ||
1789 | LinkObjects(newRoot, newSet); | 1964 | newRoot.ParentGroup.areUpdatesSuspended = true; |
1790 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 1965 | LinkObjects(newRoot, newSet); |
1791 | affectedGroups.Add(newRoot.ParentGroup); | 1966 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1792 | } | 1967 | affectedGroups.Add(newRoot.ParentGroup); |
1793 | } | 1968 | } |
1794 | } | 1969 | } |
1795 | 1970 | ||
@@ -1797,8 +1972,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1797 | // | 1972 | // |
1798 | foreach (SceneObjectGroup g in affectedGroups) | 1973 | foreach (SceneObjectGroup g in affectedGroups) |
1799 | { | 1974 | { |
1975 | // Child prims that have been unlinked and deleted will | ||
1976 | // return unless the root is deleted. This will remove them | ||
1977 | // from the database. They will be rewritten immediately, | ||
1978 | // minus the rows for the unlinked child prims. | ||
1979 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1800 | g.TriggerScriptChangedEvent(Changed.LINK); | 1980 | g.TriggerScriptChangedEvent(Changed.LINK); |
1801 | g.HasGroupChanged = true; // Persist | 1981 | g.HasGroupChanged = true; // Persist |
1982 | g.areUpdatesSuspended = false; | ||
1802 | g.ScheduleGroupForFullUpdate(); | 1983 | g.ScheduleGroupForFullUpdate(); |
1803 | } | 1984 | } |
1804 | } | 1985 | } |
@@ -1900,9 +2081,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1900 | child.ApplyNextOwnerPermissions(); | 2081 | child.ApplyNextOwnerPermissions(); |
1901 | } | 2082 | } |
1902 | } | 2083 | } |
1903 | |||
1904 | copy.RootPart.ObjectSaleType = 0; | ||
1905 | copy.RootPart.SalePrice = 10; | ||
1906 | } | 2084 | } |
1907 | 2085 | ||
1908 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2086 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |