diff options
author | Melanie Thielker | 2009-04-29 15:54:16 +0000 |
---|---|---|
committer | Melanie Thielker | 2009-04-29 15:54:16 +0000 |
commit | d604cd284efc61af4616506830ff17ee52ff6e48 (patch) | |
tree | 94f26b6d1605f09b6c6ef0aef422a33b9eb77bbb | |
parent | fixes exception thrown when client session is shutdown while (diff) | |
download | opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.zip opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.tar.gz opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.tar.bz2 opensim-SC-d604cd284efc61af4616506830ff17ee52ff6e48.tar.xz |
Again, completely revamp the unlink code to finally allow unlinking
arbitrary combinations of root and child prims from one or multiple
link sets. Please test throughly and consider things UNSTABLE until
this is proven out.
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 160 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 95 |
2 files changed, 131 insertions, 124 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 1e6955a..4b4461f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -1588,106 +1588,108 @@ namespace OpenSim.Region.Framework.Scenes | |||
1588 | 1588 | ||
1589 | protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) | 1589 | protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) |
1590 | { | 1590 | { |
1591 | SceneObjectGroup parentPrim = null; | 1591 | List<SceneObjectPart> childParts = new List<SceneObjectPart>(); |
1592 | // Find the root prim among the prim ids we've been given | 1592 | List<SceneObjectPart> rootParts = new List<SceneObjectPart>(); |
1593 | for (int i = 0; i < primIds.Count; i++) | 1593 | List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>(); |
1594 | // Look them all up in one go, since that is comparatively expensive | ||
1595 | // | ||
1596 | foreach (uint primID in primIds) | ||
1594 | { | 1597 | { |
1595 | // Get the group for this prim and check that it is the parent | 1598 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); |
1596 | parentPrim = GetGroupByPrim(primIds[i]); | 1599 | if (part != null) |
1597 | if (parentPrim != null && parentPrim.LocalId == primIds[i]) | ||
1598 | { | 1600 | { |
1599 | primIds.RemoveAt(i); | 1601 | if (part.LinkNum < 2) // Root or single |
1600 | break; | 1602 | rootParts.Add(part); |
1603 | else | ||
1604 | childParts.Add(part); | ||
1605 | |||
1606 | SceneObjectGroup group = part.ParentGroup; | ||
1607 | if (!affectedGroups.Contains(group)) | ||
1608 | affectedGroups.Add(group); | ||
1609 | } | ||
1610 | else | ||
1611 | { | ||
1612 | m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); | ||
1601 | } | 1613 | } |
1602 | } | 1614 | } |
1603 | 1615 | ||
1604 | if (parentPrim != null) | 1616 | foreach (SceneObjectPart child in childParts) |
1605 | { | 1617 | { |
1606 | foreach (uint childPrimId in primIds) | 1618 | // Unlink all child parts from their groups |
1607 | { | 1619 | // |
1608 | parentPrim.DelinkFromGroup(childPrimId, sendEvents); | 1620 | child.ParentGroup.DelinkFromGroup(child, sendEvents); |
1609 | } | 1621 | } |
1610 | 1622 | ||
1611 | if (parentPrim.Children.Count == 1) | 1623 | foreach (SceneObjectPart root in rootParts) |
1612 | { | 1624 | { |
1613 | // The link set has been completely torn down | 1625 | // In most cases, this will run only one time, and the prim |
1614 | // This is the case if you select a link set and delink | 1626 | // will be a solo prim |
1615 | // | 1627 | // However, editing linked parts and unlinking may be different |
1616 | parentPrim.RootPart.LinkNum = 0; | 1628 | // |
1617 | if (sendEvents) | 1629 | SceneObjectGroup group = root.ParentGroup; |
1618 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | 1630 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); |
1619 | } | 1631 | int numChildren = group.Children.Count; |
1620 | else | 1632 | |
1633 | // If there are prims left in a link set, but the root is | ||
1634 | // slated for unlink, we need to do this | ||
1635 | // | ||
1636 | if (numChildren != 1) | ||
1621 | { | 1637 | { |
1622 | // The link set has prims remaining. This path is taken | 1638 | // Unlink the remaining set |
1623 | // when a subset of a link set's prims are selected | ||
1624 | // and the root prim is part of that selection | ||
1625 | // | 1639 | // |
1626 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); | 1640 | bool sendEventsToRemainder = true; |
1641 | if (numChildren > 1) | ||
1642 | sendEventsToRemainder = false; | ||
1627 | 1643 | ||
1628 | List<uint> unlink_ids = new List<uint>(); | 1644 | foreach (SceneObjectPart p in newSet) |
1629 | foreach (SceneObjectPart unlink_part in parts) | 1645 | { |
1630 | unlink_ids.Add(unlink_part.LocalId); | 1646 | if (p != group.RootPart) |
1647 | group.DelinkFromGroup(p, sendEventsToRemainder); | ||
1648 | } | ||
1631 | 1649 | ||
1632 | // Tear down the remaining link set | 1650 | // If there is more than one prim remaining, we |
1651 | // need to re-link | ||
1633 | // | 1652 | // |
1634 | if (unlink_ids.Count == 2) | 1653 | if (numChildren > 2) |
1635 | { | 1654 | { |
1636 | DelinkObjects(unlink_ids, true); | 1655 | // Remove old root |
1637 | return; | 1656 | // |
1638 | } | 1657 | if (newSet.Contains(root)) |
1658 | newSet.Remove(root); | ||
1659 | |||
1660 | // Preserve link ordering | ||
1661 | // | ||
1662 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1663 | { | ||
1664 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1665 | }); | ||
1639 | 1666 | ||
1640 | DelinkObjects(unlink_ids, false); | 1667 | // Determine new root |
1668 | // | ||
1669 | SceneObjectPart newRoot = newSet[0]; | ||
1670 | newSet.RemoveAt(0); | ||
1641 | 1671 | ||
1642 | // Send event to root prim, then we're done with it | 1672 | List<uint> linkIDs = new List<uint>(); |
1643 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
1644 | 1673 | ||
1645 | unlink_ids.Remove(parentPrim.RootPart.LocalId); | 1674 | foreach (SceneObjectPart newChild in newSet) |
1675 | { | ||
1676 | newChild.UpdateFlag = 0; | ||
1677 | linkIDs.Add(newChild.LocalId); | ||
1678 | } | ||
1646 | 1679 | ||
1647 | foreach (uint localId in unlink_ids) | 1680 | LinkObjects(null, newRoot.LocalId, linkIDs); |
1648 | { | 1681 | if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1649 | SceneObjectPart nr = GetSceneObjectPart(localId); | 1682 | affectedGroups.Add(newRoot.ParentGroup); |
1650 | nr.UpdateFlag = 0; | ||
1651 | } | 1683 | } |
1652 | |||
1653 | uint newRoot = unlink_ids[0]; | ||
1654 | unlink_ids.Remove(newRoot); | ||
1655 | |||
1656 | LinkObjects(null, newRoot, unlink_ids); | ||
1657 | } | 1684 | } |
1658 | } | 1685 | } |
1659 | else | ||
1660 | { | ||
1661 | // The selected prims were all child prims. Edit linked parts | ||
1662 | // without the root prim selected will get us here | ||
1663 | // | ||
1664 | List<SceneObjectGroup> parentGroups = new List<SceneObjectGroup>(); | ||
1665 | 1686 | ||
1666 | // If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow | 1687 | // Finally, trigger events in the roots |
1667 | // We know that this is not the root prim now essentially, so we don't have to worry about remapping | 1688 | // |
1668 | // which one is the root prim | 1689 | foreach (SceneObjectGroup g in affectedGroups) |
1669 | bool delinkedSomething = false; | 1690 | { |
1670 | for (int i = 0; i < primIds.Count; i++) | 1691 | g.TriggerScriptChangedEvent(Changed.LINK); |
1671 | { | 1692 | g.ScheduleGroupForFullUpdate(); |
1672 | SceneObjectGroup parent = GetGroupByPrim(primIds[i]); | ||
1673 | parent.DelinkFromGroup(primIds[i]); | ||
1674 | delinkedSomething = true; | ||
1675 | if (!parentGroups.Contains(parent)) | ||
1676 | parentGroups.Add(parent); | ||
1677 | } | ||
1678 | if (!delinkedSomething) | ||
1679 | { | ||
1680 | m_log.InfoFormat("[SCENE]: " + | ||
1681 | "DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!", | ||
1682 | primIds); | ||
1683 | } | ||
1684 | else | ||
1685 | { | ||
1686 | foreach (SceneObjectGroup g in parentGroups) | ||
1687 | { | ||
1688 | g.TriggerScriptChangedEvent(Changed.LINK); | ||
1689 | } | ||
1690 | } | ||
1691 | } | 1693 | } |
1692 | } | 1694 | } |
1693 | 1695 | ||
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f8b4483..6dc331b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -2237,71 +2237,76 @@ namespace OpenSim.Region.Framework.Scenes | |||
2237 | { | 2237 | { |
2238 | SceneObjectPart linkPart = GetChildPart(partID); | 2238 | SceneObjectPart linkPart = GetChildPart(partID); |
2239 | 2239 | ||
2240 | if (null != linkPart) | 2240 | if (linkPart != null) |
2241 | { | 2241 | { |
2242 | linkPart.ClearUndoState(); | 2242 | DelinkFromGroup(linkPart, sendEvents); |
2243 | } | ||
2244 | else | ||
2245 | { | ||
2246 | m_log.InfoFormat("[SCENE OBJECT GROUP]: " + | ||
2247 | "DelinkFromGroup(): Child prim {0} not found in object {1}, {2}", | ||
2248 | partID, LocalId, UUID); | ||
2249 | } | ||
2250 | } | ||
2251 | |||
2252 | public void DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) | ||
2253 | { | ||
2254 | linkPart.ClearUndoState(); | ||
2243 | // m_log.DebugFormat( | 2255 | // m_log.DebugFormat( |
2244 | // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", | 2256 | // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", |
2245 | // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); | 2257 | // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); |
2246 | 2258 | ||
2247 | Quaternion worldRot = linkPart.GetWorldRotation(); | 2259 | Quaternion worldRot = linkPart.GetWorldRotation(); |
2248 | 2260 | ||
2249 | // Remove the part from this object | 2261 | // Remove the part from this object |
2250 | lock (m_parts) | 2262 | lock (m_parts) |
2251 | { | 2263 | { |
2252 | m_parts.Remove(linkPart.UUID); | 2264 | m_parts.Remove(linkPart.UUID); |
2253 | } | 2265 | } |
2254 | 2266 | ||
2255 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left | 2267 | if (m_parts.Count == 1 && RootPart != null) //Single prim is left |
2256 | RootPart.LinkNum = 0; | 2268 | RootPart.LinkNum = 0; |
2257 | else | 2269 | else |
2270 | { | ||
2271 | foreach (SceneObjectPart p in m_parts.Values) | ||
2258 | { | 2272 | { |
2259 | foreach (SceneObjectPart p in m_parts.Values) | 2273 | if (p.LinkNum > linkPart.LinkNum) |
2260 | { | 2274 | p.LinkNum--; |
2261 | if (p.LinkNum > linkPart.LinkNum) | ||
2262 | p.LinkNum--; | ||
2263 | } | ||
2264 | } | 2275 | } |
2276 | } | ||
2265 | 2277 | ||
2266 | linkPart.ParentID = 0; | 2278 | linkPart.ParentID = 0; |
2267 | linkPart.LinkNum = 0; | 2279 | linkPart.LinkNum = 0; |
2268 | 2280 | ||
2269 | if (linkPart.PhysActor != null) | 2281 | if (linkPart.PhysActor != null) |
2270 | { | 2282 | { |
2271 | m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2283 | m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
2272 | } | 2284 | } |
2273 | 2285 | ||
2274 | // We need to reset the child part's position | 2286 | // We need to reset the child part's position |
2275 | // ready for life as a separate object after being a part of another object | 2287 | // ready for life as a separate object after being a part of another object |
2276 | Quaternion parentRot = m_rootPart.RotationOffset; | 2288 | Quaternion parentRot = m_rootPart.RotationOffset; |
2277 | 2289 | ||
2278 | Vector3 axPos = linkPart.OffsetPosition; | 2290 | Vector3 axPos = linkPart.OffsetPosition; |
2279 | 2291 | ||
2280 | axPos *= parentRot; | 2292 | axPos *= parentRot; |
2281 | linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); | 2293 | linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); |
2282 | linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; | 2294 | linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; |
2283 | linkPart.OffsetPosition = new Vector3(0, 0, 0); | 2295 | linkPart.OffsetPosition = new Vector3(0, 0, 0); |
2284 | 2296 | ||
2285 | linkPart.RotationOffset = worldRot; | 2297 | linkPart.RotationOffset = worldRot; |
2286 | 2298 | ||
2287 | SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); | 2299 | SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); |
2288 | 2300 | ||
2289 | m_scene.AddNewSceneObject(objectGroup, true); | 2301 | m_scene.AddNewSceneObject(objectGroup, true); |
2290 | 2302 | ||
2291 | if (sendEvents) | 2303 | if (sendEvents) |
2292 | linkPart.TriggerScriptChangedEvent(Changed.LINK); | 2304 | linkPart.TriggerScriptChangedEvent(Changed.LINK); |
2293 | 2305 | ||
2294 | linkPart.Rezzed = RootPart.Rezzed; | 2306 | linkPart.Rezzed = RootPart.Rezzed; |
2295 | 2307 | ||
2296 | HasGroupChanged = true; | 2308 | HasGroupChanged = true; |
2297 | ScheduleGroupForFullUpdate(); | 2309 | ScheduleGroupForFullUpdate(); |
2298 | } | ||
2299 | else | ||
2300 | { | ||
2301 | m_log.InfoFormat("[SCENE OBJECT GROUP]: " + | ||
2302 | "DelinkFromGroup(): Child prim {0} not found in object {1}, {2}", | ||
2303 | partID, LocalId, UUID); | ||
2304 | } | ||
2305 | } | 2310 | } |
2306 | 2311 | ||
2307 | /// <summary> | 2312 | /// <summary> |