public LSL_List GetLinkPrimitiveParams(ISceneChildEntity part, LSL_List rules)
{
LSL_List res = new LSL_List();
int idx = 0;
while (idx < rules.Length)
{
int code = rules.GetLSLIntegerItem(idx++);
int remain = rules.Length - idx;
Primitive.TextureEntry tex = part.Shape.Textures;
int face = 0;
if (code == (int)ScriptBaseClass.PRIM_NAME)
{
res.Add(new LSL_String(part.Name));
}
else if (code == (int)ScriptBaseClass.PRIM_DESC)
{
res.Add(new LSL_String(part.Description));
}
else if (code == (int)ScriptBaseClass.PRIM_MATERIAL)
{
res.Add(new LSL_Integer(part.Material));
}
else if (code == (int)ScriptBaseClass.PRIM_PHYSICS)
{
res.Add((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0
? new LSL_Integer(1)
: new LSL_Integer(0));
}
else if (code == (int)ScriptBaseClass.PRIM_TEMP_ON_REZ)
{
res.Add((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0
? new LSL_Integer(1)
: new LSL_Integer(0));
}
else if (code == (int)ScriptBaseClass.PRIM_PHANTOM)
{
res.Add((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0
? new LSL_Integer(1)
: new LSL_Integer(0));
}
else if (code == (int)ScriptBaseClass.PRIM_POSITION)
{
Vector3 tmp = part.AbsolutePosition;
LSL_Vector v = new LSL_Vector(tmp.X,
tmp.Y,
tmp.Z);
// For some reason, the part.AbsolutePosition.* values do not change if the
// linkset is rotated; they always reflect the child prim's world position
// as though the linkset is unrotated. This is incompatible behavior with SL's
// implementation, so will break scripts imported from there (not to mention it
// makes it more difficult to determine a child prim's actual inworld position).
if (part.ParentID != 0)
{
LSL_Rotation rtmp = llGetRootRotation();
LSL_Vector rpos = llGetRootPosition();
v = ((v - rpos) * rtmp) + rpos;
}
res.Add(v);
}
else if (code == (int)ScriptBaseClass.PRIM_POS_LOCAL)
{
res.Add(GetLocalPos(part));
}
else if (code == (int)ScriptBaseClass.PRIM_SIZE)
{
Vector3 tmp = part.Scale;
res.Add(new LSL_Vector(tmp.X,
tmp.Y,
tmp.Z));
}
else if (code == (int)ScriptBaseClass.PRIM_ROTATION)
{
res.Add(GetPartRot(part));
}
else if (code == (int)ScriptBaseClass.PRIM_TYPE)
{
// implementing box
PrimitiveBaseShape Shape = part.Shape;
int primType = (int)part.GetPrimType();
res.Add(new LSL_Integer(primType));
double topshearx = (sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
double topsheary = (sbyte)Shape.PathShearY / 100.0; // and PathShearY.
if (primType == ScriptBaseClass.PRIM_TYPE_BOX ||
primType == ScriptBaseClass.PRIM_TYPE_CYLINDER ||
primType == ScriptBaseClass.PRIM_TYPE_PRISM)
{
res.Add(new LSL_Integer(Shape.ProfileCurve));
res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
res.Add(new LSL_Vector(topshearx, topsheary, 0));
}
if (primType == ScriptBaseClass.PRIM_TYPE_SPHERE)
{
res.Add(new LSL_Integer(Shape.ProfileCurve));
res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
}
if (primType == ScriptBaseClass.PRIM_TYPE_SCULPT)
{
res.Add(Shape.SculptTexture.ToString());
res.Add(new LSL_Integer(Shape.SculptType));
}
if (primType == ScriptBaseClass.PRIM_TYPE_RING ||
primType == ScriptBaseClass.PRIM_TYPE_TUBE ||
primType == ScriptBaseClass.PRIM_TYPE_TORUS)
{
// holeshape
res.Add(new LSL_Integer(Shape.ProfileCurve));
// cut
res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
// hollow
res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
// twist
res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
// vector holesize
res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
// vector topshear
res.Add(new LSL_Vector(topshearx, topsheary, 0));
// vector profilecut
res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
// vector tapera
res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
// float revolutions
res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
// Slightly inaccurate, because an unsigned byte is being used to represent
// the entire range of floating-point values from 1.0 through 4.0 (which is how
// SL does it).
//
// Using these formulas to store and retrieve PathRevolutions, it is not
// possible to use all values between 1.00 and 4.00. For instance, you can't
// represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
// use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
// with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
// behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
// In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
// such as 1.10. So, SL must store and retreive the actual user input rather
// than only storing the encoded value.
// float radiusoffset
res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
// float skew
res.Add(new LSL_Float(Shape.PathSkew / 100.0));
}
}
else if (code == (int)ScriptBaseClass.PRIM_TEXTURE)
{
if (remain < 1)
return res;
face = rules.GetLSLIntegerItem(idx++);
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
res.Add(new LSL_String(texface.TextureID.ToString()));
res.Add(new LSL_Vector(texface.RepeatU,
texface.RepeatV,
0));
res.Add(new LSL_Vector(texface.OffsetU,
texface.OffsetV,
0));
res.Add(new LSL_Float(texface.Rotation));
}
}
else
{
if (face >= 0 && face < GetNumberOfSides(part))
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
res.Add(new LSL_String(texface.TextureID.ToString()));
res.Add(new LSL_Vector(texface.RepeatU,
texface.RepeatV,
0));
res.Add(new LSL_Vector(texface.OffsetU,
texface.OffsetV,
0));
res.Add(new LSL_Float(texface.Rotation));
}
}
}
else if (code == (int)ScriptBaseClass.PRIM_COLOR)
{
if (remain < 1)
return res;
face = rules.GetLSLIntegerItem(idx++);
tex = part.Shape.Textures;
Color4 texcolor;
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
texcolor = tex.GetFace((uint)face).RGBA;
res.Add(new LSL_Vector(texcolor.R,
texcolor.G,
texcolor.B));
res.Add(new LSL_Float(texcolor.A));
}
}
else
{
texcolor = tex.GetFace((uint)face).RGBA;
res.Add(new LSL_Vector(texcolor.R,
texcolor.G,
texcolor.B));
res.Add(new LSL_Float(texcolor.A));
}
}
else if (code == (int)ScriptBaseClass.PRIM_BUMP_SHINY)
{
if (remain < 1)
return res;
face = rules.GetLSLIntegerItem(idx++);
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
// Convert Shininess to PRIM_SHINY_*
res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
// PRIM_BUMP_*
res.Add(new LSL_Integer((int)texface.Bump));
}
}
else
{
if (face >= 0 && face < GetNumberOfSides(part))
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
// Convert Shininess to PRIM_SHINY_*
res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
// PRIM_BUMP_*
res.Add(new LSL_Integer((int)texface.Bump));
}
}
}
else if (code == (int)ScriptBaseClass.PRIM_FULLBRIGHT)
{
if (remain < 1)
return res;
face = rules.GetLSLIntegerItem(idx++);
tex = part.Shape.Textures;
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
}
}
else
{
if (face >= 0 && face < GetNumberOfSides(part))
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
}
}
}
else if (code == (int)ScriptBaseClass.PRIM_FLEXIBLE)
{
PrimitiveBaseShape shape = part.Shape;
res.Add(shape.FlexiEntry ? new LSL_Integer(1) : new LSL_Integer(0));
res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
res.Add(new LSL_Float(shape.FlexiDrag)); // friction
res.Add(new LSL_Float(shape.FlexiWind)); // wind
res.Add(new LSL_Float(shape.FlexiTension)); // tension
res.Add(new LSL_Vector(shape.FlexiForceX, // force
shape.FlexiForceY,
shape.FlexiForceZ));
}
else if (code == (int)ScriptBaseClass.PRIM_TEXGEN)
{
if (remain < 1)
return res;
face = rules.GetLSLIntegerItem(idx++);
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
MappingType texgen = tex.GetFace((uint)face).TexMapType;
// Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc.
res.Add(new LSL_Integer((uint)texgen >> 1));
}
}
else
{
if (face >= 0 && face < GetNumberOfSides(part))
{
MappingType texgen = tex.GetFace((uint)face).TexMapType;
res.Add(new LSL_Integer((uint)texgen >> 1));
}
}
}
else if (code == (int)ScriptBaseClass.PRIM_POINT_LIGHT)
{
PrimitiveBaseShape shape = part.Shape;
res.Add(shape.LightEntry ? new LSL_Integer(1) : new LSL_Integer(0));
res.Add(new LSL_Vector(shape.LightColorR, // color
shape.LightColorG,
shape.LightColorB));
res.Add(new LSL_Float(shape.LightIntensity)); // intensity
res.Add(new LSL_Float(shape.LightRadius)); // radius
res.Add(new LSL_Float(shape.LightFalloff)); // falloff
}
else if (code == (int)ScriptBaseClass.PRIM_GLOW)
{
if (remain < 1)
return res;
face = rules.GetLSLIntegerItem(idx++);
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
res.Add(new LSL_Float(texface.Glow));
}
}
else
{
if (face >= 0 && face < GetNumberOfSides(part))
{
Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
res.Add(new LSL_Float(texface.Glow));
}
}
}
else if (code == (int)ScriptBaseClass.PRIM_TEXT)
{
Color4 textColor = part.GetTextColor();
res.Add(new LSL_String(part.Text));
res.Add(new LSL_Vector(textColor.R,
textColor.G,
textColor.B));
res.Add(new LSL_Float(textColor.A));
}
else if (code == (int)ScriptBaseClass.PRIM_ROT_LOCAL)
{
Quaternion rtmp = part.RotationOffset;
res.Add(new LSL_Rotation(rtmp.X, rtmp.Y, rtmp.Z, rtmp.W));
}
else if (code == (int)ScriptBaseClass.PRIM_OMEGA)
{
Vector3 axis = part.OmegaAxis;
LSL_Float spinRate = part.OmegaSpinRate;
LSL_Float gain = part.OmegaGain;
res.Add(axis);
res.Add(spinRate);
res.Add(gain);
}
else if (code == (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE)
{
res.Add(new LSL_Integer(part.PhysicsType));
}
else if (code == (int)ScriptBaseClass.PRIM_LINK_TARGET)
{
if (remain < 1)
continue;
LSL_Integer nextLink = rules.GetLSLIntegerItem(idx++);
List<ISceneChildEntity> entities = GetLinkParts(nextLink);
if (entities.Count > 0)
part = entities[0];
}
}
return res;
}