first pass on unlinking of objects. From Jay Clarke (IBM)

afrisby
Sean Dague 2007-11-13 19:57:11 +00:00
parent 448612db62
commit eb41ec00c9
8 changed files with 194 additions and 14 deletions

View File

@ -175,6 +175,8 @@ namespace OpenSim.Framework
public delegate void StartAnim(IClientAPI remoteClient, LLUUID animID, int seq);
public delegate void LinkObjects(uint parent, List<uint> children);
public delegate void DelinkObjects(List<uint> primIds);
public delegate void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY);
@ -290,6 +292,7 @@ namespace OpenSim.Framework
event SetAppearance OnSetAppearance;
event StartAnim OnStartAnim;
event LinkObjects OnLinkObjects;
event DelinkObjects OnDelinkObjects;
event RequestMapBlocks OnRequestMapBlocks;
event TeleportLocationRequest OnTeleportLocationRequest;
event DisconnectUser OnDisconnectUser;

View File

@ -58,6 +58,7 @@ namespace OpenSim.Region.ClientStack
public event StartAnim OnStartAnim;
public event Action<IClientAPI> OnRequestAvatarsData;
public event LinkObjects OnLinkObjects;
public event DelinkObjects OnDelinkObjects;
public event UpdateVector OnGrabObject;
public event ObjectSelect OnDeGrabObject;
public event ObjectDuplicate OnObjectDuplicate;

View File

@ -223,7 +223,7 @@ namespace OpenSim.Region.ClientStack
#region Objects/m_sceneObjects
case PacketType.ObjectLink:
// OpenSim.Framework.Console.MainLog.Instance.Verbose( Pack.ToString());
//OpenSim.Framework.Console.MainLog.Instance.Verbose( Pack.ToString());
ObjectLinkPacket link = (ObjectLinkPacket) Pack;
uint parentprimid = 0;
List<uint> childrenprims = new List<uint>();
@ -240,6 +240,26 @@ namespace OpenSim.Region.ClientStack
{
OnLinkObjects(parentprimid, childrenprims);
}
break;
case PacketType.ObjectDelink:
//OpenSim.Framework.Console.MainLog.Instance.Verbose( Pack.ToString());
ObjectDelinkPacket delink = (ObjectDelinkPacket) Pack;
// It appears the prim at index 0 is not always the root prim (for
// instance, when one prim of a link set has been edited independently
// of the others). Therefore, we'll pass all the ids onto the delink
// method for it to decide which is the root.
List<uint> prims = new List<uint>();
for (int i = 0; i < delink.ObjectData.Length; i++)
{
prims.Add(delink.ObjectData[i].ObjectLocalID);
}
if (OnDelinkObjects != null)
{
OnDelinkObjects(prims);
}
break;
case PacketType.ObjectAdd:
if (OnAddPrim != null)
@ -775,4 +795,4 @@ namespace OpenSim.Region.ClientStack
OutPacket(logReply);
}
}
}
}

View File

@ -536,6 +536,56 @@ namespace OpenSim.Region.Environment.Scenes
parenPrim.LinkToGroup(sceneObj);
}
}
/// <summary>
/// Delink a linkset
/// </summary>
/// <param name="prims"></param>
public void DelinkObjects(List<uint> primIds)
{
//OpenSim.Framework.Console.MainLog.Instance.Verbose("DelinkObjects()");
SceneObjectGroup parenPrim = null;
// Need a list of the SceneObjectGroup local ids
// XXX I'm anticipating that building this dictionary once is more efficient than
// repeated scanning of the Entity.Values for a large number of primIds. However, it might
// be more efficient yet to keep this dictionary permanently on hand.
Dictionary<uint, SceneObjectGroup> sceneObjects = new Dictionary<uint, SceneObjectGroup>();
foreach (EntityBase ent in Entities.Values)
{
if (ent is SceneObjectGroup)
{
SceneObjectGroup obj = (SceneObjectGroup)ent;
sceneObjects.Add(obj.LocalId, obj);
}
}
// Find the root prim among the prim ids we've been given
for (int i = 0; i < primIds.Count; i++)
{
if (sceneObjects.ContainsKey(primIds[i]))
{
parenPrim = sceneObjects[primIds[i]];
primIds.RemoveAt(i);
break;
}
}
if (parenPrim != null)
{
foreach (uint childPrimId in primIds)
{
parenPrim.DelinkFromGroup(childPrimId);
}
}
else
{
OpenSim.Framework.Console.MainLog.Instance.Verbose(
"DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!",
primIds);
}
}
/// <summary>
///

View File

@ -705,6 +705,7 @@ namespace OpenSim.Region.Environment.Scenes
client.OnObjectDescription += m_innerScene.PrimDescription;
client.OnObjectName += m_innerScene.PrimName;
client.OnLinkObjects += m_innerScene.LinkObjects;
client.OnDelinkObjects += m_innerScene.DelinkObjects;
client.OnObjectDuplicate += m_innerScene.DuplicateObject;
client.OnUpdatePrimFlags += m_innerScene.UpdatePrimFlags;
@ -1273,4 +1274,4 @@ namespace OpenSim.Region.Environment.Scenes
#endregion
}
}
}

View File

@ -222,6 +222,27 @@ namespace OpenSim.Region.Environment.Scenes
public SceneObjectGroup()
{
}
/// <summary>
/// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
/// The original SceneObjectPart will be used rather than a copy, preserving
/// its existing localID and UUID.
/// </summary>
public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part)
{
m_scene = scene;
m_regionHandle = regionHandle;
part.SetParent(this);
part.ParentID = 0;
m_parts.Add(part.UUID, part);
SetPartAsRoot(part);
AttachToBackup();
ScheduleGroupForFullUpdate();
}
/// <summary>
///
@ -594,10 +615,10 @@ namespace OpenSim.Region.Environment.Scenes
#region SceneGroupPart Methods
/// <summary>
///
/// Get a child part with a given UUID
/// </summary>
/// <param name="primID"></param>
/// <returns></returns>
/// <returns>null if a child part with the primID was not found</returns>
public SceneObjectPart GetChildPart(LLUUID primID)
{
SceneObjectPart childPart = null;
@ -609,10 +630,10 @@ namespace OpenSim.Region.Environment.Scenes
}
/// <summary>
///
/// Get a child part with a given local ID
/// </summary>
/// <param name="localID"></param>
/// <returns></returns>
/// <returns>null if a child part with the local ID was not found</returns>
public SceneObjectPart GetChildPart(uint localID)
{
foreach (SceneObjectPart part in m_parts.Values)
@ -717,13 +738,85 @@ namespace OpenSim.Region.Environment.Scenes
objectGroup.DeleteParts();
ScheduleGroupForFullUpdate();
}
/// <summary>
/// Delink the given prim from this group. The delinked prim is established as
/// an independent SceneObjectGroup.
/// </summary>
/// <param name="partID"></param>
public void DelinkFromGroup(uint partID)
{
SceneObjectPart linkPart = GetChildPart(partID);
if (null != linkPart)
{
// Remove the part from this object
m_parts.Remove(linkPart.UUID);
// We need to reset the child part's position
// ready for life as a separate object after being a part of another object
Quaternion parentRot
= new Quaternion(
m_rootPart.RotationOffset.W,
m_rootPart.RotationOffset.X,
m_rootPart.RotationOffset.Y,
m_rootPart.RotationOffset.Z);
Vector3 axPos
= new Vector3(
linkPart.OffsetPosition.X,
linkPart.OffsetPosition.Y,
linkPart.OffsetPosition.Z);
axPos = parentRot * axPos;
linkPart.OffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
linkPart.OffsetPosition = new LLVector3(0, 0, 0);
Quaternion oldRot
= new Quaternion(
linkPart.RotationOffset.W,
linkPart.RotationOffset.X,
linkPart.RotationOffset.Y,
linkPart.RotationOffset.Z);
Quaternion newRot = parentRot * oldRot;
linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
// Add physics information back to delinked part if appropriate
// XXX This is messy and should be refactorable with the similar section in
// SceneObjectPart.UpdatePrimFlags()
if (m_rootPart.PhysActor != null)
{
linkPart.PhysActor = m_scene.PhysScene.AddPrimShape(
linkPart.Name,
linkPart.Shape,
new PhysicsVector(linkPart.AbsolutePosition.X, linkPart.AbsolutePosition.Y,
linkPart.AbsolutePosition.Z),
new PhysicsVector(linkPart.Scale.X, linkPart.Scale.Y, linkPart.Scale.Z),
new Quaternion(linkPart.RotationOffset.W, linkPart.RotationOffset.X,
linkPart.RotationOffset.Y, linkPart.RotationOffset.Z),
m_rootPart.PhysActor.IsPhysical);
}
SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
m_scene.AddEntity(objectGroup);
ScheduleGroupForFullUpdate();
}
else
{
OpenSim.Framework.Console.MainLog.Instance.Verbose(
"DelinkFromGroup(): Child prim local id {0} not found in object with root prim id {1}",
partID, LocalId);
}
}
private void DetachFromBackup(SceneObjectGroup objectGroup)
{
m_scene.EventManager.OnBackup -= objectGroup.ProcessBackup;
}
private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation)
{
part.SetParent(this);
@ -1431,4 +1524,4 @@ namespace OpenSim.Region.Environment.Scenes
Text = text;
}
}
}
}

