diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 303 |
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() |