/* * 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.ComponentModel; using System.Xml; using System.Xml.Serialization; namespace libsecondlife { public partial class Primitive : LLObject { #region Enums /// /// Extra parameters for primitives, these flags are for features that have /// been added after the original ObjectFlags that has all eight bits /// reserved already /// [Flags] public enum ExtraParamType : ushort { /// Whether this object has flexible parameters Flexible = 0x10, /// Whether this object has light parameters Light = 0x20, /// Whether this object is a sculpted prim Sculpt = 0x30 } /// /// /// public enum JointType : byte { /// Invalid = 0, /// Hinge = 1, /// Point = 2, /// [Obsolete] LPoint = 3, /// [Obsolete] Wheel = 4 } /// /// /// public enum SculptType : byte { /// None = 0, /// Sphere = 1, /// Torus = 2, /// Plane = 3, /// Cylinder = 4 } #endregion Enums #region Subclasses /// /// Controls the texture animation of a particular prim /// [Serializable] public struct TextureAnimation { /// public uint Flags; /// public uint Face; /// public uint SizeX; /// public uint SizeY; /// public float Start; /// public float Length; /// public float Rate; /// /// /// /// /// 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; } } /// /// /// /// 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; } } /// /// Information on the flexible properties of a primitive /// [Serializable] public struct FlexibleData { /// public int Softness; /// public float Gravity; /// public float Drag; /// public float Wind; /// public float Tension; /// public LLVector3 Force; /// /// /// /// /// 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; } } /// /// /// /// 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; } } /// /// Information on the light properties of a primitive /// [Serializable] public struct LightData { /// public LLColor Color; /// public float Radius; /// public float Cutoff; /// public float Falloff; /// /// /// /// /// 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; } } /// /// /// /// 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; } } /// /// Information on the sculpt properties of a sculpted primitive /// [Serializable] 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 /// public TextureAnimation TextureAnim; /// public FlexibleData Flexible; /// public LightData Light; /// public SculptData Sculpt; /// public ParticleSystem ParticleSys; /// public ObjectManager.ClickAction ClickAction; /// public LLUUID Sound; /// Identifies the owner of the audio or particle system public LLUUID OwnerID; /// public byte SoundFlags; /// public float SoundGain; /// public float SoundRadius; /// public string Text; /// public LLColor TextColor; /// public string MediaURL; /// public JointType Joint; /// public LLVector3 JointPivot; /// public LLVector3 JointAxisOrAnchor; #endregion Public Members /// /// Default constructor /// 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 void ToXml(XmlWriter xmlWriter) { XmlSerializer serializer = new XmlSerializer(typeof(Primitive)); serializer.Serialize(xmlWriter, this); } public static Primitive FromXml(XmlReader xmlReader) { XmlSerializer serializer = new XmlSerializer(typeof(Primitive)); return (Primitive)serializer.Deserialize(xmlReader); } 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; } } }