diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
index 5f543ddf01..8813e437da 100644
--- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
+++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs
@@ -206,6 +206,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
}
+ //SendSceneUpdates put each update into an outgoing queue of each SyncConnector
public void SendSceneUpdates()
{
// Existing value of 1 indicates that updates are currently being sent so skip updates this pass
@@ -310,6 +311,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
});
}
+ //The following Sendxxx calls,send out a message immediately, w/o putting it in the SyncConnector's outgoing queue.
+ //May need some optimization there on the priorities.
+
public void SendTerrainUpdates(string lastUpdateActorID)
{
if(m_isSyncRelay || m_actorID.Equals(lastUpdateActorID))
@@ -320,6 +324,114 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
}
+ ///
+ /// Send a sync message to remove the given objects in all connected actors.
+ /// UUID is used for identified a removed object. This function now should
+ /// only be triggered by an object removal that is initiated locally.
+ ///
+ ///
+ //private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog)
+ public void SendDeleteObject(SceneObjectGroup sog, bool softDelete)
+ {
+ //m_log.DebugFormat("RegionSyncModule_OnObjectBeingRemovedFromScene called at time {0}:{1}:{2}", DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
+
+ //Only send the message out if this is a relay node for sync messages, or this actor caused deleting the object
+ //if (m_isSyncRelay || CheckObjectForSendingUpdate(sog))
+
+
+ OSDMap data = new OSDMap();
+ //data["regionHandle"] = OSD.FromULong(regionHandle);
+ //data["localID"] = OSD.FromUInteger(sog.LocalId);
+ data["UUID"] = OSD.FromUUID(sog.UUID);
+ data["actorID"] = OSD.FromString(m_actorID);
+ data["softDelete"] = OSD.FromBoolean(softDelete);
+
+ SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RemovedObject, OSDParser.SerializeJsonString(data));
+ SendObjectUpdateToRelevantSyncConnectors(sog, rsm);
+ }
+
+
+ public void SendLinkObject(SceneObjectPart root, List children)
+ {
+ if(children.Count==0) return;
+
+ OSDMap data = new OSDMap();
+ //string sogxml = SceneObjectSerializer.ToXml2Format(linkedGroup);
+ //data["linkedGroup"]=OSD.FromString(sogxml);
+ data["root"] = OSD.FromUUID(root.UUID);
+ data["partCount"] = OSD.FromInteger(children.Count);
+ data["actorID"] = OSD.FromString(m_actorID);
+ int partNum = 0;
+ foreach(SceneObjectPart part in children){
+ string partTempID = "part"+partNum;
+ data[partTempID] = OSD.FromUUID(part.UUID);
+ partNum++;
+ }
+
+ SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.LinkObject, OSDParser.SerializeJsonString(data));
+ SendObjectUpdateToRelevantSyncConnectors(root.ParentGroup, rsm);
+ }
+
+
+ public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs)
+ {
+ switch (ev)
+ {
+ case EventManager.EventNames.NewScript:
+ if (evArgs.Length < 3)
+ {
+ m_log.Error(LogHeader + " not enough event args for NewScript");
+ return;
+ }
+ OnLocalNewScript((UUID)evArgs[0], (SceneObjectPart)evArgs[1], (UUID)evArgs[2]);
+ return;
+ case EventManager.EventNames.UpdateScript:
+ if (evArgs.Length < 5)
+ {
+ m_log.Error(LogHeader + " not enough event args for UpdateScript");
+ return;
+ }
+ OnLocalUpdateScript((UUID)evArgs[0], (UUID)evArgs[1], (UUID)evArgs[2], (bool)evArgs[3], (UUID)evArgs[4]);
+ return;
+ case EventManager.EventNames.ScriptReset:
+ if (evArgs.Length < 2)
+ {
+ m_log.Error(LogHeader + " not enough event args for ScriptReset");
+ return;
+ }
+ OnLocalScriptReset((uint)evArgs[0], (UUID)evArgs[1]);
+ return;
+ case EventManager.EventNames.ChatFromClient:
+ if (evArgs.Length < 2)
+ {
+ m_log.Error(LogHeader + " not enough event args for ChatFromClient");
+ return;
+ }
+ OnLocalChatFromClient(evArgs[0], (OSChatMessage)evArgs[1]);
+ return;
+ case EventManager.EventNames.ChatFromWorld:
+ if (evArgs.Length < 2)
+ {
+ m_log.Error(LogHeader + " not enough event args for ChatFromWorld");
+ return;
+ }
+ OnLocalChatFromWorld(evArgs[0], (OSChatMessage)evArgs[1]);
+ return;
+ case EventManager.EventNames.ObjectGrab:
+ OnLocalGrabObject((uint)evArgs[0], (uint)evArgs[1], (Vector3)evArgs[2], (IClientAPI)evArgs[3], (SurfaceTouchEventArgs)evArgs[4]);
+ return;
+ case EventManager.EventNames.ObjectGrabbing:
+ OnLocalObjectGrabbing((uint)evArgs[0], (uint)evArgs[1], (Vector3)evArgs[2], (IClientAPI)evArgs[3], (SurfaceTouchEventArgs)evArgs[4]);
+ return;
+ case EventManager.EventNames.ObjectDeGrab:
+ OnLocalDeGrabObject((uint)evArgs[0], (uint)evArgs[1], (IClientAPI)evArgs[2], (SurfaceTouchEventArgs)evArgs[3]);
+ return;
+ default:
+ return;
+ }
+ }
+
+
#endregion //IRegionSyncModule
#region ICommandableModule Members
@@ -855,7 +967,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
/// The handler for processing incoming sync messages.
///
///
- public void HandleIncomingMessage(SymmetricSyncMessage msg)
+ public void HandleIncomingMessage(SymmetricSyncMessage msg, string senderActorID)
{
switch (msg.Type)
{
@@ -903,6 +1015,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
HandleRemovedObject(msg);
return;
}
+ case SymmetricSyncMessage.MsgType.LinkObject:
+ {
+ HandleLinkObject(msg);
+ return;
+ }
//EVENTS PROCESSING
case SymmetricSyncMessage.MsgType.NewScript:
case SymmetricSyncMessage.MsgType.UpdateScript:
@@ -1059,6 +1176,38 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
}
+ private void HandleLinkObject(SymmetricSyncMessage msg)
+ {
+ // Get the data from message and error check
+ OSDMap data = DeserializeMessage(msg);
+ if (data == null)
+ {
+ SymmetricSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
+ return;
+ }
+
+ string init_actorID = data["actorID"].AsString();
+ //string sogxml = data["linkedGroup"].AsString();
+ //SceneObjectGroup linkedGroup = SceneObjectSerializer.FromXml2Format(sogxml);
+ UUID rootID = data["root"].AsUUID();
+ int partCount = data["partCount"].AsInteger();
+ List childrenIDs = new List();
+
+ for (int i = 0; i < partCount; i++)
+ {
+ string partTempID = "part" + i;
+ childrenIDs.Add(data[partTempID].AsUUID());
+ }
+
+ m_scene.LinkObjectBySync(rootID, childrenIDs);
+
+ //if this is a relay node, forwards the event
+ if (m_isSyncRelay)
+ {
+ SendSceneEventToRelevantSyncConnectors(init_actorID, msg);
+ }
+ }
+
///
/// The common actions for handling remote events (event initiated at other actors and propogated here)
///
@@ -1346,89 +1495,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_scene.EventManager.TriggerObjectDeGrabLocally(part.LocalId, originalID, remoteClinet, surfaceArgs);
}
- ///
- /// Send a sync message to remove the given objects in all connected actors.
- /// UUID is used for identified a removed object. This function now should
- /// only be triggered by an object removal that is initiated locally.
- ///
- ///
- //private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog)
- public void SendDeleteObject(SceneObjectGroup sog, bool softDelete)
- {
- //m_log.DebugFormat("RegionSyncModule_OnObjectBeingRemovedFromScene called at time {0}:{1}:{2}", DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
-
- //Only send the message out if this is a relay node for sync messages, or this actor caused deleting the object
- //if (m_isSyncRelay || CheckObjectForSendingUpdate(sog))
-
-
- OSDMap data = new OSDMap(1);
- //data["regionHandle"] = OSD.FromULong(regionHandle);
- //data["localID"] = OSD.FromUInteger(sog.LocalId);
- data["UUID"] = OSD.FromUUID(sog.UUID);
- data["actorID"] = OSD.FromString(m_actorID);
- data["softDelete"] = OSD.FromBoolean(softDelete);
-
- SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RemovedObject, OSDParser.SerializeJsonString(data));
- SendObjectUpdateToRelevantSyncConnectors(sog, rsm);
- }
-
- public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs)
- {
- switch (ev)
- {
- case EventManager.EventNames.NewScript:
- if (evArgs.Length < 3)
- {
- m_log.Error(LogHeader + " not enough event args for NewScript");
- return;
- }
- OnLocalNewScript((UUID)evArgs[0], (SceneObjectPart)evArgs[1], (UUID)evArgs[2]);
- return;
- case EventManager.EventNames.UpdateScript:
- if (evArgs.Length < 5)
- {
- m_log.Error(LogHeader + " not enough event args for UpdateScript");
- return;
- }
- OnLocalUpdateScript((UUID)evArgs[0], (UUID)evArgs[1], (UUID)evArgs[2], (bool)evArgs[3], (UUID)evArgs[4]);
- return;
- case EventManager.EventNames.ScriptReset:
- if (evArgs.Length < 2)
- {
- m_log.Error(LogHeader + " not enough event args for ScriptReset");
- return;
- }
- OnLocalScriptReset((uint)evArgs[0], (UUID)evArgs[1]);
- return;
- case EventManager.EventNames.ChatFromClient:
- if (evArgs.Length < 2)
- {
- m_log.Error(LogHeader + " not enough event args for ChatFromClient");
- return;
- }
- OnLocalChatFromClient(evArgs[0], (OSChatMessage)evArgs[1]);
- return;
- case EventManager.EventNames.ChatFromWorld:
- if (evArgs.Length < 2)
- {
- m_log.Error(LogHeader + " not enough event args for ChatFromWorld");
- return;
- }
- OnLocalChatFromWorld(evArgs[0], (OSChatMessage)evArgs[1]);
- return;
- case EventManager.EventNames.ObjectGrab:
- OnLocalGrabObject((uint)evArgs[0], (uint)evArgs[1], (Vector3) evArgs[2], (IClientAPI) evArgs[3], (SurfaceTouchEventArgs)evArgs[4]);
- return;
- case EventManager.EventNames.ObjectGrabbing:
- OnLocalObjectGrabbing((uint)evArgs[0], (uint)evArgs[1], (Vector3)evArgs[2], (IClientAPI)evArgs[3], (SurfaceTouchEventArgs)evArgs[4]);
- return;
- case EventManager.EventNames.ObjectDeGrab:
- OnLocalDeGrabObject((uint)evArgs[0], (uint)evArgs[1], (IClientAPI)evArgs[2], (SurfaceTouchEventArgs)evArgs[3]);
- return;
- default:
- return;
- }
- }
///
/// The handler for (locally initiated) event OnNewScript: triggered by client's RezSript packet, publish it to other actors.
diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs
index 8e5f09bb8f..381216f132 100755
--- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs
+++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs
@@ -30,6 +30,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
NewObject, // objects
UpdatedObject, // objects
RemovedObject, // objects
+ LinkObject,
RegionName,
//RegionStatus,
ActorID,
diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs
index 6f2e915b36..105ce77559 100755
--- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs
+++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs
@@ -292,7 +292,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//For any other messages, we simply deliver the message to RegionSyncModule for now.
//Later on, we may deliver messages to different modules, say sync message to RegionSyncModule and event message to ActorSyncModule.
- m_regionSyncModule.HandleIncomingMessage(msg);
+ m_regionSyncModule.HandleIncomingMessage(msg, m_syncOtherSideActorID);
}
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs
index 5048434859..41629c20d6 100755
--- a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs
@@ -60,10 +60,15 @@ namespace OpenSim.Region.Framework.Interfaces
void QueueSceneObjectPartForUpdate(SceneObjectPart part);
void QueueScenePresenceForTerseUpdate(ScenePresence presence);
- //void SendUpdatesToSynchronizeState(List sog);
+ //SendSceneUpdates put each update into an outgoing queue of each SyncConnector
void SendSceneUpdates();
+
+ //In RegionSyncModule's implementation,
+ //The following calls send out a message immediately, w/o putting it in the SyncConnector's outgoing queue.
+ //May need some optimization there on the priorities.
void SendTerrainUpdates(string lastUpdateActorID);
void SendDeleteObject(SceneObjectGroup sog, bool softDelete);
+ void SendLinkObject(SceneObjectPart root, List children);
//For propogating scene events to other actors
void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 9b0340879e..e810d502e1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -725,6 +725,74 @@ namespace OpenSim.Region.Framework.Scenes
m_sceneGraph.AddSceneObjectByStateSynch(group);
}
+ public void DebugSceneObjectGroups()
+ {
+ EntityBase[] entities = Entities.GetEntities();
+ List groups = new List();
+
+ foreach (EntityBase ent in entities)
+ {
+ if (ent is SceneObjectGroup)
+ {
+ SceneObjectGroup sog = (SceneObjectGroup)ent;
+ groups.Add(sog);
+ }
+ }
+
+ m_log.Debug("Scene " + m_regInfo.RegionName + " has " + groups.Count + " SOGs");
+ foreach (SceneObjectGroup sog in groups)
+ {
+ string sogDebug = sog.DebugObjectUpdateResult();
+ m_log.Debug(sogDebug);
+ }
+ }
+
+ //Assuming that the permission and owner checking is done at the actor that initiates the link operation, so
+ //no checking of permissions here.
+ ///
+ /// Update the grouping relations of the SceneObjectParts as identified by the rootID and childrenIDs, and update the properties of all the parts in the new object group.
+ ///
+ ///
+ ///
+ ///
+ public void LinkObjectBySync(UUID rootID, List childrenIDs)
+ {
+ m_log.Debug("Start to LinkObjectBySync");
+ DebugSceneObjectGroups();
+
+ List children = new List();
+ SceneObjectPart root = GetSceneObjectPart(rootID);
+
+ if (root == null)
+ {
+ m_log.Warn("LinkObjectBySync: root part " + rootID + " not found at local Scene copy");
+ return;
+ }
+
+ foreach (UUID childID in childrenIDs)
+ {
+ SceneObjectPart part = GetSceneObjectPart(childID);
+
+ if (part == null)
+ {
+ m_log.Warn("LinkObjectBySync: child part " + rootID + " not found at local Scene copy");
+ continue;
+ }
+
+ children.Add(part);
+ }
+
+ //Leverage the LinkObject implementation to get the book keeping of Group and Parts relations right
+ m_sceneGraph.LinkObjectsBySync(root, children);
+
+ //The properties of the newly linked object should be updated later with another UpdatedObject message.
+
+ //Set the property values as in the incoming copy of the object group
+ //SceneObjectGroup localGroup = root.ParentGroup;
+ //localGroup.UpdateObjectProperties(linkedGroup);
+
+ }
+
#endregion //SYMMETRIC SYNC
public ICapabilitiesModule CapsModule
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 99c150ff3c..987468f1c5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1576,6 +1576,24 @@ namespace OpenSim.Region.Framework.Scenes
return; // parent is null so not in this region
}
+
+ //SYMMETRIC SYNC
+ //Send out a LinkObject message for synchronization purpose, before other object-update sync messages are sent out.
+ //We need to do this before the calling to parentGroup.LinkToGroup() below, as LinkToGroup will trigger
+ //SendDeleteObject message to be sent out.
+
+ // ------------- NOTE: This needs further optimization, as we don't want to block on sending messages while inside the lock. -------------
+ // However, we also want to make sure that the LinkObject message is sent out with high priority and sent
+ // earlier than the object update message triggered by the ScheduleGroupForFullUpdate() function below
+ if (m_parentScene.RegionSyncModule != null)
+ {
+ //Tell other actors to link the SceneObjectParts together as a new group. But not updating the properties yet.
+ //The properties will be updated later when parentGroup.ScheduleGroupForFullUpdate() is called below.
+ m_parentScene.RegionSyncModule.SendLinkObject(root, children);
+ }
+
+ //end of SYMMETRIC SYNC
+
foreach (SceneObjectGroup child in childGroups)
{
parentGroup.LinkToGroup(child);
@@ -1585,6 +1603,7 @@ namespace OpenSim.Region.Framework.Scenes
child.AbsolutePosition = child.AbsolutePosition;
}
+
// 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)
parentGroup.RootPart.CreateSelected = true;
@@ -1946,6 +1965,7 @@ namespace OpenSim.Region.Framework.Scenes
public Scene.ObjectUpdateResult AddOrUpdateObjectBySynchronization(SceneObjectGroup updatedSog)
{
UUID sogID = updatedSog.UUID;
+ Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.Unchanged;
if (Entities.ContainsKey(sogID))
{
@@ -1954,22 +1974,27 @@ namespace OpenSim.Region.Framework.Scenes
if (entity is SceneObjectGroup)
{
SceneObjectGroup localSog = (SceneObjectGroup)entity;
- Scene.ObjectUpdateResult updateResult = localSog.UpdateObjectGroupBySync(updatedSog);
- return updateResult;
+ updateResult = localSog.UpdateObjectGroupBySync(updatedSog);
}
else
{
m_log.Warn("Entity with " + sogID + " is not of type SceneObjectGroup");
//return false;
- return Scene.ObjectUpdateResult.Error;
+ updateResult = Scene.ObjectUpdateResult.Error;
}
}
else
{
m_log.Debug("AddSceneObjectByStateSynch to be called");
AddSceneObjectByStateSynch(updatedSog);
- return Scene.ObjectUpdateResult.New;
+ updateResult = Scene.ObjectUpdateResult.New;
}
+
+ //Debug
+ m_log.Debug("after AddOrUpdateObjectBySynchronization");
+ m_parentScene.DebugSceneObjectGroups();
+
+ return updateResult;
}
//This is called when an object is added due to receiving a state synchronization message from Scene or an actor. Do similar things as the original AddSceneObject(),
@@ -2058,6 +2083,62 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+ public void LinkObjectsBySync(SceneObjectPart root, List children)
+ {
+ Monitor.Enter(m_updateLock);
+ try
+ {
+ SceneObjectGroup parentGroup = root.ParentGroup;
+
+ List childGroups = new List();
+ if (parentGroup != null)
+ {
+ // We do this in reverse to get the link order of the prims correct
+ for (int i = children.Count - 1; i >= 0; i--)
+ {
+ SceneObjectGroup child = children[i].ParentGroup;
+
+ if (child != null)
+ {
+ // Make sure no child prim is set for sale
+ // So that, on delink, no prims are unwittingly
+ // left for sale and sold off
+ child.RootPart.ObjectSaleType = 0;
+ child.RootPart.SalePrice = 10;
+ childGroups.Add(child);
+ }
+ }
+ }
+ else
+ {
+ return; // parent is null so not in this region
+ }
+
+ foreach (SceneObjectGroup child in childGroups)
+ {
+ parentGroup.LinkToGroupBySync(child);
+
+ // this is here so physics gets updated!
+ // Don't remove! Bad juju! Stay away! or fix physics!
+ child.AbsolutePosition = child.AbsolutePosition;
+ }
+
+
+ // 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)
+ parentGroup.RootPart.CreateSelected = true;
+ parentGroup.TriggerScriptChangedEvent(Changed.LINK);
+ parentGroup.HasGroupChanged = true;
+ //Do not change the timestamp and actorID values
+ parentGroup.ScheduleGroupForFullUpdate_SyncInfoUnchanged();
+
+ }
+ finally
+ {
+ Monitor.Exit(m_updateLock);
+ }
+ }
+
#endregion //SYMMETRIC SYNC
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 32e79517fd..625f6d6217 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2127,6 +2127,7 @@ namespace OpenSim.Region.Framework.Scenes
//ScheduleGroupForFullUpdate();
//SYMMETRIC SYNC
+ //The DeleteObject message will be enqueued to be sent out by another thread, and the call will return quickly.
if (m_scene.RegionSyncModule != null)
m_scene.RegionSyncModule.SendDeleteObject(objectGroup, true);
//end of SYMMETRIC SYNC
@@ -3648,9 +3649,33 @@ namespace OpenSim.Region.Framework.Scenes
ScheduleGroupForFullUpdate_SyncInfoUnchanged();
}
+ //debug the update result
+ if (groupUpdateResult == Scene.ObjectUpdateResult.Updated)
+ {
+ DebugObjectUpdateResult();
+ }
+
return groupUpdateResult;
}
+ public string DebugObjectUpdateResult()
+ {
+ //m_log.Debug("ObjectGroup " + UUID + " updated. Rootpart: " +m_rootPart.DebugObjectPartProperties());
+ string sogDebug = "ObjectGroup " + UUID + ".\n Rootpart: " + m_rootPart.DebugObjectPartProperties();
+
+ int partNum = 1;
+ foreach (SceneObjectPart part in Parts)
+ {
+ if (part.UUID != m_rootPart.UUID)
+ {
+ //m_log.Debug("part " + partNum + ", " + part.DebugObjectPartProperties());
+ sogDebug += "\n"+part.DebugObjectPartProperties();
+ partNum++;
+ }
+ }
+ return sogDebug;
+ }
+
private void AddNewPart(SceneObjectPart newPart)
{
//set the parent relationship
@@ -3750,6 +3775,91 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+ //Similar to LinkToGroup(), except that not calling RegionSyncModule.SendDeleteObject
+ public void LinkToGroupBySync(SceneObjectGroup objectGroup)
+ {
+
+ SceneObjectPart linkPart = objectGroup.m_rootPart;
+
+ Vector3 oldGroupPosition = linkPart.GroupPosition;
+ Quaternion oldRootRotation = linkPart.RotationOffset;
+
+ linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
+ linkPart.GroupPosition = AbsolutePosition;
+ Vector3 axPos = linkPart.OffsetPosition;
+
+ Quaternion parentRot = m_rootPart.RotationOffset;
+ axPos *= Quaternion.Inverse(parentRot);
+
+ linkPart.OffsetPosition = axPos;
+ Quaternion oldRot = linkPart.RotationOffset;
+ Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot;
+ linkPart.RotationOffset = newRot;
+
+ linkPart.ParentID = m_rootPart.LocalId;
+ if (m_rootPart.LinkNum == 0)
+ m_rootPart.LinkNum = 1;
+
+ lock (m_parts.SyncRoot)
+ {
+ m_parts.Add(linkPart.UUID, linkPart);
+
+ // Insert in terms of link numbers, the new links
+ // before the current ones (with the exception of
+ // the root prim. Shuffle the old ones up
+ SceneObjectPart[] parts = m_parts.GetArray();
+ for (int i = 0; i < parts.Length; i++)
+ {
+ SceneObjectPart part = parts[i];
+ if (part.LinkNum != 1)
+ {
+ // Don't update root prim link number
+ part.LinkNum += objectGroup.PrimCount;
+ }
+ }
+
+ linkPart.LinkNum = 2;
+
+ linkPart.SetParent(this);
+ linkPart.CreateSelected = true;
+
+ //if (linkPart.PhysActor != null)
+ //{
+ // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
+
+ //linkPart.PhysActor = null;
+ //}
+
+ //TODO: rest of parts
+ int linkNum = 3;
+ SceneObjectPart[] ogParts = objectGroup.Parts;
+ for (int i = 0; i < ogParts.Length; i++)
+ {
+ SceneObjectPart part = ogParts[i];
+ if (part.UUID != objectGroup.m_rootPart.UUID)
+ LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
+ part.ClearUndoState();
+ }
+ }
+
+ m_scene.UnlinkSceneObject(objectGroup, true);
+ objectGroup.m_isDeleted = true;
+
+ objectGroup.m_parts.Clear();
+
+ // Can't do this yet since backup still makes use of the root part without any synchronization
+ // objectGroup.m_rootPart = null;
+
+ AttachToBackup();
+
+ // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
+ // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
+ // unmoved prims!
+ ResetChildPrimPhysicsPositions();
+
+ }
+
+
#endregion
}
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index fb6e231885..97745aac02 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -5084,6 +5084,8 @@ namespace OpenSim.Region.Framework.Scenes
m_parentGroup.Scene.EventManager.TriggerAggregateScriptEvents(this);
}
+ m_log.Debug("SceneObjectPart Name-" +Name+", localID-" + m_localId + " updated");
+
return partUpdateResult;
}
@@ -5097,6 +5099,12 @@ namespace OpenSim.Region.Framework.Scenes
return false;
}
+ public string DebugObjectPartProperties()
+ {
+ string debugMsg = "UUID " + UUID + ", Name " + Name + ", localID " + LocalId + ", lastUpdateActorID " + LastUpdateActorID + ", lastUpdateTimeStamp " + LastUpdateTimeStamp;
+ return debugMsg;
+ }
+
///
/// Schedules this prim for a full update, without changing the timestamp or actorID (info on when and who modified any property).
/// NOTE: this is the same as the original SceneObjectPart.ScheduleFullUpdate().
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index a22e3f174c..536c0145c5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -654,6 +654,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (m_Suspended)
return 0;
+
lock (m_Script)
{
EventParams data = null;
@@ -674,6 +675,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
return 0;
}
+ m_log.DebugFormat("[Script] processing event {2} in state {3} to {0}.{1}, localID -{4}", m_PrimName, m_ScriptName, data.EventName, m_State, m_LocalID);
+
+
if (data.EventName == "timer")
m_TimerQueued = false;
if (data.EventName == "control")
@@ -712,8 +716,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
{
SceneObjectPart part = m_Engine.World.GetSceneObjectPart(
m_LocalID);
- // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
- // m_PrimName, m_ScriptName, data.EventName, m_State);
try
{
@@ -786,6 +788,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
}
}
+ m_log.DebugFormat("[Script] processing event {2} in state {3} to {0}.{1}, localID -{4}; to trigger QueueEventHandler", m_PrimName, m_ScriptName, data.EventName, m_State, m_LocalID);
+
lock (m_EventQueue)
{
if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown))