public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
{
int idx = 0;
while (idx < rules.Length)
{
int code = (int)rules.GetLSLIntegerItem(idx++);
int remain = rules.Length - idx;
switch (code)
{
case (int)ScriptBaseClass.PRIM_MATERIAL:
res.Add(new LSL_Integer(part.Material));
break;
case (int)ScriptBaseClass.PRIM_PHYSICS:
if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
res.Add(new LSL_Integer(1));
else
res.Add(new LSL_Integer(0));
break;
case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
res.Add(new LSL_Integer(1));
else
res.Add(new LSL_Integer(0));
break;
case (int)ScriptBaseClass.PRIM_PHANTOM:
if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
res.Add(new LSL_Integer(1));
else
res.Add(new LSL_Integer(0));
break;
case (int)ScriptBaseClass.PRIM_POSITION:
LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
part.AbsolutePosition.Y,
part.AbsolutePosition.Z);
res.Add(v);
break;
case (int)ScriptBaseClass.PRIM_SIZE:
res.Add(new LSL_Vector(part.Scale));
break;
case (int)ScriptBaseClass.PRIM_ROTATION:
res.Add(GetPartRot(part));
break;
case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
res.Add(new LSL_Integer((int)part.PhysicsShapeType));
break;
case (int)ScriptBaseClass.PRIM_TYPE:
// implementing box
PrimitiveBaseShape Shape = part.Shape;
int primType = (int)part.GetPrimType();
res.Add(new LSL_Integer(primType));
double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY.
switch (primType)
{
case ScriptBaseClass.PRIM_TYPE_BOX:
case ScriptBaseClass.PRIM_TYPE_CYLINDER:
case ScriptBaseClass.PRIM_TYPE_PRISM:
res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
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));
break;
case ScriptBaseClass.PRIM_TYPE_SPHERE:
res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
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));
break;
case ScriptBaseClass.PRIM_TYPE_SCULPT:
res.Add(new LSL_String(Shape.SculptTexture.ToString()));
res.Add(new LSL_Integer(Shape.SculptType));
break;
case ScriptBaseClass.PRIM_TYPE_RING:
case ScriptBaseClass.PRIM_TYPE_TUBE:
case ScriptBaseClass.PRIM_TYPE_TORUS:
// holeshape
res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
// 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));
break;
}
break;
case (int)ScriptBaseClass.PRIM_TEXTURE:
if (remain < 1)
return new LSL_List();
int face = (int)rules.GetLSLIntegerItem(idx++);
Primitive.TextureEntry 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_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));
}
}
break;
case (int)ScriptBaseClass.PRIM_COLOR:
if (remain < 1)
return new LSL_List();
face = (int)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));
}
break;
case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
if (remain < 1)
return new LSL_List();
face = (int)rules.GetLSLIntegerItem(idx++);
tex = part.Shape.Textures;
int shiny;
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
Shininess shinyness = tex.GetFace((uint)face).Shiny;
if (shinyness == Shininess.High)
{
shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
}
else if (shinyness == Shininess.Medium)
{
shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
}
else if (shinyness == Shininess.Low)
{
shiny = ScriptBaseClass.PRIM_SHINY_LOW;
}
else
{
shiny = ScriptBaseClass.PRIM_SHINY_NONE;
}
res.Add(new LSL_Integer(shiny));
res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
}
}
else
{
Shininess shinyness = tex.GetFace((uint)face).Shiny;
if (shinyness == Shininess.High)
{
shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
}
else if (shinyness == Shininess.Medium)
{
shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
}
else if (shinyness == Shininess.Low)
{
shiny = ScriptBaseClass.PRIM_SHINY_LOW;
}
else
{
shiny = ScriptBaseClass.PRIM_SHINY_NONE;
}
res.Add(new LSL_Integer(shiny));
res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
}
break;
case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
if (remain < 1)
return new LSL_List();
face = (int)rules.GetLSLIntegerItem(idx++);
tex = part.Shape.Textures;
int fullbright;
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
if (tex.GetFace((uint)face).Fullbright == true)
{
fullbright = ScriptBaseClass.TRUE;
}
else
{
fullbright = ScriptBaseClass.FALSE;
}
res.Add(new LSL_Integer(fullbright));
}
}
else
{
if (tex.GetFace((uint)face).Fullbright == true)
{
fullbright = ScriptBaseClass.TRUE;
}
else
{
fullbright = ScriptBaseClass.FALSE;
}
res.Add(new LSL_Integer(fullbright));
}
break;
case (int)ScriptBaseClass.PRIM_FLEXIBLE:
PrimitiveBaseShape shape = part.Shape;
if (shape.FlexiEntry)
res.Add(new LSL_Integer(1)); // active
else
res.Add(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));
break;
case (int)ScriptBaseClass.PRIM_TEXGEN:
// (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
if (remain < 1)
return new LSL_List();
face = (int)rules.GetLSLIntegerItem(idx++);
tex = part.Shape.Textures;
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
{
res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
}
else
{
res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
}
}
}
else
{
if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
{
res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
}
else
{
res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
}
}
break;
case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
shape = part.Shape;
if (shape.LightEntry)
res.Add(new LSL_Integer(1)); // active
else
res.Add(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
break;
case (int)ScriptBaseClass.PRIM_GLOW:
if (remain < 1)
return new LSL_List();
face = (int)rules.GetLSLIntegerItem(idx++);
tex = part.Shape.Textures;
float primglow;
if (face == ScriptBaseClass.ALL_SIDES)
{
for (face = 0; face < GetNumberOfSides(part); face++)
{
primglow = tex.GetFace((uint)face).Glow;
res.Add(new LSL_Float(primglow));
}
}
else
{
primglow = tex.GetFace((uint)face).Glow;
res.Add(new LSL_Float(primglow));
}
break;
case (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));
break;
case (int)ScriptBaseClass.PRIM_NAME:
res.Add(new LSL_String(part.Name));
break;
case (int)ScriptBaseClass.PRIM_DESC:
res.Add(new LSL_String(part.Description));
break;
case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
res.Add(new LSL_Rotation(part.RotationOffset));
break;
case (int)ScriptBaseClass.PRIM_POS_LOCAL:
res.Add(new LSL_Vector(GetPartLocalPos(part)));
break;
case (int)ScriptBaseClass.PRIM_SLICE:
PrimType prim_type = part.GetPrimType();
bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING);
res.Add(new LSL_Vector(
(useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0,
1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0,
0
));
break;
case (int)ScriptBaseClass.PRIM_OMEGA:
// this may return values diferent from SL since we don't handle set the same way
float gain = 1.0f; // we don't use gain and don't store it
Vector3 axis = part.AngularVelocity;
float spin = axis.Length();
if(spin < 1.0e-6)
{
axis = Vector3.Zero;
gain = 0.0f;
spin = 0.0f;
}
else
{
axis = axis * (1.0f/spin);
}
res.Add(new LSL_Vector(axis.X,
axis.Y,
axis.Z));
res.Add(new LSL_Float(spin));
res.Add(new LSL_Float(gain));
break;
case (int)ScriptBaseClass.PRIM_SIT_TARGET:
if(part.IsSitTargetSet)
{
res.Add(new LSL_Integer(1));
res.Add(new LSL_Vector(part.SitTargetPosition));
res.Add(new LSL_Rotation(part.SitTargetOrientation));
}
else
{
res.Add(new LSL_Integer(0));
res.Add(new LSL_Vector(Vector3.Zero));
res.Add(new LSL_Rotation(Quaternion.Identity));
}
break;
case (int)ScriptBaseClass.PRIM_LINK_TARGET:
// TODO: Should be issuing a runtime script warning in this case.
if (remain < 2)
return new LSL_List();
return rules.GetSublist(idx, -1);
}
}
return new LSL_List();
}