From 0e23374aa244bb1e6f949228bf37241296c52209 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 26 Feb 2014 23:07:13 +0000 Subject: Implement PRIM_ROTATION, PRIM_ROT_LOCAL, PRIM_POSITION and PRIM_POS_LOCAL when manipulating avatars via llSetLinkPrimitiveParams() Combination of core parts of Freaky's patch at https://github.com/ft-/opensim-patches/blob/master/opensim-llsetlinkprimitive-agent-fix.patch plus further adjustments from myself. Resolves Mantises 6121, 6421, 6573, 6657 --- .../Shared/Api/Implementation/LSL_Api.cs | 145 ++++++++++++++++++--- 1 file changed, 128 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 91885b7..25d8c54 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -313,6 +313,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// The link entity. null if not found. /// + /// /// /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. @@ -323,18 +324,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then /// null is returned. /// - public ISceneEntity GetLinkEntity(int linknum) + public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum) { if (linknum < 0) { if (linknum == ScriptBaseClass.LINK_THIS) - return m_host; + return part; else return null; } - int actualPrimCount = m_host.ParentGroup.PrimCount; - List sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); + int actualPrimCount = part.ParentGroup.PrimCount; + List sittingAvatarIds = part.ParentGroup.GetSittingAvatars(); int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; // Special case for a single prim. In this case the linknum is zero. However, this will not match a single @@ -342,7 +343,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (linknum == 0) { if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) - return m_host; + return part; return null; } @@ -351,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) { if (sittingAvatarIds.Count > 0) - return m_host.ParentGroup.RootPart; + return part.ParentGroup.RootPart; else return null; } @@ -359,7 +360,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (linknum <= actualPrimCount) { - return m_host.ParentGroup.GetLinkNumPart(linknum); + return part.ParentGroup.GetLinkNumPart(linknum); } else { @@ -427,6 +428,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public List GetLinkEntities(int linkType) + { + return GetLinkEntities(m_host, linkType); + } + + public List GetLinkEntities(SceneObjectPart part, int linkType) + { + List ret = new List(); + ret.Add(part); + + switch (linkType) + { + case ScriptBaseClass.LINK_SET: + return new List(part.ParentGroup.Parts); + + case ScriptBaseClass.LINK_ROOT: + ret = new List(); + ret.Add(part.ParentGroup.RootPart); + return ret; + + case ScriptBaseClass.LINK_ALL_OTHERS: + ret = new List(part.ParentGroup.Parts); + + if (ret.Contains(part)) + ret.Remove(part); + + return ret; + + case ScriptBaseClass.LINK_ALL_CHILDREN: + ret = new List(part.ParentGroup.Parts); + + if (ret.Contains(part.ParentGroup.RootPart)) + ret.Remove(part.ParentGroup.RootPart); + return ret; + + case ScriptBaseClass.LINK_THIS: + return ret; + + default: + if (linkType < 0) + return new List(); + + ISceneEntity target = GetLinkEntity(part, linkType); + if (target == null) + return new List(); + ret = new List(); + ret.Add(target); + return ret; + } + } + //These are the implementations of the various ll-functions used by the LSL scripts. public LSL_Float llSin(double f) { @@ -3882,7 +3934,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - ISceneEntity entity = GetLinkEntity(linknum); + ISceneEntity entity = GetLinkEntity(m_host, linknum); if (entity != null) return entity.UUID.ToString(); @@ -3933,7 +3985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - ISceneEntity entity = GetLinkEntity(linknum); + ISceneEntity entity = GetLinkEntity(m_host, linknum); if (entity != null) return entity.Name; @@ -7371,22 +7423,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) { - List parts = GetLinkParts(linknumber); + List entities = GetLinkEntities(linknumber); LSL_List remaining = null; uint rulesParsed = 0; - foreach (SceneObjectPart part in parts) - remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); + foreach (ISceneEntity entity in entities) + { + if (entity is SceneObjectPart) + remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); + else + remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); + } while (remaining != null && remaining.Length > 2) { linknumber = remaining.GetLSLIntegerItem(0); rules = remaining.GetSublist(1, -1); - parts = GetLinkParts(linknumber); + entities = GetLinkEntities(linknumber); - foreach (SceneObjectPart part in parts) - remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); + foreach (ISceneEntity entity in entities) + { + if (entity is SceneObjectPart) + remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); + else + remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); + } } } @@ -7956,6 +8018,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } + + return null; + } + + protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed) + { + int idx = 0; + int idxStart = 0; + + try + { + while (idx < rules.Length) + { + ++rulesParsed; + int code = rules.GetLSLIntegerItem(idx++); + + int remain = rules.Length - idx; + idxStart = idx; + + LSL_Vector v; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_POSITION: + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + if (remain < 1) + return null; + + sp.OffsetPosition = rules.GetVector3Item(idx++); + break; + + case (int)ScriptBaseClass.PRIM_ROTATION: + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + if (remain < 1) + return null; + + sp.Rotation = rules.GetQuaternionItem(idx++); + + break; + } + } + } + catch (InvalidCastException e) + { + Error( + originFunc, + string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); + } + return null; } @@ -8225,7 +8336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int linknumber = remaining.GetLSLIntegerItem(0); rules = remaining.GetSublist(1, -1); - entity = GetLinkEntity(linknumber); + entity = GetLinkEntity(m_host, linknumber); } } @@ -8240,7 +8351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - return GetEntityParams(GetLinkEntity(linknumber), rules); + return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); } public LSL_Vector GetAgentSize(ScenePresence sp) -- cgit v1.1