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
0.8.0.3
Justin Clark-Casey (justincc) 2014-02-26 23:07:13 +00:00
parent 26fe59c35e
commit 0e23374aa2
1 changed files with 128 additions and 17 deletions

View File

@ -313,6 +313,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// <returns> /// <returns>
/// The link entity. null if not found. /// The link entity. null if not found.
/// </returns> /// </returns>
/// <param name='part'></param>
/// <param name='linknum'> /// <param name='linknum'>
/// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4).
/// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. /// 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 /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then
/// null is returned. /// null is returned.
/// </param> /// </param>
public ISceneEntity GetLinkEntity(int linknum) public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
{ {
if (linknum < 0) if (linknum < 0)
{ {
if (linknum == ScriptBaseClass.LINK_THIS) if (linknum == ScriptBaseClass.LINK_THIS)
return m_host; return part;
else else
return null; return null;
} }
int actualPrimCount = m_host.ParentGroup.PrimCount; int actualPrimCount = part.ParentGroup.PrimCount;
List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); List<UUID> sittingAvatarIds = part.ParentGroup.GetSittingAvatars();
int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; 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 // 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 (linknum == 0)
{ {
if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
return m_host; return part;
return null; return null;
} }
@ -351,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1)
{ {
if (sittingAvatarIds.Count > 0) if (sittingAvatarIds.Count > 0)
return m_host.ParentGroup.RootPart; return part.ParentGroup.RootPart;
else else
return null; return null;
} }
@ -359,7 +360,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
if (linknum <= actualPrimCount) if (linknum <= actualPrimCount)
{ {
return m_host.ParentGroup.GetLinkNumPart(linknum); return part.ParentGroup.GetLinkNumPart(linknum);
} }
else else
{ {
@ -427,6 +428,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
public List<ISceneEntity> GetLinkEntities(int linkType)
{
return GetLinkEntities(m_host, linkType);
}
public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType)
{
List<ISceneEntity> ret = new List<ISceneEntity>();
ret.Add(part);
switch (linkType)
{
case ScriptBaseClass.LINK_SET:
return new List<ISceneEntity>(part.ParentGroup.Parts);
case ScriptBaseClass.LINK_ROOT:
ret = new List<ISceneEntity>();
ret.Add(part.ParentGroup.RootPart);
return ret;
case ScriptBaseClass.LINK_ALL_OTHERS:
ret = new List<ISceneEntity>(part.ParentGroup.Parts);
if (ret.Contains(part))
ret.Remove(part);
return ret;
case ScriptBaseClass.LINK_ALL_CHILDREN:
ret = new List<ISceneEntity>(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>();
ISceneEntity target = GetLinkEntity(part, linkType);
if (target == null)
return new List<ISceneEntity>();
ret = new List<ISceneEntity>();
ret.Add(target);
return ret;
}
}
//These are the implementations of the various ll-functions used by the LSL scripts. //These are the implementations of the various ll-functions used by the LSL scripts.
public LSL_Float llSin(double f) public LSL_Float llSin(double f)
{ {
@ -3882,7 +3934,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
ISceneEntity entity = GetLinkEntity(linknum); ISceneEntity entity = GetLinkEntity(m_host, linknum);
if (entity != null) if (entity != null)
return entity.UUID.ToString(); return entity.UUID.ToString();
@ -3933,7 +3985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
ISceneEntity entity = GetLinkEntity(linknum); ISceneEntity entity = GetLinkEntity(m_host, linknum);
if (entity != null) if (entity != null)
return entity.Name; return entity.Name;
@ -7371,22 +7423,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
{ {
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<ISceneEntity> entities = GetLinkEntities(linknumber);
LSL_List remaining = null; LSL_List remaining = null;
uint rulesParsed = 0; uint rulesParsed = 0;
foreach (SceneObjectPart part in parts) foreach (ISceneEntity entity in entities)
remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); {
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) while (remaining != null && remaining.Length > 2)
{ {
linknumber = remaining.GetLSLIntegerItem(0); linknumber = remaining.GetLSLIntegerItem(0);
rules = remaining.GetSublist(1, -1); rules = remaining.GetSublist(1, -1);
parts = GetLinkParts(linknumber); entities = GetLinkEntities(linknumber);
foreach (SceneObjectPart part in parts) foreach (ISceneEntity entity in entities)
remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); {
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; return null;
} }
@ -8225,7 +8336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
int linknumber = remaining.GetLSLIntegerItem(0); int linknumber = remaining.GetLSLIntegerItem(0);
rules = remaining.GetSublist(1, -1); 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); m_host.AddScriptLPS(1);
return GetEntityParams(GetLinkEntity(linknumber), rules); return GetEntityParams(GetLinkEntity(m_host, linknumber), rules);
} }
public LSL_Vector GetAgentSize(ScenePresence sp) public LSL_Vector GetAgentSize(ScenePresence sp)