From 6fe4b6fbe807672ec64700ff8c6307a2a3e4f084 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 2 Feb 2012 02:51:59 +0100 Subject: [PATCH] Fix remembering attachment point and position when an item is rezzed in world. Also fix PRIM_LOCAL_POS returning 0 when used on child prims from a script in the root. --- .../InventoryAccess/InventoryAccessModule.cs | 12 ++ .../Framework/Scenes/SceneObjectGroup.cs | 20 ++- .../Shared/Api/Implementation/LSL_Api.cs | 121 +++++++++--------- 3 files changed, 92 insertions(+), 61 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 7ebf002377..fe75271e7f 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -367,6 +367,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; + // Restore attachment data after trip through the sim + if (objectGroup.RootPart.AttachPoint > 0) + inventoryStoredPosition = objectGroup.RootPart.AttachOffset; + objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; + objectGroup.AbsolutePosition = inventoryStoredPosition; // Make sure all bits but the ones we want are clear @@ -740,6 +745,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (e == null || attachment) // Single { SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + if (!attachment) + { + g.RootPart.AttachPoint = g.RootPart.Shape.State; + g.RootPart.AttachOffset = g.AbsolutePosition; + } objlist.Add(g); veclist.Add(new Vector3(0, 0, 0)); @@ -769,6 +779,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (XmlNode n in groups) { SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml); + g.RootPart.AttachPoint = g.RootPart.Shape.State; + g.RootPart.AttachOffset = g.AbsolutePosition; objlist.Add(g); XmlElement el = (XmlElement)n; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c31cbab85d..648571013e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2351,6 +2351,11 @@ namespace OpenSim.Region.Framework.Scenes /// The group of prims which should be linked to this group public void LinkToGroup(SceneObjectGroup objectGroup) { + LinkToGroup(objectGroup, false); + } + + public void LinkToGroup(SceneObjectGroup objectGroup, bool insert) + { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); @@ -2380,7 +2385,20 @@ namespace OpenSim.Region.Framework.Scenes lock (m_parts.SyncRoot) { - int linkNum = PrimCount + 1; + int linkNum; + if (insert) + { + linkNum = 2; + foreach (SceneObjectPart part in Parts) + { + if (part.LinkNum > 1) + part.LinkNum++; + } + } + else + { + linkNum = PrimCount + 1; + } m_parts.Add(linkPart.UUID, linkPart); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7ed41f2056..3e9529f4e2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2223,11 +2223,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - if (m_host.IsRoot) + if (part.IsRoot) { - return new LSL_Vector(m_host.AttachedPos.X, - m_host.AttachedPos.Y, - m_host.AttachedPos.Z); + return new LSL_Vector(part.AttachedPos.X, + part.AttachedPos.Y, + part.AttachedPos.Z); } else { @@ -2971,68 +2971,69 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) - return; - float dist = (float)llVecDist(llGetPos(), pos); - - if (dist > m_ScriptDistanceFactor * 10.0f) - return; - - //Clone is thread-safe - TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); - - foreach (KeyValuePair inv in partInventory) + Util.FireAndForget(delegate (object x) { - if (inv.Value.Name == inventory) + if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) + return; + float dist = (float)llVecDist(llGetPos(), pos); + + if (dist > m_ScriptDistanceFactor * 10.0f) + return; + + //Clone is thread-safe + TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); + + foreach (KeyValuePair inv in partInventory) { - // make sure we're an object. - if (inv.Value.InvType != (int)InventoryType.Object) + if (inv.Value.Name == inventory) { - llSay(0, "Unable to create requested object. Object is missing from database."); + // make sure we're an object. + if (inv.Value.InvType != (int)InventoryType.Object) + { + llSay(0, "Unable to create requested object. Object is missing from database."); + return; + } + + Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); + + // need the magnitude later + // float velmag = (float)Util.GetMagnitude(llvel); + + SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param); + + // If either of these are null, then there was an unknown error. + if (new_group == null) + continue; + + // objects rezzed with this method are die_at_edge by default. + new_group.RootPart.SetDieAtEdge(true); + + new_group.ResumeScripts(); + + m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( + "object_rez", new Object[] { + new LSL_String( + new_group.RootPart.UUID.ToString()) }, + new DetectParams[0])); + + float groupmass = new_group.GetMass(); + + if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero) + { + //Recoil. + llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); + } + // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) return; } - - Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); - - // need the magnitude later - float velmag = (float)Util.GetMagnitude(llvel); - - SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, Rot2Quaternion(rot), llvel, param); - - // If either of these are null, then there was an unknown error. - if (new_group == null) - continue; - - // objects rezzed with this method are die_at_edge by default. - new_group.RootPart.SetDieAtEdge(true); - - Util.FireAndForget(delegate (object x) - { - new_group.ResumeScripts(); - }); - - m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( - "object_rez", new Object[] { - new LSL_String( - new_group.RootPart.UUID.ToString()) }, - new DetectParams[0])); - - float groupmass = new_group.GetMass(); - - if (new_group.RootPart.PhysActor != null && new_group.RootPart.PhysActor.IsPhysical && llvel != Vector3.Zero) - { - //Recoil. - llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); - } - // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) - ScriptSleep((int)((groupmass * velmag) / 10)); - ScriptSleep(100); - return; } - } - llSay(0, "Could not find object " + inventory); + llSay(0, "Could not find object " + inventory); + }); + + //ScriptSleep((int)((groupmass * velmag) / 10)); + ScriptSleep(100); } public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) @@ -3938,7 +3939,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Required for linking childPrim.RootPart.ClearUpdateSchedule(); - parentPrim.LinkToGroup(childPrim); + parentPrim.LinkToGroup(childPrim, true); } parentPrim.TriggerScriptChangedEvent(Changed.LINK);