Thank you, dslake, for a patch that converts many of the linear searches
in SceneGraph to fast dictionary lookups. Includes a regression fix for attachments by myself. Fixes Mantis #33120.6.5-rc1
parent
87ce5ea0eb
commit
cc86df4a3f
|
@ -233,12 +233,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
get { return m_defaultScriptEngine; }
|
get { return m_defaultScriptEngine; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local reference to the objects in the scene (which are held in the scenegraph)
|
|
||||||
// public Dictionary<UUID, SceneObjectGroup> Objects
|
|
||||||
// {
|
|
||||||
// get { return m_sceneGraph.SceneObjects; }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Reference to all of the agents in the scene (root and child)
|
// Reference to all of the agents in the scene (root and child)
|
||||||
protected Dictionary<UUID, ScenePresence> m_scenePresences
|
protected Dictionary<UUID, ScenePresence> m_scenePresences
|
||||||
{
|
{
|
||||||
|
@ -246,12 +240,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
set { m_sceneGraph.ScenePresences = value; }
|
set { m_sceneGraph.ScenePresences = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// protected Dictionary<UUID, SceneObjectGroup> m_sceneObjects
|
|
||||||
// {
|
|
||||||
// get { return m_sceneGraph.SceneObjects; }
|
|
||||||
// set { m_sceneGraph.SceneObjects = value; }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public EntityManager Entities
|
public EntityManager Entities
|
||||||
{
|
{
|
||||||
get { return m_sceneGraph.Entities; }
|
get { return m_sceneGraph.Entities; }
|
||||||
|
@ -3492,7 +3480,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal void jointMoved(PhysicsJoint joint)
|
protected internal void jointMoved(PhysicsJoint joint)
|
||||||
{
|
{
|
||||||
// m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked
|
// m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked
|
||||||
// FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
|
|
||||||
SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
|
SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
|
||||||
if (jointProxyObject == null)
|
if (jointProxyObject == null)
|
||||||
{
|
{
|
||||||
|
@ -3555,7 +3542,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal void jointDeactivated(PhysicsJoint joint)
|
protected internal void jointDeactivated(PhysicsJoint joint)
|
||||||
{
|
{
|
||||||
//m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene);
|
//m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene);
|
||||||
// FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
|
|
||||||
SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
|
SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
|
||||||
if (jointProxyObject == null)
|
if (jointProxyObject == null)
|
||||||
{
|
{
|
||||||
|
@ -3580,7 +3566,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// from within the OdePhysicsScene.
|
// from within the OdePhysicsScene.
|
||||||
public void jointErrorMessage(PhysicsJoint joint, string message)
|
public void jointErrorMessage(PhysicsJoint joint, string message)
|
||||||
{
|
{
|
||||||
// FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
|
|
||||||
if (joint != null)
|
if (joint != null)
|
||||||
{
|
{
|
||||||
if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages)
|
if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages)
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
protected RegionInfo m_regInfo;
|
protected RegionInfo m_regInfo;
|
||||||
protected Scene m_parentScene;
|
protected Scene m_parentScene;
|
||||||
protected List<EntityBase> m_updateList = new List<EntityBase>();
|
protected Dictionary<UUID, EntityBase> m_updateList = new Dictionary<UUID, EntityBase>();
|
||||||
protected int m_numRootAgents = 0;
|
protected int m_numRootAgents = 0;
|
||||||
protected int m_numPrim = 0;
|
protected int m_numPrim = 0;
|
||||||
protected int m_numChildAgents = 0;
|
protected int m_numChildAgents = 0;
|
||||||
|
@ -90,6 +90,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
protected internal PhysicsScene _PhyScene;
|
protected internal PhysicsScene _PhyScene;
|
||||||
|
|
||||||
|
protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalID = new Dictionary<uint, SceneObjectGroup>();
|
||||||
|
protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
|
||||||
|
private readonly Object m_dictionary_lock = new Object();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
protected internal SceneGraph(Scene parent, RegionInfo regInfo)
|
protected internal SceneGraph(Scene parent, RegionInfo regInfo)
|
||||||
|
@ -126,6 +130,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
ScenePresences.Clear();
|
ScenePresences.Clear();
|
||||||
}
|
}
|
||||||
|
lock (m_dictionary_lock)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullID.Clear();
|
||||||
|
SceneObjectGroupsByLocalID.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
Entities.Clear();
|
Entities.Clear();
|
||||||
}
|
}
|
||||||
|
@ -300,6 +309,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
if (OnObjectCreate != null)
|
if (OnObjectCreate != null)
|
||||||
OnObjectCreate(sceneObject);
|
OnObjectCreate(sceneObject);
|
||||||
|
|
||||||
|
lock (m_dictionary_lock)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
|
||||||
|
SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
|
||||||
|
foreach (SceneObjectPart part in sceneObject.Children.Values)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullID[part.UUID] = sceneObject;
|
||||||
|
SceneObjectGroupsByLocalID[part.LocalId] = sceneObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -329,6 +349,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (OnObjectRemove != null)
|
if (OnObjectRemove != null)
|
||||||
OnObjectRemove(Entities[uuid]);
|
OnObjectRemove(Entities[uuid]);
|
||||||
|
|
||||||
|
lock (m_dictionary_lock)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullID.Remove(uuid);
|
||||||
|
SceneObjectGroupsByLocalID.Remove(((SceneObjectGroup)Entities[uuid]).LocalId);
|
||||||
|
}
|
||||||
Entities.Remove(uuid);
|
Entities.Remove(uuid);
|
||||||
//SceneObjectGroup part;
|
//SceneObjectGroup part;
|
||||||
//((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
|
//((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
|
||||||
|
@ -349,10 +374,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
lock (m_updateList)
|
lock (m_updateList)
|
||||||
{
|
{
|
||||||
if (!m_updateList.Contains(obj))
|
m_updateList[obj.UUID] = obj;
|
||||||
{
|
|
||||||
m_updateList.Add(obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,26 +383,28 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected internal void ProcessUpdates()
|
protected internal void ProcessUpdates()
|
||||||
{
|
{
|
||||||
|
Dictionary<UUID, EntityBase> updates;
|
||||||
|
// Some updates add more updates to the updateList.
|
||||||
|
// Get the current list of updates and clear the list before iterating
|
||||||
lock (m_updateList)
|
lock (m_updateList)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_updateList.Count; i++)
|
updates = new Dictionary<UUID, EntityBase>(m_updateList);
|
||||||
{
|
|
||||||
EntityBase entity = m_updateList[i];
|
|
||||||
|
|
||||||
// Don't abort the whole update if one entity happens to give us an exception.
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_updateList[i].Update();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat(
|
|
||||||
"[INNER SCENE]: Failed to update {0}, {1} - {2}", entity.Name, entity.UUID, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_updateList.Clear();
|
m_updateList.Clear();
|
||||||
}
|
}
|
||||||
|
// Go through all timers
|
||||||
|
foreach (KeyValuePair<UUID, EntityBase> kvp in updates)
|
||||||
|
{
|
||||||
|
// Don't abort the whole update if one entity happens to give us an exception.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
kvp.Value.Update();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.ErrorFormat(
|
||||||
|
"[INNER SCENE]: Failed to update {0}, {1} - {2}", kvp.Value.Name, kvp.Value.UUID, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal void AddPhysicalPrim(int number)
|
protected internal void AddPhysicalPrim(int number)
|
||||||
|
@ -405,38 +429,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void DropObject(uint objectLocalID, IClientAPI remoteClient)
|
public void DropObject(uint objectLocalID, IClientAPI remoteClient)
|
||||||
{
|
{
|
||||||
List<EntityBase> EntityList = GetEntities();
|
SceneObjectGroup group = GetGroupByPrim(objectLocalID);
|
||||||
|
if (group != null)
|
||||||
foreach (EntityBase obj in EntityList)
|
|
||||||
{
|
{
|
||||||
if (obj is SceneObjectGroup)
|
m_parentScene.DetachSingleAttachmentToGround(group.UUID, remoteClient);
|
||||||
{
|
|
||||||
if (((SceneObjectGroup)obj).LocalId == objectLocalID)
|
|
||||||
{
|
|
||||||
SceneObjectGroup group = (SceneObjectGroup)obj;
|
|
||||||
|
|
||||||
m_parentScene.DetachSingleAttachmentToGround(group.UUID,remoteClient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient)
|
protected internal void DetachObject(uint objectLocalID, IClientAPI remoteClient)
|
||||||
{
|
{
|
||||||
List<EntityBase> EntityList = GetEntities();
|
SceneObjectGroup group = GetGroupByPrim(objectLocalID);
|
||||||
|
if( group != null )
|
||||||
foreach (EntityBase obj in EntityList)
|
|
||||||
{
|
{
|
||||||
if (obj is SceneObjectGroup)
|
//group.DetachToGround();
|
||||||
{
|
m_parentScene.DetachSingleAttachmentToInv(group.GetFromAssetID(),remoteClient);
|
||||||
if (((SceneObjectGroup)obj).LocalId == objectLocalID)
|
|
||||||
{
|
|
||||||
SceneObjectGroup group = (SceneObjectGroup)obj;
|
|
||||||
|
|
||||||
//group.DetachToGround();
|
|
||||||
m_parentScene.DetachSingleAttachmentToInv(group.GetFromAssetID(),remoteClient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,20 +459,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal void HandleObjectGroupUpdate(
|
protected internal void HandleObjectGroupUpdate(
|
||||||
IClientAPI remoteClient, UUID GroupID, uint objectLocalID, UUID Garbage)
|
IClientAPI remoteClient, UUID GroupID, uint objectLocalID, UUID Garbage)
|
||||||
{
|
{
|
||||||
List<EntityBase> EntityList = GetEntities();
|
SceneObjectGroup group = GetGroupByPrim(objectLocalID);
|
||||||
|
if( group != null )
|
||||||
foreach (EntityBase obj in EntityList)
|
|
||||||
{
|
{
|
||||||
if (obj is SceneObjectGroup)
|
if (group.OwnerID == remoteClient.AgentId)
|
||||||
{
|
group.SetGroup(GroupID, remoteClient);
|
||||||
if (((SceneObjectGroup)obj).LocalId == objectLocalID)
|
|
||||||
{
|
|
||||||
SceneObjectGroup group = (SceneObjectGroup)obj;
|
|
||||||
|
|
||||||
if (group.OwnerID == remoteClient.AgentId)
|
|
||||||
group.SetGroup(GroupID, remoteClient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,19 +524,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (itemID == UUID.Zero) // If this happened, someone made a mistake....
|
if (itemID == UUID.Zero) // If this happened, someone made a mistake....
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List<EntityBase> EntityList = GetEntities();
|
// We can NOT use the dictionries here, as we are looking
|
||||||
|
// for an entity by the fromAssetID, which is NOT the prim UUID
|
||||||
|
//
|
||||||
|
List<EntityBase> detachEntities = GetEntities();
|
||||||
|
SceneObjectGroup group;
|
||||||
|
|
||||||
foreach (EntityBase obj in EntityList)
|
foreach (EntityBase entity in detachEntities)
|
||||||
{
|
{
|
||||||
if (obj is SceneObjectGroup)
|
if (entity is SceneObjectGroup)
|
||||||
{
|
{
|
||||||
if (((SceneObjectGroup)obj).GetFromAssetID() == itemID)
|
group = (SceneObjectGroup)entity;
|
||||||
|
if (group.GetFromAssetID() == itemID)
|
||||||
{
|
{
|
||||||
SceneObjectGroup group = (SceneObjectGroup)obj;
|
|
||||||
group.DetachToInventoryPrep();
|
group.DetachToInventoryPrep();
|
||||||
m_log.Debug("[DETACH]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
|
m_log.Debug("[DETACH]: Saving attachpoint: " +
|
||||||
m_parentScene.updateKnownAsset(remoteClient, group, group.GetFromAssetID(), group.OwnerID);
|
((uint)group.GetAttachmentPoint()).ToString());
|
||||||
|
m_parentScene.updateKnownAsset(remoteClient, group,
|
||||||
|
group.GetFromAssetID(), group.OwnerID);
|
||||||
m_parentScene.DeleteSceneObject(group, false);
|
m_parentScene.DeleteSceneObject(group, false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,73 +552,61 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal void AttachObject(
|
protected internal void AttachObject(
|
||||||
IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent)
|
IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent)
|
||||||
{
|
{
|
||||||
List<EntityBase> EntityList = GetEntities();
|
SceneObjectGroup group = GetGroupByPrim(objectLocalID);
|
||||||
foreach (EntityBase obj in EntityList)
|
if( group != null )
|
||||||
{
|
{
|
||||||
if (obj is SceneObjectGroup)
|
if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId))
|
||||||
{
|
{
|
||||||
if (((SceneObjectGroup)obj).LocalId == objectLocalID)
|
// If the attachment point isn't the same as the one previously used
|
||||||
|
// set it's offset position = 0 so that it appears on the attachment point
|
||||||
|
// and not in a weird location somewhere unknown.
|
||||||
|
if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint())
|
||||||
{
|
{
|
||||||
SceneObjectGroup group = (SceneObjectGroup)obj;
|
attachPos = Vector3.Zero;
|
||||||
if (m_parentScene.Permissions.CanTakeObject(obj.UUID, remoteClient.AgentId))
|
|
||||||
{
|
|
||||||
// If the attachment point isn't the same as the one previously used
|
|
||||||
// set it's offset position = 0 so that it appears on the attachment point
|
|
||||||
// and not in a weird location somewhere unknown.
|
|
||||||
if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint())
|
|
||||||
{
|
|
||||||
|
|
||||||
attachPos = Vector3.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AttachmentPt 0 means the client chose to 'wear' the attachment.
|
|
||||||
if (AttachmentPt == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check object for stored attachment point
|
|
||||||
AttachmentPt = (uint)group.GetAttachmentPoint();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we still didn't find a suitable attachment point.......
|
|
||||||
if (AttachmentPt == 0)
|
|
||||||
{
|
|
||||||
// Stick it on left hand with Zero Offset from the attachment point.
|
|
||||||
AttachmentPt = (uint)AttachmentPoint.LeftHand;
|
|
||||||
attachPos = Vector3.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
group.SetAttachmentPoint(Convert.ToByte(AttachmentPt));
|
|
||||||
group.AbsolutePosition = attachPos;
|
|
||||||
|
|
||||||
// Saves and gets assetID
|
|
||||||
UUID itemId;
|
|
||||||
|
|
||||||
if (group.GetFromAssetID() == UUID.Zero)
|
|
||||||
{
|
|
||||||
m_parentScene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itemId = group.GetFromAssetID();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group);
|
|
||||||
|
|
||||||
group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent);
|
|
||||||
// In case it is later dropped again, don't let
|
|
||||||
// it get cleaned up
|
|
||||||
//
|
|
||||||
group.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
|
|
||||||
group.HasGroupChanged = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AttachmentPt 0 means the client chose to 'wear' the attachment.
|
||||||
|
if (AttachmentPt == 0)
|
||||||
|
{
|
||||||
|
// Check object for stored attachment point
|
||||||
|
AttachmentPt = (uint)group.GetAttachmentPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we still didn't find a suitable attachment point.......
|
||||||
|
if (AttachmentPt == 0)
|
||||||
|
{
|
||||||
|
// Stick it on left hand with Zero Offset from the attachment point.
|
||||||
|
AttachmentPt = (uint)AttachmentPoint.LeftHand;
|
||||||
|
attachPos = Vector3.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
group.SetAttachmentPoint(Convert.ToByte(AttachmentPt));
|
||||||
|
group.AbsolutePosition = attachPos;
|
||||||
|
|
||||||
|
// Saves and gets assetID
|
||||||
|
UUID itemId;
|
||||||
|
|
||||||
|
if (group.GetFromAssetID() == UUID.Zero)
|
||||||
|
{
|
||||||
|
m_parentScene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
itemId = group.GetFromAssetID();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group);
|
||||||
|
|
||||||
|
group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent);
|
||||||
|
// In case it is later dropped again, don't let
|
||||||
|
// it get cleaned up
|
||||||
|
//
|
||||||
|
group.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
|
||||||
|
group.HasGroupChanged = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -864,6 +856,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return Entities[localID] as SceneObjectGroup;
|
return Entities[localID] as SceneObjectGroup;
|
||||||
|
|
||||||
//m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
|
//m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
|
||||||
|
SceneObjectGroup sog;
|
||||||
|
lock (SceneObjectGroupsByLocalID)
|
||||||
|
{
|
||||||
|
if (SceneObjectGroupsByLocalID.TryGetValue(localID, out sog))
|
||||||
|
{
|
||||||
|
return sog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<EntityBase> EntityList = GetEntities();
|
List<EntityBase> EntityList = GetEntities();
|
||||||
foreach (EntityBase ent in EntityList)
|
foreach (EntityBase ent in EntityList)
|
||||||
{
|
{
|
||||||
|
@ -871,7 +872,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (ent is SceneObjectGroup)
|
if (ent is SceneObjectGroup)
|
||||||
{
|
{
|
||||||
if (((SceneObjectGroup)ent).HasChildPrim(localID))
|
if (((SceneObjectGroup)ent).HasChildPrim(localID))
|
||||||
return (SceneObjectGroup)ent;
|
{
|
||||||
|
sog = (SceneObjectGroup)ent;
|
||||||
|
lock (SceneObjectGroupsByLocalID)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByLocalID[localID] = sog;
|
||||||
|
}
|
||||||
|
return sog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -884,6 +892,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <returns>null if no scene object group containing that prim is found</returns>
|
/// <returns>null if no scene object group containing that prim is found</returns>
|
||||||
private SceneObjectGroup GetGroupByPrim(UUID fullID)
|
private SceneObjectGroup GetGroupByPrim(UUID fullID)
|
||||||
{
|
{
|
||||||
|
SceneObjectGroup sog;
|
||||||
|
lock (SceneObjectGroupsByFullID)
|
||||||
|
{
|
||||||
|
if (SceneObjectGroupsByFullID.TryGetValue(fullID, out sog))
|
||||||
|
{
|
||||||
|
return sog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<EntityBase> EntityList = GetEntities();
|
List<EntityBase> EntityList = GetEntities();
|
||||||
|
|
||||||
foreach (EntityBase ent in EntityList)
|
foreach (EntityBase ent in EntityList)
|
||||||
|
@ -891,7 +908,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
if (ent is SceneObjectGroup)
|
if (ent is SceneObjectGroup)
|
||||||
{
|
{
|
||||||
if (((SceneObjectGroup)ent).HasChildPrim(fullID))
|
if (((SceneObjectGroup)ent).HasChildPrim(fullID))
|
||||||
return (SceneObjectGroup)ent;
|
{
|
||||||
|
sog = (SceneObjectGroup)ent;
|
||||||
|
lock (SceneObjectGroupsByFullID)
|
||||||
|
{
|
||||||
|
SceneObjectGroupsByFullID[fullID] = sog;
|
||||||
|
}
|
||||||
|
return sog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -930,11 +954,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal SceneObjectPart GetSceneObjectPart(uint localID)
|
protected internal SceneObjectPart GetSceneObjectPart(uint localID)
|
||||||
{
|
{
|
||||||
SceneObjectGroup group = GetGroupByPrim(localID);
|
SceneObjectGroup group = GetGroupByPrim(localID);
|
||||||
|
if (group == null)
|
||||||
if (group != null)
|
|
||||||
return group.GetChildPart(localID);
|
|
||||||
else
|
|
||||||
return null;
|
return null;
|
||||||
|
return group.GetChildPart(localID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -972,11 +994,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
protected internal SceneObjectPart GetSceneObjectPart(UUID fullID)
|
protected internal SceneObjectPart GetSceneObjectPart(UUID fullID)
|
||||||
{
|
{
|
||||||
SceneObjectGroup group = GetGroupByPrim(fullID);
|
SceneObjectGroup group = GetGroupByPrim(fullID);
|
||||||
|
if (group == null)
|
||||||
if (group != null)
|
|
||||||
return group.GetChildPart(fullID);
|
|
||||||
else
|
|
||||||
return null;
|
return null;
|
||||||
|
return group.GetChildPart(fullID);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
|
protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
|
||||||
|
@ -1503,43 +1523,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="client"></param>
|
/// <param name="client"></param>
|
||||||
/// <param name="parentPrim"></param>
|
/// <param name="parentPrim"></param>
|
||||||
/// <param name="childPrims"></param>
|
/// <param name="childPrims"></param>
|
||||||
protected internal void LinkObjects(IClientAPI client, uint parentPrim, List<uint> childPrims)
|
protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds)
|
||||||
{
|
{
|
||||||
List<EntityBase> EntityList = GetEntities();
|
SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId);
|
||||||
|
|
||||||
SceneObjectGroup parenPrim = null;
|
List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
|
||||||
foreach (EntityBase ent in EntityList)
|
if (parentGroup != null)
|
||||||
{
|
|
||||||
if (ent is SceneObjectGroup)
|
|
||||||
{
|
|
||||||
if (((SceneObjectGroup)ent).LocalId == parentPrim)
|
|
||||||
{
|
|
||||||
parenPrim = (SceneObjectGroup)ent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<SceneObjectGroup> children = new List<SceneObjectGroup>();
|
|
||||||
if (parenPrim != null)
|
|
||||||
{
|
{
|
||||||
// We do this in reverse to get the link order of the prims correct
|
// We do this in reverse to get the link order of the prims correct
|
||||||
for (int i = childPrims.Count - 1; i >= 0; i--)
|
for (int i = childPrimIds.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
foreach (EntityBase ent in EntityList)
|
SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]);
|
||||||
|
if( child != null )
|
||||||
{
|
{
|
||||||
if (ent is SceneObjectGroup)
|
// Make sure no child prim is set for sale
|
||||||
{
|
// So that, on delink, no prims are unwittingly
|
||||||
if (((SceneObjectGroup)ent).LocalId == childPrims[i])
|
// left for sale and sold off
|
||||||
{
|
child.RootPart.ObjectSaleType = 0;
|
||||||
// Make sure no child prim is set for sale
|
child.RootPart.SalePrice = 10;
|
||||||
// So that, on delink, no prims are unwittingly
|
childGroups.Add(child);
|
||||||
// left for sale and sold off
|
|
||||||
((SceneObjectGroup)ent).RootPart.ObjectSaleType = 0;
|
|
||||||
((SceneObjectGroup)ent).RootPart.SalePrice = 10;
|
|
||||||
children.Add((SceneObjectGroup)ent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1548,29 +1550,29 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return; // parent is null so not in this region
|
return; // parent is null so not in this region
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (SceneObjectGroup sceneObj in children)
|
foreach (SceneObjectGroup child in childGroups)
|
||||||
{
|
{
|
||||||
parenPrim.LinkToGroup(sceneObj);
|
parentGroup.LinkToGroup(child);
|
||||||
|
|
||||||
// this is here so physics gets updated!
|
// this is here so physics gets updated!
|
||||||
// Don't remove! Bad juju! Stay away! or fix physics!
|
// Don't remove! Bad juju! Stay away! or fix physics!
|
||||||
sceneObj.AbsolutePosition = sceneObj.AbsolutePosition;
|
child.AbsolutePosition = child.AbsolutePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to explicitly resend the newly link prim's object properties since no other actions
|
// We need to explicitly resend the newly link prim's object properties since no other actions
|
||||||
// occur on link to invoke this elsewhere (such as object selection)
|
// occur on link to invoke this elsewhere (such as object selection)
|
||||||
parenPrim.RootPart.AddFlag(PrimFlags.CreateSelected);
|
parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected);
|
||||||
parenPrim.TriggerScriptChangedEvent(Changed.LINK);
|
parentGroup.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
|
|
||||||
if (client != null)
|
if (client != null)
|
||||||
{
|
{
|
||||||
parenPrim.GetProperties(client);
|
parentGroup.GetProperties(client);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (ScenePresence p in GetScenePresences())
|
foreach (ScenePresence p in GetScenePresences())
|
||||||
{
|
{
|
||||||
parenPrim.GetProperties(p.ControllingClient);
|
parentGroup.GetProperties(p.ControllingClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1586,58 +1588,34 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
|
protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
|
||||||
{
|
{
|
||||||
SceneObjectGroup parenPrim = null;
|
SceneObjectGroup parentPrim = 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>();
|
|
||||||
|
|
||||||
List<EntityBase> EntityList = GetEntities();
|
|
||||||
foreach (EntityBase ent in EntityList)
|
|
||||||
{
|
|
||||||
if (ent is SceneObjectGroup)
|
|
||||||
{
|
|
||||||
SceneObjectGroup obj = (SceneObjectGroup)ent;
|
|
||||||
// Nasty one. Can't unlink anything in the sim
|
|
||||||
// If a duplicate local ID sneaks in
|
|
||||||
// So, check it here!
|
|
||||||
//
|
|
||||||
if (!sceneObjects.ContainsKey(obj.LocalId))
|
|
||||||
sceneObjects.Add(obj.LocalId, obj);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the root prim among the prim ids we've been given
|
// Find the root prim among the prim ids we've been given
|
||||||
for (int i = 0; i < primIds.Count; i++)
|
for (int i = 0; i < primIds.Count; i++)
|
||||||
{
|
{
|
||||||
|
// Get the group for this prim and check that it is the parent
|
||||||
if (sceneObjects.ContainsKey(primIds[i]))
|
parentPrim = GetGroupByPrim(primIds[i]);
|
||||||
|
if (parentPrim != null && parentPrim.LocalId == primIds[i])
|
||||||
{
|
{
|
||||||
parenPrim = sceneObjects[primIds[i]];
|
|
||||||
primIds.RemoveAt(i);
|
primIds.RemoveAt(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parenPrim != null)
|
if (parentPrim != null)
|
||||||
{
|
{
|
||||||
foreach (uint childPrimId in primIds)
|
foreach (uint childPrimId in primIds)
|
||||||
{
|
{
|
||||||
parenPrim.DelinkFromGroup(childPrimId, sendEvents);
|
parentPrim.DelinkFromGroup(childPrimId, sendEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parenPrim.Children.Count == 1)
|
if (parentPrim.Children.Count == 1)
|
||||||
{
|
{
|
||||||
// The link set has been completely torn down
|
// The link set has been completely torn down
|
||||||
// This is the case if you select a link set and delink
|
// This is the case if you select a link set and delink
|
||||||
//
|
//
|
||||||
parenPrim.RootPart.LinkNum = 0;
|
parentPrim.RootPart.LinkNum = 0;
|
||||||
if (sendEvents)
|
if (sendEvents)
|
||||||
parenPrim.TriggerScriptChangedEvent(Changed.LINK);
|
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1645,7 +1623,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// when a subset of a link set's prims are selected
|
// when a subset of a link set's prims are selected
|
||||||
// and the root prim is part of that selection
|
// and the root prim is part of that selection
|
||||||
//
|
//
|
||||||
List<SceneObjectPart> parts = new List<SceneObjectPart>(parenPrim.Children.Values);
|
List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values);
|
||||||
|
|
||||||
List<uint> unlink_ids = new List<uint>();
|
List<uint> unlink_ids = new List<uint>();
|
||||||
foreach (SceneObjectPart unlink_part in parts)
|
foreach (SceneObjectPart unlink_part in parts)
|
||||||
|
@ -1662,9 +1640,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
DelinkObjects(unlink_ids, false);
|
DelinkObjects(unlink_ids, false);
|
||||||
|
|
||||||
// Send event to root prim, then we're done with it
|
// Send event to root prim, then we're done with it
|
||||||
parenPrim.TriggerScriptChangedEvent(Changed.LINK);
|
parentPrim.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
|
|
||||||
unlink_ids.Remove(parenPrim.RootPart.LocalId);
|
unlink_ids.Remove(parentPrim.RootPart.LocalId);
|
||||||
|
|
||||||
foreach (uint localId in unlink_ids)
|
foreach (uint localId in unlink_ids)
|
||||||
{
|
{
|
||||||
|
@ -1683,7 +1661,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// The selected prims were all child prims. Edit linked parts
|
// The selected prims were all child prims. Edit linked parts
|
||||||
// without the root prim selected will get us here
|
// without the root prim selected will get us here
|
||||||
//
|
//
|
||||||
List<SceneObjectGroup> parents = new List<SceneObjectGroup>();
|
List<SceneObjectGroup> parentGroups = new List<SceneObjectGroup>();
|
||||||
|
|
||||||
// If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow
|
// If the first scan failed, we need to do a /deep/ scan of the linkages. This is /really/ slow
|
||||||
// We know that this is not the root prim now essentially, so we don't have to worry about remapping
|
// We know that this is not the root prim now essentially, so we don't have to worry about remapping
|
||||||
|
@ -1691,18 +1669,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
bool delinkedSomething = false;
|
bool delinkedSomething = false;
|
||||||
for (int i = 0; i < primIds.Count; i++)
|
for (int i = 0; i < primIds.Count; i++)
|
||||||
{
|
{
|
||||||
foreach (SceneObjectGroup grp in sceneObjects.Values)
|
SceneObjectGroup parent = GetGroupByPrim(primIds[i]);
|
||||||
{
|
parent.DelinkFromGroup(primIds[i]);
|
||||||
SceneObjectPart gPart = grp.GetChildPart(primIds[i]);
|
delinkedSomething = true;
|
||||||
if (gPart != null)
|
if (!parentGroups.Contains(parent))
|
||||||
{
|
parentGroups.Add(parent);
|
||||||
grp.DelinkFromGroup(primIds[i]);
|
|
||||||
delinkedSomething = true;
|
|
||||||
if (!parents.Contains(grp))
|
|
||||||
parents.Add(grp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!delinkedSomething)
|
if (!delinkedSomething)
|
||||||
{
|
{
|
||||||
|
@ -1712,7 +1683,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (SceneObjectGroup g in parents)
|
foreach (SceneObjectGroup g in parentGroups)
|
||||||
{
|
{
|
||||||
g.TriggerScriptChangedEvent(Changed.LINK);
|
g.TriggerScriptChangedEvent(Changed.LINK);
|
||||||
}
|
}
|
||||||
|
@ -1790,30 +1761,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="originalPrim"></param>
|
/// <param name="originalPrim"></param>
|
||||||
/// <param name="offset"></param>
|
/// <param name="offset"></param>
|
||||||
/// <param name="flags"></param>
|
/// <param name="flags"></param>
|
||||||
protected internal SceneObjectGroup DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
|
protected internal SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
|
//m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID);
|
||||||
|
SceneObjectGroup original = GetGroupByPrim(originalPrimID);
|
||||||
List<EntityBase> EntityList = GetEntities();
|
if (original != null)
|
||||||
|
|
||||||
SceneObjectGroup originPrim = null;
|
|
||||||
foreach (EntityBase ent in EntityList)
|
|
||||||
{
|
{
|
||||||
if (ent is SceneObjectGroup)
|
if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition))
|
||||||
{
|
{
|
||||||
if (((SceneObjectGroup)ent).LocalId == originalPrim)
|
SceneObjectGroup copy = original.Copy(AgentID, GroupID, true);
|
||||||
{
|
|
||||||
originPrim = (SceneObjectGroup)ent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originPrim != null)
|
|
||||||
{
|
|
||||||
if (m_parentScene.Permissions.CanDuplicateObject(originPrim.Children.Count, originPrim.UUID, AgentID, originPrim.AbsolutePosition))
|
|
||||||
{
|
|
||||||
SceneObjectGroup copy = originPrim.Copy(AgentID, GroupID, true);
|
|
||||||
copy.AbsolutePosition = copy.AbsolutePosition + offset;
|
copy.AbsolutePosition = copy.AbsolutePosition + offset;
|
||||||
|
|
||||||
Entities.Add(copy);
|
Entities.Add(copy);
|
||||||
|
@ -1840,7 +1796,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
copy.AbsolutePosition = copy.AbsolutePosition;
|
copy.AbsolutePosition = copy.AbsolutePosition;
|
||||||
|
|
||||||
if (OnObjectDuplicate != null)
|
if (OnObjectDuplicate != null)
|
||||||
OnObjectDuplicate(originPrim, copy);
|
OnObjectDuplicate(original, copy);
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue