aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie Thielker2009-04-29 15:54:16 +0000
committerMelanie Thielker2009-04-29 15:54:16 +0000
commitd604cd284efc61af4616506830ff17ee52ff6e48 (patch)
tree94f26b6d1605f09b6c6ef0aef422a33b9eb77bbb
parentfixes exception thrown when client session is shutdown while (diff)
downloadopensim-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.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>