View File

@ -328,17 +328,28 @@ namespace OpenSim.Region.Environment.Scenes
if (m_updateTimes.ContainsKey(part.UUID))
{
ScenePartUpdate update = m_updateTimes[part.UUID];
if (update.LastFullUpdateTime < part.TimeStampFull)
// Two updates can occur with the same timestamp (especially
// since our timestamp resolution is to the nearest second). The first
// could have been sent in the last update - we still need to send the
// second here.
if (update.LastFullUpdateTime <= part.TimeStampFull)
{
//need to do a full update
part.SendFullUpdate(ControllingClient);
update.LastFullUpdateTime = (uint) Util.UnixTimeSinceEpoch();
// We'll update to the part's timestamp rather than the current to
// avoid the race condition whereby the next tick occurs while we are
// doing this update. If this happened, then subsequent updates which occurred
// on the same tick or the next tick of the last update would be ignored.
update.LastFullUpdateTime = part.TimeStampFull;
updateCount++;
}
else if (update.LastTerseUpdateTime < part.TimeStampTerse)
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{
part.SendTerseUpdate(ControllingClient);
update.LastTerseUpdateTime = (uint) Util.UnixTimeSinceEpoch();
update.LastTerseUpdateTime = part.TimeStampTerse;
updateCount++;
}
}
@ -348,7 +359,7 @@ namespace OpenSim.Region.Environment.Scenes
part.SendFullUpdate(ControllingClient);
ScenePartUpdate update = new ScenePartUpdate();
update.FullID = part.UUID;
update.LastFullUpdateTime = (uint) Util.UnixTimeSinceEpoch();
update.LastFullUpdateTime = part.TimeStampFull;
m_updateTimes.Add(part.UUID, update);
updateCount++;
}

View File

@ -57,6 +57,7 @@ namespace SimpleApp
public event SetAppearance OnSetAppearance;
public event StartAnim OnStartAnim;
public event LinkObjects OnLinkObjects;
public event DelinkObjects OnDelinkObjects;
public event RequestMapBlocks OnRequestMapBlocks;
public event TeleportLocationRequest OnTeleportLocationRequest;
public event DisconnectUser OnDisconnectUser;