diff options
-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> |