From bcf74416a1677584c069e4e0b9acf9015d8c5b6c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 19 Jul 2008 04:05:34 +0000 Subject: Fix prim link numbers (Mantis #1781) Implements additional unlink modes (unlink root prim from link set, some multi-set operations). Linking (single and mutiple) fully implemented. Consistent numbering of links while in world. Link/delink with predictable link numbering. Correct link numbers in LSL. Not all multi-set ops implemented. Link numbers still change when taken and re-rezzed. --- .../Modules/World/Estate/EstateManagementModule.cs | 8 +-- OpenSim/Region/Environment/Scenes/InnerScene.cs | 81 +++++++++++++++++++++- .../Region/Environment/Scenes/SceneObjectGroup.cs | 46 ++++++++++-- .../Region/Environment/Scenes/SceneObjectPart.cs | 12 ++-- .../ScriptEngine/Common/LSL_BuiltIn_Commands.cs | 18 ++--- .../Shared/Api/Implementation/LSL_Api.cs | 18 ++--- .../Region/ScriptEngine/XEngine/EventManager.cs | 12 +--- 7 files changed, 148 insertions(+), 47 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs index ab0adf2..3996fb3 100644 --- a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs @@ -558,10 +558,10 @@ namespace OpenSim.Region.Environment.Modules.World.Estate args.regionFlags = GetRegionFlags(); args.regionName = m_scene.RegionInfo.RegionName; args.SimOwner = m_scene.RegionInfo.MasterAvatarAssignedUUID; - args.terrainBase0 = m_scene.RegionInfo.RegionSettings.TerrainTexture1; - args.terrainBase1 = m_scene.RegionInfo.RegionSettings.TerrainTexture2; - args.terrainBase2 = m_scene.RegionInfo.RegionSettings.TerrainTexture3; - args.terrainBase3 = m_scene.RegionInfo.RegionSettings.TerrainTexture4; + args.terrainBase0 = LLUUID.Zero; + args.terrainBase1 = LLUUID.Zero; + args.terrainBase2 = LLUUID.Zero; + args.terrainBase3 = LLUUID.Zero; args.terrainDetail0 = m_scene.RegionInfo.RegionSettings.TerrainTexture1; args.terrainDetail1 = m_scene.RegionInfo.RegionSettings.TerrainTexture2; args.terrainDetail2 = m_scene.RegionInfo.RegionSettings.TerrainTexture3; diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs index 7e8259f..57d3e5c 100644 --- a/OpenSim/Region/Environment/Scenes/InnerScene.cs +++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs @@ -1372,7 +1372,16 @@ namespace OpenSim.Region.Environment.Scenes // 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) - parenPrim.GetProperties(client); + parenPrim.TriggerScriptChangedEvent(Changed.LINK); + if(client != null) + parenPrim.GetProperties(client); + else + { + foreach (ScenePresence p in ScenePresences.Values) + { + parenPrim.GetProperties(p.ControllingClient); + } + } } /// @@ -1381,6 +1390,11 @@ namespace OpenSim.Region.Environment.Scenes /// protected internal void DelinkObjects(List primIds) { + DelinkObjects(primIds, true); + } + + protected internal void DelinkObjects(List primIds, bool sendEvents) + { SceneObjectGroup parenPrim = null; // Need a list of the SceneObjectGroup local ids @@ -1407,7 +1421,6 @@ namespace OpenSim.Region.Environment.Scenes if (sceneObjects.ContainsKey(primIds[i])) { - parenPrim = sceneObjects[primIds[i]]; primIds.RemoveAt(i); break; @@ -1418,11 +1431,64 @@ namespace OpenSim.Region.Environment.Scenes { foreach (uint childPrimId in primIds) { - parenPrim.DelinkFromGroup(childPrimId); + parenPrim.DelinkFromGroup(childPrimId, sendEvents); + } + + if(parenPrim.Children.Count == 1) + { + // The link set has been completely torn down + // This is the case if you select a link set and delink + // + parenPrim.RootPart.LinkNum = 1; + if(sendEvents) + parenPrim.TriggerScriptChangedEvent(Changed.LINK); + } + else + { + // The link set has prims remaining. This path is taken + // when a subset of a link set's prims are selected + // and the root prim is part of that selection + // + List parts = new List(parenPrim.Children.Values); + + List unlink_ids = new List(); + foreach (SceneObjectPart unlink_part in parts) + unlink_ids.Add(unlink_part.LocalId); + + // Tear down the remaining link set + // + if(unlink_ids.Count == 2) + { + DelinkObjects(unlink_ids, true); + return; + } + + DelinkObjects(unlink_ids, false); + + // Send event to root prim, then we're done with it + parenPrim.TriggerScriptChangedEvent(Changed.LINK); + + unlink_ids.Remove(parenPrim.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 parents = new List(); + // 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 // which one is the root prim @@ -1436,6 +1502,8 @@ namespace OpenSim.Region.Environment.Scenes { grp.DelinkFromGroup(primIds[i]); delinkedSomething = true; + if(!parents.Contains(grp)) + parents.Add(grp); } } @@ -1446,6 +1514,13 @@ namespace OpenSim.Region.Environment.Scenes "DelinkObjects(): Could not find a root prim out of {0} as given to a delink request!", primIds); } + else + { + foreach (SceneObjectGroup g in parents) + { + g.TriggerScriptChangedEvent(Changed.LINK); + } + } } } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index 86e0caa..82e395d 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -427,7 +427,10 @@ namespace OpenSim.Region.Environment.Scenes if (reader.Name == "SceneObjectPart") { SceneObjectPart Part = SceneObjectPart.FromXml(reader); + if(m_rootPart.LinkNum == 0) + m_rootPart.LinkNum++; AddPart(Part); + Part.LinkNum = m_parts.Count; Part.StoreUndoState(); } else @@ -462,7 +465,7 @@ namespace OpenSim.Region.Environment.Scenes LLVector3 rootOffset = new LLVector3(0, 0, 0); SceneObjectPart newPart = new SceneObjectPart(m_regionHandle, this, ownerID, localID, shape, pos, rot, rootOffset); - newPart.LinkNum = m_parts.Count; + newPart.LinkNum = 0; m_parts.Add(newPart.UUID, newPart); SetPartAsRoot(newPart); @@ -817,7 +820,6 @@ namespace OpenSim.Region.Environment.Scenes lock (m_parts) { part.SetParent(this); - part.LinkNum = m_parts.Count; try { @@ -828,6 +830,11 @@ namespace OpenSim.Region.Environment.Scenes { m_log.Error("Failed to add scened object part", e); } + + part.LinkNum = m_parts.Count; + + if(part.LinkNum == 2 && RootPart != null) + RootPart.LinkNum = 1; } } @@ -1738,14 +1745,16 @@ namespace OpenSim.Region.Environment.Scenes linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); linkPart.ParentID = m_rootPart.LocalId; - - linkPart.LinkNum = m_parts.Count; + if(m_rootPart.LinkNum == 0) + m_rootPart.LinkNum = 1; lock (m_parts) { m_parts.Add(linkPart.UUID, linkPart); } + linkPart.LinkNum = m_parts.Count; + linkPart.SetParent(this); //if (linkPart.PhysActor != null) @@ -1784,6 +1793,11 @@ namespace OpenSim.Region.Environment.Scenes /// public void DelinkFromGroup(uint partID) { + DelinkFromGroup(partID, true); + } + + public void DelinkFromGroup(uint partID, bool sendEvents) + { SceneObjectPart linkPart = GetChildPart(partID); if (null != linkPart) @@ -1801,7 +1815,17 @@ namespace OpenSim.Region.Environment.Scenes m_parts.Remove(linkPart.UUID); } + if(m_parts.Count == 1 && RootPart != null) //Single prim is left + RootPart.LinkNum = 0; + else + { + foreach (SceneObjectPart p in m_parts.Values) + if(p.LinkNum > linkPart.LinkNum) + p.LinkNum--; + } + linkPart.ParentID = 0; + linkPart.LinkNum = 0; if (linkPart.PhysActor != null) { @@ -1834,6 +1858,9 @@ namespace OpenSim.Region.Environment.Scenes m_scene.AddNewSceneObject(objectGroup, true); + if(sendEvents) + linkPart.TriggerScriptChangedEvent(Changed.LINK); + HasGroupChanged = true; ScheduleGroupForFullUpdate(); } @@ -1858,13 +1885,14 @@ namespace OpenSim.Region.Environment.Scenes { part.SetParent(this); part.ParentID = m_rootPart.LocalId; - part.LinkNum = m_parts.Count; lock (m_parts) { m_parts.Add(part.UUID, part); } + part.LinkNum = m_parts.Count; + Vector3 axiomOldPos = new Vector3(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z); axiomOldPos = oldGroupRotation * axiomOldPos; axiomOldPos += oldGroupPosition; @@ -2670,5 +2698,13 @@ namespace OpenSim.Region.Environment.Scenes ScheduleGroupForFullUpdate(); } + + public void TriggerScriptChangedEvent(Changed val) + { + foreach (SceneObjectPart part in Children.Values) + { + part.TriggerScriptChangedEvent(val); + } + } } } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 63ec23c..edccbe5 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -674,12 +674,7 @@ namespace OpenSim.Region.Environment.Scenes public int LinkNum { get { return m_linkNum; } - set - { - m_linkNum = value; - TriggerScriptChangedEvent(Changed.LINK); - - } + set { m_linkNum = value; } } public byte ClickAction @@ -2250,7 +2245,8 @@ namespace OpenSim.Region.Environment.Scenes public void SetAvatarOnSitTarget(LLUUID avatarID) { m_sitTargetAvatar = avatarID; - TriggerScriptChangedEvent(Changed.LINK); + if(ParentGroup != null) + ParentGroup.TriggerScriptChangedEvent(Changed.LINK); } public void SetAxisRotation(int axis, int rotate) @@ -3294,4 +3290,4 @@ namespace OpenSim.Region.Environment.Scenes #endregion Public Methods } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs index cbd4db2..682d566 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs @@ -2600,7 +2600,7 @@ namespace OpenSim.Region.ScriptEngine.Common if (m_host.ParentGroup.Children.Count > 1) { - return m_host.LinkNum + 1; + return m_host.LinkNum; } else { @@ -2979,7 +2979,7 @@ namespace OpenSim.Region.ScriptEngine.Common object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( @@ -3004,7 +3004,7 @@ namespace OpenSim.Region.ScriptEngine.Common partItemID = item.ItemID; Object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( @@ -3032,7 +3032,7 @@ namespace OpenSim.Region.ScriptEngine.Common partItemID = item.ItemID; Object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( @@ -3062,7 +3062,7 @@ namespace OpenSim.Region.ScriptEngine.Common partItemID = item.ItemID; Object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( @@ -3086,7 +3086,7 @@ namespace OpenSim.Region.ScriptEngine.Common object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( @@ -3103,7 +3103,7 @@ namespace OpenSim.Region.ScriptEngine.Common foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) { - if ((partInst.LinkNum + 1) == linknum) + if ((partInst.LinkNum) == linknum) { foreach (TaskInventoryItem item in partInst.TaskInventory.Values) @@ -3114,7 +3114,7 @@ namespace OpenSim.Region.ScriptEngine.Common partItemID = item.ItemID; Object[] resObjDef = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( @@ -5246,7 +5246,7 @@ namespace OpenSim.Region.ScriptEngine.Common { foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) { - if ((partInst.LinkNum + 1) == linknumber) + if ((partInst.LinkNum) == linknumber) { part = partInst; break; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index decd2d0..c3255b1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2487,7 +2487,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_host.ParentGroup.Children.Count > 1) { - return m_host.LinkNum + 1; + return m_host.LinkNum; } else { @@ -2923,7 +2923,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.PostScriptEvent(partItemID, @@ -2947,7 +2947,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api partItemID = item.ItemID; Object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.PostScriptEvent(partItemID, @@ -2975,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api partItemID = item.ItemID; Object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.PostScriptEvent(partItemID, @@ -3005,7 +3005,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api partItemID = item.ItemID; Object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.PostScriptEvent(partItemID, @@ -3029,7 +3029,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api object[] resobj = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.PostScriptEvent(partItemID, @@ -3045,7 +3045,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) { - if ((partInst.LinkNum + 1) == linknum) + if ((partInst.LinkNum) == linknum) { foreach (TaskInventoryItem item in partInst.TaskInventory.Values) @@ -3056,7 +3056,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api partItemID = item.ItemID; Object[] resObjDef = new object[] { - new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) + new LSL_Types.LSLInteger(m_host.LinkNum), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id) }; m_ScriptEngine.PostScriptEvent(partItemID, @@ -5046,7 +5046,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) { - if ((partInst.LinkNum + 1) == linknumber) + if ((partInst.LinkNum) == linknumber) { part = partInst; break; diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 3fd4942..db11e6b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -93,9 +93,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (part == null) return; - det[0].LinkNum = 0; - if (part.ParentGroup.Children.Count > 0) - det[0].LinkNum = part.LinkNum + 1; + det[0].LinkNum = part.LinkNum; myScriptEngine.PostObjectEvent(localID, new EventParams( "touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, @@ -119,9 +117,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (part == null) return; - det[0].LinkNum = 0; - if (part.ParentGroup.Children.Count > 0) - det[0].LinkNum = part.LinkNum + 1; + det[0].LinkNum = part.LinkNum; myScriptEngine.PostObjectEvent(localID, new EventParams( "touch", new Object[] { new LSL_Types.LSLInteger(1) }, @@ -141,9 +137,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (part == null) return; - det[0].LinkNum = 0; - if (part.ParentGroup.Children.Count > 0) - det[0].LinkNum = part.LinkNum + 1; + det[0].LinkNum = part.LinkNum; myScriptEngine.PostObjectEvent(localID, new EventParams( "touch_end", new Object[] { new LSL_Types.LSLInteger(1) }, -- cgit v1.1