aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs160
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs95
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>