Files
libremetaverse/libsecondlife/Prims.cs
John Hurliman 3013742668 * Increased SIMULATOR_TIMEOUT to 30 seconds
* Converted all timers to System.Threading timers to fix problems running in services and the CF
* UDPBase now uses our own ReaderWriterLock that is more efficient, and CF compatible
* Login uses a hand-created LoginProxy object instead of dynamically building the class with reflection .Emit()
* Replaced ParameterizedThreadStart calls with class-wide variables for CF compat.
* Removed transfer timeout code (irrelevant now that uploads go through CAPS)
* Added several new Helpers methods to wrap desktop and CF conditional code
* Replaced Monitor calls with AutoResetEvent in BlockingQueue
* InventoryNodeDictionary uses generics now
* Removed final lingering piece of XML serialization
* Added CookComputing.XmlRpc.CF.dll for the CF

git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1479 52acb1d6-8a22-11de-b505-999d5b087335
2007-11-06 09:26:10 +00:00

486 lines
16 KiB
C#

/*
* Copyright (c) 2006-2007, Second Life Reverse Engineering Team
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Neither the name of the Second Life Reverse Engineering Team nor the names
* of its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
namespace libsecondlife
{
public partial class Primitive : LLObject
{
#region Enums
/// <summary>
/// Extra parameters for primitives, these flags are for features that have
/// been added after the original ObjectFlags that has all eight bits
/// reserved already
/// </summary>
[Flags]
public enum ExtraParamType : ushort
{
/// <summary>Whether this object has flexible parameters</summary>
Flexible = 0x10,
/// <summary>Whether this object has light parameters</summary>
Light = 0x20,
/// <summary>Whether this object is a sculpted prim</summary>
Sculpt = 0x30
}
/// <summary>
///
/// </summary>
public enum JointType : byte
{
/// <summary></summary>
Invalid = 0,
/// <summary></summary>
Hinge = 1,
/// <summary></summary>
Point = 2,
/// <summary></summary>
[Obsolete]
LPoint = 3,
/// <summary></summary>
[Obsolete]
Wheel = 4
}
/// <summary>
///
/// </summary>
public enum SculptType : byte
{
/// <summary></summary>
None = 0,
/// <summary></summary>
Sphere = 1,
/// <summary></summary>
Torus = 2,
/// <summary></summary>
Plane = 3,
/// <summary></summary>
Cylinder = 4
}
/// <summary>
///
/// </summary>
public enum FaceType : ushort
{
/// <summary></summary>
PathBegin = 0x1 << 0,
/// <summary></summary>
PathEnd = 0x1 << 1,
/// <summary></summary>
InnerSide = 0x1 << 2,
/// <summary></summary>
ProfileBegin = 0x1 << 3,
/// <summary></summary>
ProfileEnd = 0x1 << 4,
/// <summary></summary>
OuterSide0 = 0x1 << 5,
/// <summary></summary>
OuterSide1 = 0x1 << 6,
/// <summary></summary>
OuterSide2 = 0x1 << 7,
/// <summary></summary>
OuterSide3 = 0x1 << 8
}
#endregion Enums
#region Subclasses
/// <summary>
/// Controls the texture animation of a particular prim
/// </summary>
public struct TextureAnimation
{
/// <summary></summary>
public uint Flags;
/// <summary></summary>
public uint Face;
/// <summary></summary>
public uint SizeX;
/// <summary></summary>
public uint SizeY;
/// <summary></summary>
public float Start;
/// <summary></summary>
public float Length;
/// <summary></summary>
public float Rate;
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
public TextureAnimation(byte[] data, int pos)
{
if (data.Length >= 16)
{
Flags = (uint)data[pos++];
Face = (uint)data[pos++];
SizeX = (uint)data[pos++];
SizeY = (uint)data[pos++];
Start = Helpers.BytesToFloat(data, pos);
Length = Helpers.BytesToFloat(data, pos + 4);
Rate = Helpers.BytesToFloat(data, pos + 8);
}
else
{
Flags = 0;
Face = 0;
SizeX = 0;
SizeY = 0;
Start = 0.0f;
Length = 0.0f;
Rate = 0.0f;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] GetBytes()
{
byte[] data = new byte[16];
int pos = 0;
data[pos++] = (byte)Flags;
data[pos++] = (byte)Face;
data[pos++] = (byte)SizeX;
data[pos++] = (byte)SizeY;
Helpers.FloatToBytes(Start).CopyTo(data, pos);
Helpers.FloatToBytes(Length).CopyTo(data, pos + 4);
Helpers.FloatToBytes(Rate).CopyTo(data, pos + 4);
return data;
}
}
/// <summary>
/// Information on the flexible properties of a primitive
/// </summary>
public struct FlexibleData
{
/// <summary></summary>
public int Softness;
/// <summary></summary>
public float Gravity;
/// <summary></summary>
public float Drag;
/// <summary></summary>
public float Wind;
/// <summary></summary>
public float Tension;
/// <summary></summary>
public LLVector3 Force;
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
public FlexibleData(byte[] data, int pos)
{
if (data.Length >= 5)
{
Softness = ((data[pos] & 0x80) >> 6) | ((data[pos + 1] & 0x80) >> 7);
Tension = (float)(data[pos++] & 0x7F) / 10.0f;
Drag = (float)(data[pos++] & 0x7F) / 10.0f;
Gravity = (float)(data[pos++] / 10.0f) - 10.0f;
Wind = (float)data[pos++] / 10.0f;
Force = new LLVector3(data, pos);
}
else
{
Softness = 0;
Tension = 0.0f;
Drag = 0.0f;
Gravity = 0.0f;
Wind = 0.0f;
Force = LLVector3.Zero;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] GetBytes()
{
byte[] data = new byte[16];
int i = 0;
// Softness is packed in the upper bits of tension and drag
data[i] = (byte)((Softness & 2) << 6);
data[i + 1] = (byte)((Softness & 1) << 7);
data[i++] |= (byte)((byte)(Tension * 10.01f) & 0x7F);
data[i++] |= (byte)((byte)(Drag * 10.01f) & 0x7F);
data[i++] = (byte)((Gravity + 10.0f) * 10.01f);
data[i++] = (byte)(Wind * 10.01f);
Force.GetBytes().CopyTo(data, i);
return data;
}
}
/// <summary>
/// Information on the light properties of a primitive
/// </summary>
public struct LightData
{
/// <summary></summary>
public LLColor Color;
/// <summary></summary>
public float Radius;
/// <summary></summary>
public float Cutoff;
/// <summary></summary>
public float Falloff;
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="pos"></param>
public LightData(byte[] data, int pos)
{
if (data.Length >= 16)
{
Color = new LLColor(data, 0);
Radius = Helpers.BytesToFloat(data, 4);
Cutoff = Helpers.BytesToFloat(data, 8);
Falloff = Helpers.BytesToFloat(data, 12);
}
else
{
Color = LLColor.Black;
Radius = 0.0f;
Cutoff = 0.0f;
Falloff = 0.0f;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] GetBytes()
{
byte[] data = new byte[16];
Color.GetBytes().CopyTo(data, 0);
Helpers.FloatToBytes(Radius).CopyTo(data, 4);
Helpers.FloatToBytes(Cutoff).CopyTo(data, 8);
Helpers.FloatToBytes(Falloff).CopyTo(data, 12);
return data;
}
}
/// <summary>
/// Information on the sculpt properties of a sculpted primitive
/// </summary>
public struct SculptData
{
public LLUUID SculptTexture;
public SculptType Type;
public SculptData(byte[] data, int pos)
{
if (data.Length >= 17)
{
SculptTexture = new LLUUID(data, pos);
Type = (SculptType)data[pos + 16];
}
else
{
SculptTexture = LLUUID.Zero;
Type = SculptType.None;
}
}
public byte[] GetBytes()
{
byte[] data = new byte[17];
SculptTexture.GetBytes().CopyTo(data, 0);
data[16] = (byte)Type;
return data;
}
}
#endregion Subclasses
#region Public Members
/// <summary></summary>
public TextureAnimation TextureAnim;
/// <summary></summary>
public FlexibleData Flexible;
/// <summary></summary>
public LightData Light;
/// <summary></summary>
public SculptData Sculpt;
/// <summary></summary>
public ParticleSystem ParticleSys;
/// <summary></summary>
public ObjectManager.ClickAction ClickAction;
/// <summary></summary>
public LLUUID Sound;
/// <summary>Identifies the owner of the audio or particle system</summary>
public LLUUID OwnerID;
/// <summary></summary>
public byte SoundFlags;
/// <summary></summary>
public float SoundGain;
/// <summary></summary>
public float SoundRadius;
/// <summary></summary>
public string Text;
/// <summary></summary>
public LLColor TextColor;
/// <summary></summary>
public string MediaURL;
/// <summary></summary>
public JointType Joint;
/// <summary></summary>
public LLVector3 JointPivot;
/// <summary></summary>
public LLVector3 JointAxisOrAnchor;
#endregion Public Members
/// <summary>
/// Default constructor
/// </summary>
public Primitive()
{
}
public override string ToString()
{
return String.Format("ID: {0}, GroupID: {1}, ParentID: {2}, LocalID: {3}, Flags: {4}, " +
"State: {5}, PCode: {6}, Material: {7}", ID, GroupID, ParentID, LocalID, Flags, Data.State,
Data.PCode, Data.Material);
}
public Dictionary<string, object> ToLLSD()
{
Dictionary<string, object> path = new Dictionary<string, object>(14);
path["begin"] = Data.PathBegin;
path["curve"] = Data.PathCurve;
path["end"] = Data.PathEnd;
path["radius_offset"] = Data.PathRadiusOffset;
path["revolutions"] = Data.PathRevolutions;
path["scale_x"] = Data.PathScaleX;
path["scale_y"] = Data.PathScaleY;
path["shear_x"] = Data.PathShearX;
path["shear_y"] = Data.PathShearY;
path["skew"] = Data.PathSkew;
path["taper_x"] = Data.PathTaperX;
path["taper_y"] = Data.PathTaperY;
path["twist"] = Data.PathTwist;
path["twist_begin"] = Data.PathTwistBegin;
Dictionary<string, object> profile = new Dictionary<string, object>(4);
profile["begin"] = Data.ProfileBegin;
profile["curve"] = Data.ProfileCurve;
profile["end"] = Data.ProfileEnd;
profile["hollow"] = Data.ProfileHollow;
Dictionary<string, object> volume = new Dictionary<string, object>(2);
volume["path"] = path;
volume["profile"] = profile;
Dictionary<string, object> prim = new Dictionary<string, object>(9);
prim["phantom"] = ((Flags & ObjectFlags.Phantom) != 0);
prim["physical"] = ((Flags & ObjectFlags.Physics) != 0);
prim["position"] = Position.ToLLSD();
prim["rotation"] = Rotation.ToLLSD();
prim["scale"] = Scale.ToLLSD();
prim["shadows"] = ((Flags & ObjectFlags.CastShadows) != 0);
prim["textures"] = Textures.ToLLSD();
prim["volume"] = volume;
if (ParentID != 0)
prim["parentid"] = ParentID;
return prim;
}
internal int SetExtraParamsFromBytes(byte[] data, int pos)
{
int i = pos;
int totalLength = 1;
if (data.Length == 0 || pos >= data.Length)
return 0;
try
{
byte extraParamCount = data[i++];
for (int k = 0; k < extraParamCount; k++)
{
ExtraParamType type = (ExtraParamType)Helpers.BytesToUInt16(data, i);
i += 2;
uint paramLength = Helpers.BytesToUIntBig(data, i);
i += 4;
if (type == ExtraParamType.Flexible)
Flexible = new FlexibleData(data, i);
else if (type == ExtraParamType.Light)
Light = new LightData(data, i);
else if (type == ExtraParamType.Sculpt)
Sculpt = new SculptData(data, i);
i += (int)paramLength;
totalLength += (int)paramLength + 6;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return totalLength;
}
}
}