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.0.6.5-rc1
parent
84701701ef
commit
d604cd284e
|
@ -1588,106 +1588,108 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
|
protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
|
||||||
{
|
{
|
||||||
SceneObjectGroup parentPrim = null;
|
List<SceneObjectPart> childParts = new List<SceneObjectPart>();
|
||||||
// Find the root prim among the prim ids we've been given
|
List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
|
||||||
for (int i = 0; i < primIds.Count; i++)
|
List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
|
||||||
{
|
// Look them all up in one go, since that is comparatively expensive
|
||||||
// Get the group for this prim and check that it is the parent
|
|
||||||
parentPrim = GetGroupByPrim(primIds[i]);
|
|
||||||
if (parentPrim != null && parentPrim.LocalId == primIds[i])
|
|
||||||
{
|
|
||||||
primIds.RemoveAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentPrim != null)
|
|
||||||
{
|
|
||||||
foreach (uint childPrimId in primIds)
|
|
||||||
{
|
|
||||||
parentPrim.DelinkFromGroup(childPrimId, sendEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parentPrim.Children.Count == 1)
|
|
||||||
{
|
|
||||||
// The link set has been completely torn down
|
|
||||||
// This is the case if you select a link set and delink
|
|
||||||
//
|
//
|
||||||
parentPrim.RootPart.LinkNum = 0;
|
foreach (uint primID in primIds)
|
||||||
if (sendEvents)
|
{
|
||||||
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
|
SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID);
|
||||||
|
if (part != null)
|
||||||
|
{
|
||||||
|
if (part.LinkNum < 2) // Root or single
|
||||||
|
rootParts.Add(part);
|
||||||
|
else
|
||||||
|
childParts.Add(part);
|
||||||
|
|
||||||
|
SceneObjectGroup group = part.ParentGroup;
|
||||||
|
if (!affectedGroups.Contains(group))
|
||||||
|
affectedGroups.Add(group);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The link set has prims remaining. This path is taken
|
m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID);
|
||||||
// when a subset of a link set's prims are selected
|
}
|
||||||
// and the root prim is part of that selection
|
}
|
||||||
|
|
||||||
|
foreach (SceneObjectPart child in childParts)
|
||||||
|
{
|
||||||
|
// Unlink all child parts from their groups
|
||||||
//
|
//
|
||||||
List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
|
child.ParentGroup.DelinkFromGroup(child, sendEvents);
|
||||||
|
}
|
||||||
|
|
||||||
List<uint> unlink_ids = new List<uint>();
|
foreach (SceneObjectPart root in rootParts)
|
||||||
foreach (SceneObjectPart unlink_part in parts)
|
{
|
||||||
unlink_ids.Add(unlink_part.LocalId);
|
// In most cases, this will run only one time, and the prim
|
||||||
|
// will be a solo prim
|
||||||
// Tear down the remaining link set
|
// However, editing linked parts and unlinking may be different
|
||||||
//
|
//
|
||||||
if (unlink_ids.Count == 2)
|
SceneObjectGroup group = root.ParentGroup;
|
||||||
{
|
List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values);
|
||||||
DelinkObjects(unlink_ids, true);
|
int numChildren = group.Children.Count;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DelinkObjects(unlink_ids, false);
|
// If there are prims left in a link set, but the root is
|
||||||
|
// slated for unlink, we need to do this
|
||||||
// Send event to root prim, then we're done with it
|
|
||||||
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
|
|
||||||
|
|
||||||
unlink_ids.Remove(parentPrim.RootPart.LocalId);
|
|
||||||
|
|
||||||
foreach (uint localId in unlink_ids)
|
|
||||||
{
|
|
||||||
SceneObjectPart nr = GetSceneObjectPart(localId);
|
|
||||||
nr.UpdateFlag = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint newRoot = unlink_ids[0];
|
|
||||||
unlink_ids.Remove(newRoot);
|
|
||||||
|
|
||||||
LinkObjects(null, newRoot, unlink_ids);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The selected prims were all child prims. Edit linked parts
|
|
||||||
// without the root prim selected will get us here
|
|
||||||
//
|
//
|
||||||
List<SceneObjectGroup> parentGroups = new List<SceneObjectGroup>();
|
if (numChildren != 1)
|
||||||
|
{
|
||||||
|
// Unlink the remaining set
|
||||||
|
//
|
||||||
|
bool sendEventsToRemainder = true;
|
||||||
|
if (numChildren > 1)
|
||||||
|
sendEventsToRemainder = false;
|
||||||
|
|
||||||
// If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow
|
foreach (SceneObjectPart p in newSet)
|
||||||
// We know that this is not the root prim now essentially, so we don't have to worry about remapping
|
|
||||||
// which one is the root prim
|
|
||||||
bool delinkedSomething = false;
|
|
||||||
for (int i = 0; i < primIds.Count; i++)
|
|
||||||
{
|
{
|
||||||
SceneObjectGroup parent = GetGroupByPrim(primIds[i]);
|
if (p != group.RootPart)
|
||||||
parent.DelinkFromGroup(primIds[i]);
|
group.DelinkFromGroup(p, sendEventsToRemainder);
|
||||||
delinkedSomething = true;
|
|
||||||
if (!parentGroups.Contains(parent))
|
|
||||||
parentGroups.Add(parent);
|
|
||||||
}
|
}
|
||||||
if (!delinkedSomething)
|
|
||||||
|
// If there is more than one prim remaining, we
|
||||||
|
// need to re-link
|
||||||
|
//
|
||||||
|
if (numChildren > 2)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[SCENE]: " +
|
// Remove old root
|
||||||
"DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!",
|
//
|
||||||
primIds);
|
if (newSet.Contains(root))
|
||||||
|
newSet.Remove(root);
|
||||||
|
|
||||||
|
// Preserve link ordering
|
||||||
|
//
|
||||||
|
newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
|
||||||
|
{
|
||||||
|
return a.LinkNum.CompareTo(b.LinkNum);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Determine new root
|
||||||
|
//
|
||||||
|
SceneObjectPart newRoot = newSet[0];
|
||||||
|
newSet.RemoveAt(0);
|
||||||
|
|
||||||
|
List<uint> linkIDs = new List<uint>();
|
||||||
|
|
||||||
|
foreach (SceneObjectPart newChild in newSet)
|
||||||
|
{
|
||||||
|
newChild.UpdateFlag = 0;
|
||||||
|
linkIDs.Add(newChild.LocalId);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
LinkObjects(null, newRoot.LocalId, linkIDs);
|
||||||
foreach (SceneObjectGroup g in parentGroups)
|
if (!affectedGroups.Contains(newRoot.ParentGroup))
|
||||||
|
affectedGroups.Add(newRoot.ParentGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, trigger events in the roots
|
||||||
|
//
|
||||||
|
foreach (SceneObjectGroup g in affectedGroups)
|
||||||
{
|
{
|
||||||
g.TriggerScriptChangedEvent(Changed.LINK);
|
g.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
}
|
g.ScheduleGroupForFullUpdate();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2237,7 +2237,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
SceneObjectPart linkPart = GetChildPart(partID);
|
SceneObjectPart linkPart = GetChildPart(partID);
|
||||||
|
|
||||||
if (null != linkPart)
|
if (linkPart != null)
|
||||||
|
{
|
||||||
|
DelinkFromGroup(linkPart, sendEvents);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_log.InfoFormat("[SCENE OBJECT GROUP]: " +
|
||||||
|
"DelinkFromGroup(): Child prim {0} not found in object {1}, {2}",
|
||||||
|
partID, LocalId, UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents)
|
||||||
{
|
{
|
||||||
linkPart.ClearUndoState();
|
linkPart.ClearUndoState();
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
|
@ -2296,13 +2308,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
HasGroupChanged = true;
|
HasGroupChanged = true;
|
||||||
ScheduleGroupForFullUpdate();
|
ScheduleGroupForFullUpdate();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
m_log.InfoFormat("[SCENE OBJECT GROUP]: " +
|
|
||||||
"DelinkFromGroup(): Child prim {0} not found in object {1}, {2}",
|
|
||||||
partID, LocalId, UUID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop this object from being persisted over server restarts.
|
/// Stop this object from being persisted over server restarts.
|
||||||
|
|
Loading…
Reference in New Issue