diff --git a/OpenMetaverse/Messages/LindenMessages.cs b/OpenMetaverse/Messages/LindenMessages.cs
index 4ac54e3f..3b8305f9 100644
--- a/OpenMetaverse/Messages/LindenMessages.cs
+++ b/OpenMetaverse/Messages/LindenMessages.cs
@@ -4112,6 +4112,57 @@ namespace OpenMetaverse.Messages.Linden
}
}
+ ///
+ /// Event Queue message describing physics engine attributes of a list of objects
+ /// Sim sends these when object is selected
+ ///
+ public class ObjectPhysicsPropertiesMessage : IMessage
+ {
+ /// Array with the list of physics properties
+ public Primitive.PhysicsProperties[] ObjectPhysicsProperties;
+
+ ///
+ /// Serializes the message
+ ///
+ /// Serialized OSD
+ public OSDMap Serialize()
+ {
+ OSDMap ret = new OSDMap();
+ OSDArray array = new OSDArray();
+
+ for (int i = 0; i < ObjectPhysicsProperties.Length; i++)
+ {
+ array.Add(ObjectPhysicsProperties[i].GetOSD());
+ }
+
+ ret["ObjectData"] = array;
+ return ret;
+
+ }
+
+ ///
+ /// Deseializes the message
+ ///
+ /// Incoming data to deserialize
+ public void Deserialize(OSDMap map)
+ {
+ OSDArray array = map["ObjectData"] as OSDArray;
+ if (array != null)
+ {
+ ObjectPhysicsProperties = new Primitive.PhysicsProperties[array.Count];
+
+ for (int i = 0; i < array.Count; i++)
+ {
+ ObjectPhysicsProperties[i] = Primitive.PhysicsProperties.FromOSD(array[i]);
+ }
+ }
+ else
+ {
+ ObjectPhysicsProperties = new Primitive.PhysicsProperties[0];
+ }
+ }
+ }
+
#endregion Object Messages
#region Object Media Messages
diff --git a/OpenMetaverse/Messages/MessageEventDecoder.cs b/OpenMetaverse/Messages/MessageEventDecoder.cs
index add5eea8..4847ac60 100644
--- a/OpenMetaverse/Messages/MessageEventDecoder.cs
+++ b/OpenMetaverse/Messages/MessageEventDecoder.cs
@@ -96,6 +96,7 @@ namespace OpenMetaverse.Messages
case "SetDisplayNameReply": message = new SetDisplayNameReplyMessage(); break;
case "DisplayNameUpdate": message = new DisplayNameUpdateMessage(); break;
//case "ProductInfoRequest": message = new ProductInfoRequestMessage(); break;
+ case "ObjectPhysicsProperties": message = new ObjectPhysicsPropertiesMessage(); break;
// Capabilities TODO:
// DispatchRegionInfo
@@ -127,7 +128,7 @@ namespace OpenMetaverse.Messages
}
catch (Exception e)
{
- Logger.Log("Exception while tring to Deserialize " + eventName + ":" + e.Message + ": " + e.StackTrace, Helpers.LogLevel.Error);
+ Logger.Log("Exception while trying to Deserialize " + eventName + ":" + e.Message + ": " + e.StackTrace, Helpers.LogLevel.Error);
}
return null;
diff --git a/OpenMetaverse/ObjectManager.cs b/OpenMetaverse/ObjectManager.cs
index cf26d92a..7ce314f6 100644
--- a/OpenMetaverse/ObjectManager.cs
+++ b/OpenMetaverse/ObjectManager.cs
@@ -30,6 +30,7 @@ using System.Threading;
using OpenMetaverse.Packets;
using OpenMetaverse.Http;
using OpenMetaverse.StructuredData;
+using OpenMetaverse.Interfaces;
using OpenMetaverse.Messages.Linden;
namespace OpenMetaverse
@@ -398,6 +399,32 @@ namespace OpenMetaverse
/// Array indexed on prim face of media entry data
public delegate void ObjectMediaCallback(bool success, string version, MediaEntry[] faceMedia);
+ /// The event subscribers, null of no subscribers
+ private EventHandler m_PhysicsProperties;
+
+ ///Raises the PhysicsProperties Event
+ /// A PhysicsPropertiesEventArgs object containing
+ /// the data sent from the simulator
+ protected virtual void OnPhysicsProperties(PhysicsPropertiesEventArgs e)
+ {
+ EventHandler handler = m_PhysicsProperties;
+ if (handler != null)
+ handler(this, e);
+ }
+
+ /// Thread sync lock object
+ private readonly object m_PhysicsPropertiesLock = new object();
+
+ /// Raised when the simulator sends us data containing
+ /// additional information
+ ///
+ ///
+ public event EventHandler PhysicsProperties
+ {
+ add { lock (m_PhysicsPropertiesLock) { m_PhysicsProperties += value; } }
+ remove { lock (m_PhysicsPropertiesLock) { m_PhysicsProperties -= value; } }
+ }
+
#endregion Delegates
/// Reference to the GridClient object
@@ -422,6 +449,7 @@ namespace OpenMetaverse
Client.Network.RegisterCallback(PacketType.ObjectPropertiesFamily, ObjectPropertiesFamilyHandler);
Client.Network.RegisterCallback(PacketType.ObjectProperties, ObjectPropertiesHandler);
Client.Network.RegisterCallback(PacketType.PayPriceReply, PayPriceReplyHandler);
+ Client.Network.RegisterEventCallback("ObjectPhysicsProperties", ObjectPhysicsPropertiesHandler);
}
#region Internal event handlers
@@ -1976,12 +2004,12 @@ namespace OpenMetaverse
prim.TreeSpecies = (Tree)block.Data[0];
else
Logger.Log("Got a foliage update with an invalid TreeSpecies field", Helpers.LogLevel.Warning);
- // prim.ScratchPad = Utils.EmptyBytes;
- // break;
- //default:
- // prim.ScratchPad = new byte[block.Data.Length];
- // if (block.Data.Length > 0)
- // Buffer.BlockCopy(block.Data, 0, prim.ScratchPad, 0, prim.ScratchPad.Length);
+ // prim.ScratchPad = Utils.EmptyBytes;
+ // break;
+ //default:
+ // prim.ScratchPad = new byte[block.Data.Length];
+ // if (block.Data.Length > 0)
+ // Buffer.BlockCopy(block.Data, 0, prim.ScratchPad, 0, prim.ScratchPad.Length);
break;
}
prim.ScratchPad = Utils.EmptyBytes;
@@ -2770,6 +2798,39 @@ namespace OpenMetaverse
}
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void ObjectPhysicsPropertiesHandler(string capsKey, IMessage message, Simulator simulator)
+ {
+ ObjectPhysicsPropertiesMessage msg = (ObjectPhysicsPropertiesMessage)message;
+ if (m_PhysicsProperties != null)
+ {
+ for (int i = 0; i < msg.ObjectPhysicsProperties.Length; i++)
+ {
+ OnPhysicsProperties(new PhysicsPropertiesEventArgs(simulator, msg.ObjectPhysicsProperties[i]));
+ }
+ }
+
+ if (Client.Settings.OBJECT_TRACKING)
+ {
+ for (int i = 0; i < msg.ObjectPhysicsProperties.Length; i++)
+ {
+ lock (simulator.ObjectsPrimitives.Dictionary)
+ {
+ if (simulator.ObjectsPrimitives.Dictionary.ContainsKey(msg.ObjectPhysicsProperties[i].LocalID))
+ {
+ simulator.ObjectsPrimitives.Dictionary[msg.ObjectPhysicsProperties[i].LocalID].PhysicsProps = msg.ObjectPhysicsProperties[i];
+ }
+ }
+ }
+ }
+
+ }
+
#endregion Packet Handlers
#region Utility Functions
@@ -3559,5 +3620,27 @@ namespace OpenMetaverse
}
}
+ ///
+ /// Set when simulator sends us infomation on primitive's physical properties
+ ///
+ public class PhysicsPropertiesEventArgs : EventArgs
+ {
+ /// Simulator where the message originated
+ public Simulator Simulator;
+ /// Updated physical properties
+ public Primitive.PhysicsProperties PhysicsProperties;
+
+ ///
+ /// Constructor
+ ///
+ /// Simulator where the message originated
+ /// Updated physical properties
+ public PhysicsPropertiesEventArgs(Simulator sim, Primitive.PhysicsProperties props)
+ {
+ Simulator = sim;
+ PhysicsProperties = props;
+ }
+ }
+
#endregion
}
diff --git a/OpenMetaverse/Primitives/Primitive.cs b/OpenMetaverse/Primitives/Primitive.cs
index d80bcfc4..a1eef6b3 100644
--- a/OpenMetaverse/Primitives/Primitive.cs
+++ b/OpenMetaverse/Primitives/Primitive.cs
@@ -1,1278 +1,1338 @@
-/*
- * Copyright (c) 2006-2008, openmetaverse.org
- * 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 openmetaverse.org 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;
-using OpenMetaverse.StructuredData;
-
-namespace OpenMetaverse
-{
- public partial class Primitive : IEquatable
- {
- // Used for packing and unpacking parameters
- protected const float CUT_QUANTA = 0.00002f;
- protected const float SCALE_QUANTA = 0.01f;
- protected const float SHEAR_QUANTA = 0.01f;
- protected const float TAPER_QUANTA = 0.01f;
- protected const float REV_QUANTA = 0.015f;
- protected const float HOLLOW_QUANTA = 0.00002f;
-
- #region Subclasses
-
- ///
- /// Parameters used to construct a visual representation of a primitive
- ///
- public struct ConstructionData
- {
- private const byte PROFILE_MASK = 0x0F;
- private const byte HOLE_MASK = 0xF0;
-
- ///
- public byte profileCurve;
- ///
- public PathCurve PathCurve;
- ///
- public float PathEnd;
- ///
- public float PathRadiusOffset;
- ///
- public float PathSkew;
- ///
- public float PathScaleX;
- ///
- public float PathScaleY;
- ///
- public float PathShearX;
- ///
- public float PathShearY;
- ///
- public float PathTaperX;
- ///
- public float PathTaperY;
- ///
- public float PathBegin;
- ///
- public float PathTwist;
- ///
- public float PathTwistBegin;
- ///
- public float PathRevolutions;
- ///
- public float ProfileBegin;
- ///
- public float ProfileEnd;
- ///
- public float ProfileHollow;
-
- ///
- public Material Material;
- ///
- public byte State;
- ///
- public PCode PCode;
-
- #region Properties
-
- /// Attachment point to an avatar
- public AttachmentPoint AttachmentPoint
- {
- get { return (AttachmentPoint)Utils.SwapWords(State); }
- set { State = (byte)Utils.SwapWords((byte)value); }
- }
-
- ///
- public ProfileCurve ProfileCurve
- {
- get { return (ProfileCurve)(profileCurve & PROFILE_MASK); }
- set
- {
- profileCurve &= HOLE_MASK;
- profileCurve |= (byte)value;
- }
- }
-
- ///
- public HoleType ProfileHole
- {
- get { return (HoleType)(profileCurve & HOLE_MASK); }
- set
- {
- profileCurve &= PROFILE_MASK;
- profileCurve |= (byte)value;
- }
- }
-
- ///
- public Vector2 PathBeginScale
- {
- get
- {
- Vector2 begin = new Vector2(1f, 1f);
- if (PathScaleX > 1f)
- begin.X = 2f - PathScaleX;
- if (PathScaleY > 1f)
- begin.Y = 2f - PathScaleY;
- return begin;
- }
- }
-
- ///
- public Vector2 PathEndScale
- {
- get
- {
- Vector2 end = new Vector2(1f, 1f);
- if (PathScaleX < 1f)
- end.X = PathScaleX;
- if (PathScaleY < 1f)
- end.Y = PathScaleY;
- return end;
- }
- }
-
- #endregion Properties
- }
-
- ///
- /// Information on the flexible properties of a primitive
- ///
- public class FlexibleData
- {
- ///
- public int Softness;
- ///
- public float Gravity;
- ///
- public float Drag;
- ///
- public float Wind;
- ///
- public float Tension;
- ///
- public Vector3 Force;
-
- ///
- /// Default constructor
- ///
- public FlexibleData()
- {
- }
-
- ///
- ///
- ///
- ///
- ///
- 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 Vector3(data, pos);
- }
- else
- {
- Softness = 0;
-
- Tension = 0.0f;
- Drag = 0.0f;
- Gravity = 0.0f;
- Wind = 0.0f;
- Force = Vector3.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;
- }
-
- ///
- ///
- ///
- ///
- public OSD GetOSD()
- {
- OSDMap map = new OSDMap();
-
- map["simulate_lod"] = OSD.FromInteger(Softness);
- map["gravity"] = OSD.FromReal(Gravity);
- map["air_friction"] = OSD.FromReal(Drag);
- map["wind_sensitivity"] = OSD.FromReal(Wind);
- map["tension"] = OSD.FromReal(Tension);
- map["user_force"] = OSD.FromVector3(Force);
-
- return map;
- }
-
- public static FlexibleData FromOSD(OSD osd)
- {
- FlexibleData flex = new FlexibleData();
-
- if (osd.Type == OSDType.Map)
- {
- OSDMap map = (OSDMap)osd;
-
- flex.Softness = map["simulate_lod"].AsInteger();
- flex.Gravity = (float)map["gravity"].AsReal();
- flex.Drag = (float)map["air_friction"].AsReal();
- flex.Wind = (float)map["wind_sensitivity"].AsReal();
- flex.Tension = (float)map["tension"].AsReal();
- flex.Force = ((OSDArray)map["user_force"]).AsVector3();
- }
-
- return flex;
- }
-
- public override int GetHashCode()
- {
- return
- Softness.GetHashCode() ^
- Gravity.GetHashCode() ^
- Drag.GetHashCode() ^
- Wind.GetHashCode() ^
- Tension.GetHashCode() ^
- Force.GetHashCode();
- }
- }
-
- ///
- /// Information on the light properties of a primitive
- ///
- public class LightData
- {
- ///
- public Color4 Color;
- ///
- public float Intensity;
- ///
- public float Radius;
- ///
- public float Cutoff;
- ///
- public float Falloff;
-
- ///
- /// Default constructor
- ///
- public LightData()
- {
- }
-
- ///
- ///
- ///
- ///
- ///
- public LightData(byte[] data, int pos)
- {
- if (data.Length - pos >= 16)
- {
- Color = new Color4(data, pos, false);
- Radius = Utils.BytesToFloat(data, pos + 4);
- Cutoff = Utils.BytesToFloat(data, pos + 8);
- Falloff = Utils.BytesToFloat(data, pos + 12);
-
- // Alpha in color is actually intensity
- Intensity = Color.A;
- Color.A = 1f;
- }
- else
- {
- Color = Color4.Black;
- Radius = 0f;
- Cutoff = 0f;
- Falloff = 0f;
- Intensity = 0f;
- }
- }
-
- ///
- ///
- ///
- ///
- public byte[] GetBytes()
- {
- byte[] data = new byte[16];
-
- // Alpha channel in color is intensity
- Color4 tmpColor = Color;
- tmpColor.A = Intensity;
- tmpColor.GetBytes().CopyTo(data, 0);
- Utils.FloatToBytes(Radius).CopyTo(data, 4);
- Utils.FloatToBytes(Cutoff).CopyTo(data, 8);
- Utils.FloatToBytes(Falloff).CopyTo(data, 12);
-
- return data;
- }
-
- public OSD GetOSD()
- {
- OSDMap map = new OSDMap();
-
- map["color"] = OSD.FromColor4(Color);
- map["intensity"] = OSD.FromReal(Intensity);
- map["radius"] = OSD.FromReal(Radius);
- map["cutoff"] = OSD.FromReal(Cutoff);
- map["falloff"] = OSD.FromReal(Falloff);
-
- return map;
- }
-
- public static LightData FromOSD(OSD osd)
- {
- LightData light = new LightData();
-
- if (osd.Type == OSDType.Map)
- {
- OSDMap map = (OSDMap)osd;
-
- light.Color = ((OSDArray)map["color"]).AsColor4();
- light.Intensity = (float)map["intensity"].AsReal();
- light.Radius = (float)map["radius"].AsReal();
- light.Cutoff = (float)map["cutoff"].AsReal();
- light.Falloff = (float)map["falloff"].AsReal();
- }
-
- return light;
- }
-
- public override int GetHashCode()
- {
- return
- Color.GetHashCode() ^
- Intensity.GetHashCode() ^
- Radius.GetHashCode() ^
- Cutoff.GetHashCode() ^
- Falloff.GetHashCode();
- }
-
- ///
- ///
- ///
- ///
- public override string ToString()
- {
- return String.Format("Color: {0} Intensity: {1} Radius: {2} Cutoff: {3} Falloff: {4}",
- Color, Intensity, Radius, Cutoff, Falloff);
- }
- }
-
- ///
- /// Information on the sculpt properties of a sculpted primitive
- ///
- public class SculptData
- {
- public UUID SculptTexture;
- private byte type;
-
- public SculptType Type
- {
- get { return (SculptType)(type & 7); }
- set { type = (byte)value; }
- }
-
- ///
- /// Render inside out (inverts the normals).
- ///
- public bool Invert
- {
- get { return ((type & (byte)SculptType.Invert) != 0); }
- }
-
- ///
- /// Render an X axis mirror of the sculpty.
- ///
- public bool Mirror
- {
- get { return ((type & (byte)SculptType.Mirror) != 0); }
- }
-
- ///
- /// Default constructor
- ///
- public SculptData()
- {
- }
-
- ///
- ///
- ///
- ///
- ///
- public SculptData(byte[] data, int pos)
- {
- if (data.Length >= 17)
- {
- SculptTexture = new UUID(data, pos);
- type = data[pos + 16];
- }
- else
- {
- SculptTexture = UUID.Zero;
- type = (byte)SculptType.None;
- }
- }
-
- public byte[] GetBytes()
- {
- byte[] data = new byte[17];
-
- SculptTexture.GetBytes().CopyTo(data, 0);
- data[16] = type;
-
- return data;
- }
-
- public OSD GetOSD()
- {
- OSDMap map = new OSDMap();
-
- map["texture"] = OSD.FromUUID(SculptTexture);
- map["type"] = OSD.FromInteger(type);
-
- return map;
- }
-
- public static SculptData FromOSD(OSD osd)
- {
- SculptData sculpt = new SculptData();
-
- if (osd.Type == OSDType.Map)
- {
- OSDMap map = (OSDMap)osd;
-
- sculpt.SculptTexture = map["texture"].AsUUID();
- sculpt.type = (byte)map["type"].AsInteger();
- }
-
- return sculpt;
- }
-
- public override int GetHashCode()
- {
- return SculptTexture.GetHashCode() ^ type.GetHashCode();
- }
- }
-
- ///
- /// Extended properties to describe an object
- ///
- public class ObjectProperties
- {
- ///
- public UUID ObjectID;
- ///
- public UUID CreatorID;
- ///
- public UUID OwnerID;
- ///
- public UUID GroupID;
- ///
- public DateTime CreationDate;
- ///
- public Permissions Permissions;
- ///
- public int OwnershipCost;
- ///
- public SaleType SaleType;
- ///
- public int SalePrice;
- ///
- public byte AggregatePerms;
- ///
- public byte AggregatePermTextures;
- ///
- public byte AggregatePermTexturesOwner;
- ///
- public ObjectCategory Category;
- ///
- public short InventorySerial;
- ///
- public UUID ItemID;
- ///
- public UUID FolderID;
- ///
- public UUID FromTaskID;
- ///
- public UUID LastOwnerID;
- ///
- public string Name;
- ///
- public string Description;
- ///
- public string TouchName;
- ///
- public string SitName;
- ///
- public UUID[] TextureIDs;
-
- ///
- /// Default constructor
- ///
- public ObjectProperties()
- {
- Name = String.Empty;
- Description = String.Empty;
- TouchName = String.Empty;
- SitName = String.Empty;
- }
-
- ///
- /// Set the properties that are set in an ObjectPropertiesFamily packet
- ///
- /// that has
- /// been partially filled by an ObjectPropertiesFamily packet
- public void SetFamilyProperties(ObjectProperties props)
- {
- ObjectID = props.ObjectID;
- OwnerID = props.OwnerID;
- GroupID = props.GroupID;
- Permissions = props.Permissions;
- OwnershipCost = props.OwnershipCost;
- SaleType = props.SaleType;
- SalePrice = props.SalePrice;
- Category = props.Category;
- LastOwnerID = props.LastOwnerID;
- Name = props.Name;
- Description = props.Description;
- }
-
- public byte[] GetTextureIDBytes()
- {
- if (TextureIDs == null || TextureIDs.Length == 0)
- return Utils.EmptyBytes;
-
- byte[] bytes = new byte[16 * TextureIDs.Length];
- for (int i = 0; i < TextureIDs.Length; i++)
- TextureIDs[i].ToBytes(bytes, 16 * i);
-
- return bytes;
- }
- }
-
- #endregion Subclasses
-
- #region Public Members
-
- ///
- public UUID ID;
- ///
- public UUID GroupID;
- ///
- public uint LocalID;
- ///
- public uint ParentID;
- ///
- public ulong RegionHandle;
- ///
- public PrimFlags Flags;
- /// Foliage type for this primitive. Only applicable if this
- /// primitive is foliage
- public Tree TreeSpecies;
- /// Unknown
- public byte[] ScratchPad;
- ///
- public Vector3 Position;
- ///
- public Vector3 Scale;
- ///
- public Quaternion Rotation = Quaternion.Identity;
- ///
- public Vector3 Velocity;
- ///
- public Vector3 AngularVelocity;
- ///
- public Vector3 Acceleration;
- ///
- public Vector4 CollisionPlane;
- ///
- public FlexibleData Flexible;
- ///
- public LightData Light;
- ///
- public SculptData Sculpt;
- ///
- public ClickAction ClickAction;
- ///
- public UUID Sound;
- /// Identifies the owner if audio or a particle system is
- /// active
- public UUID OwnerID;
- ///
- public SoundFlags SoundFlags;
- ///
- public float SoundGain;
- ///
- public float SoundRadius;
- ///
- public string Text;
- ///
- public Color4 TextColor;
- ///
- public string MediaURL;
- ///
- public JointType Joint;
- ///
- public Vector3 JointPivot;
- ///
- public Vector3 JointAxisOrAnchor;
- ///
- public NameValue[] NameValues;
- ///
- public ConstructionData PrimData;
- ///
- public ObjectProperties Properties;
-
- #endregion Public Members
-
- #region Properties
-
- /// Uses basic heuristics to estimate the primitive shape
- public PrimType Type
- {
- get
- {
- if (Sculpt != null && Sculpt.Type != SculptType.None)
- return PrimType.Sculpt;
-
- bool linearPath = (PrimData.PathCurve == PathCurve.Line || PrimData.PathCurve == PathCurve.Flexible);
- float scaleY = PrimData.PathScaleY;
-
- if (linearPath)
- {
- switch (PrimData.ProfileCurve)
- {
- case ProfileCurve.Circle:
- return PrimType.Cylinder;
- case ProfileCurve.Square:
- return PrimType.Box;
- case ProfileCurve.IsoTriangle:
- case ProfileCurve.EqualTriangle:
- case ProfileCurve.RightTriangle:
- return PrimType.Prism;
- case ProfileCurve.HalfCircle:
- default:
- return PrimType.Unknown;
- }
- }
- else
- {
- switch (PrimData.PathCurve)
- {
- case PathCurve.Flexible:
- return PrimType.Unknown;
- case PathCurve.Circle:
- switch (PrimData.ProfileCurve)
- {
- case ProfileCurve.Circle:
- if (scaleY > 0.75f)
- return PrimType.Sphere;
- else
- return PrimType.Torus;
- case ProfileCurve.HalfCircle:
- return PrimType.Sphere;
- case ProfileCurve.EqualTriangle:
- return PrimType.Ring;
- case ProfileCurve.Square:
- if (scaleY <= 0.75f)
- return PrimType.Tube;
- else
- return PrimType.Unknown;
- default:
- return PrimType.Unknown;
- }
- case PathCurve.Circle2:
- if (PrimData.ProfileCurve == ProfileCurve.Circle)
- return PrimType.Sphere;
- else
- return PrimType.Unknown;
- default:
- return PrimType.Unknown;
- }
- }
- }
- }
-
- #endregion Properties
-
- #region Constructors
-
- ///
- /// Default constructor
- ///
- public Primitive()
- {
- // Default a few null property values to String.Empty
- Text = String.Empty;
- MediaURL = String.Empty;
- }
-
- public Primitive(Primitive prim)
- {
- ID = prim.ID;
- GroupID = prim.GroupID;
- LocalID = prim.LocalID;
- ParentID = prim.ParentID;
- RegionHandle = prim.RegionHandle;
- Flags = prim.Flags;
- TreeSpecies = prim.TreeSpecies;
- if (prim.ScratchPad != null)
- {
- ScratchPad = new byte[prim.ScratchPad.Length];
- Buffer.BlockCopy(prim.ScratchPad, 0, ScratchPad, 0, ScratchPad.Length);
- }
- else
- ScratchPad = Utils.EmptyBytes;
- Position = prim.Position;
- Scale = prim.Scale;
- Rotation = prim.Rotation;
- Velocity = prim.Velocity;
- AngularVelocity = prim.AngularVelocity;
- Acceleration = prim.Acceleration;
- CollisionPlane = prim.CollisionPlane;
- Flexible = prim.Flexible;
- Light = prim.Light;
- Sculpt = prim.Sculpt;
- ClickAction = prim.ClickAction;
- Sound = prim.Sound;
- OwnerID = prim.OwnerID;
- SoundFlags = prim.SoundFlags;
- SoundGain = prim.SoundGain;
- SoundRadius = prim.SoundRadius;
- Text = prim.Text;
- TextColor = prim.TextColor;
- MediaURL = prim.MediaURL;
- Joint = prim.Joint;
- JointPivot = prim.JointPivot;
- JointAxisOrAnchor = prim.JointAxisOrAnchor;
- if (prim.NameValues != null)
- {
- if (NameValues == null || NameValues.Length != prim.NameValues.Length)
- NameValues = new NameValue[prim.NameValues.Length];
- Array.Copy(prim.NameValues, NameValues, prim.NameValues.Length);
- }
- else
- NameValues = null;
- PrimData = prim.PrimData;
- Properties = prim.Properties;
- // FIXME: Get a real copy constructor for TextureEntry instead of serializing to bytes and back
- if (prim.Textures != null)
- {
- byte[] textureBytes = prim.Textures.GetBytes();
- Textures = new TextureEntry(textureBytes, 0, textureBytes.Length);
- }
- else
- {
- Textures = null;
- }
- TextureAnim = prim.TextureAnim;
- ParticleSys = prim.ParticleSys;
- }
-
- #endregion Constructors
-
- #region Public Methods
-
- public virtual OSD GetOSD()
- {
- OSDMap path = new OSDMap(14);
- path["begin"] = OSD.FromReal(PrimData.PathBegin);
- path["curve"] = OSD.FromInteger((int)PrimData.PathCurve);
- path["end"] = OSD.FromReal(PrimData.PathEnd);
- path["radius_offset"] = OSD.FromReal(PrimData.PathRadiusOffset);
- path["revolutions"] = OSD.FromReal(PrimData.PathRevolutions);
- path["scale_x"] = OSD.FromReal(PrimData.PathScaleX);
- path["scale_y"] = OSD.FromReal(PrimData.PathScaleY);
- path["shear_x"] = OSD.FromReal(PrimData.PathShearX);
- path["shear_y"] = OSD.FromReal(PrimData.PathShearY);
- path["skew"] = OSD.FromReal(PrimData.PathSkew);
- path["taper_x"] = OSD.FromReal(PrimData.PathTaperX);
- path["taper_y"] = OSD.FromReal(PrimData.PathTaperY);
- path["twist"] = OSD.FromReal(PrimData.PathTwist);
- path["twist_begin"] = OSD.FromReal(PrimData.PathTwistBegin);
-
- OSDMap profile = new OSDMap(4);
- profile["begin"] = OSD.FromReal(PrimData.ProfileBegin);
- profile["curve"] = OSD.FromInteger((int)PrimData.ProfileCurve);
- profile["hole"] = OSD.FromInteger((int)PrimData.ProfileHole);
- profile["end"] = OSD.FromReal(PrimData.ProfileEnd);
- profile["hollow"] = OSD.FromReal(PrimData.ProfileHollow);
-
- OSDMap volume = new OSDMap(2);
- volume["path"] = path;
- volume["profile"] = profile;
-
- OSDMap prim = new OSDMap(20);
- if (Properties != null)
- {
- prim["name"] = OSD.FromString(Properties.Name);
- prim["description"] = OSD.FromString(Properties.Description);
- }
- else
- {
- prim["name"] = OSD.FromString("Object");
- prim["description"] = OSD.FromString(String.Empty);
- }
-
- prim["phantom"] = OSD.FromBoolean(((Flags & PrimFlags.Phantom) != 0));
- prim["physical"] = OSD.FromBoolean(((Flags & PrimFlags.Physics) != 0));
- prim["position"] = OSD.FromVector3(Position);
- prim["rotation"] = OSD.FromQuaternion(Rotation);
- prim["scale"] = OSD.FromVector3(Scale);
- prim["pcode"] = OSD.FromInteger((int)PrimData.PCode);
- prim["material"] = OSD.FromInteger((int)PrimData.Material);
- prim["shadows"] = OSD.FromBoolean(((Flags & PrimFlags.CastShadows) != 0));
- prim["state"] = OSD.FromInteger(PrimData.State);
-
- prim["id"] = OSD.FromUUID(ID);
- prim["localid"] = OSD.FromUInteger(LocalID);
- prim["parentid"] = OSD.FromUInteger(ParentID);
-
- prim["volume"] = volume;
-
- if (Textures != null)
- prim["textures"] = Textures.GetOSD();
-
- if (Light != null)
- prim["light"] = Light.GetOSD();
-
- if (Flexible != null)
- prim["flex"] = Flexible.GetOSD();
-
- if (Sculpt != null)
- prim["sculpt"] = Sculpt.GetOSD();
-
- return prim;
- }
-
- public static Primitive FromOSD(OSD osd)
- {
- Primitive prim = new Primitive();
- Primitive.ConstructionData data;
-
- OSDMap map = (OSDMap)osd;
- OSDMap volume = (OSDMap)map["volume"];
- OSDMap path = (OSDMap)volume["path"];
- OSDMap profile = (OSDMap)volume["profile"];
-
- #region Path/Profile
-
- data.profileCurve = (byte)0;
- data.Material = (Material)map["material"].AsInteger();
- data.PCode = (PCode)map["pcode"].AsInteger();
- data.State = (byte)map["state"].AsInteger();
-
- data.PathBegin = (float)path["begin"].AsReal();
- data.PathCurve = (PathCurve)path["curve"].AsInteger();
- data.PathEnd = (float)path["end"].AsReal();
- data.PathRadiusOffset = (float)path["radius_offset"].AsReal();
- data.PathRevolutions = (float)path["revolutions"].AsReal();
- data.PathScaleX = (float)path["scale_x"].AsReal();
- data.PathScaleY = (float)path["scale_y"].AsReal();
- data.PathShearX = (float)path["shear_x"].AsReal();
- data.PathShearY = (float)path["shear_y"].AsReal();
- data.PathSkew = (float)path["skew"].AsReal();
- data.PathTaperX = (float)path["taper_x"].AsReal();
- data.PathTaperY = (float)path["taper_y"].AsReal();
- data.PathTwist = (float)path["twist"].AsReal();
- data.PathTwistBegin = (float)path["twist_begin"].AsReal();
-
- data.ProfileBegin = (float)profile["begin"].AsReal();
- data.ProfileEnd = (float)profile["end"].AsReal();
- data.ProfileHollow = (float)profile["hollow"].AsReal();
- data.ProfileCurve = (ProfileCurve)profile["curve"].AsInteger();
- data.ProfileHole = (HoleType)profile["hole"].AsInteger();
-
- #endregion Path/Profile
-
- prim.PrimData = data;
-
- if (map["phantom"].AsBoolean())
- prim.Flags |= PrimFlags.Phantom;
-
- if (map["physical"].AsBoolean())
- prim.Flags |= PrimFlags.Physics;
-
- if (map["shadows"].AsBoolean())
- prim.Flags |= PrimFlags.CastShadows;
-
- prim.ID = map["id"].AsUUID();
- prim.LocalID = map["localid"].AsUInteger();
- prim.ParentID = map["parentid"].AsUInteger();
- prim.Position = ((OSDArray)map["position"]).AsVector3();
- prim.Rotation = ((OSDArray)map["rotation"]).AsQuaternion();
- prim.Scale = ((OSDArray)map["scale"]).AsVector3();
-
- if (map["flex"])
- prim.Flexible = FlexibleData.FromOSD(map["flex"]);
-
- if (map["light"])
- prim.Light = LightData.FromOSD(map["light"]);
-
- if (map["sculpt"])
- prim.Sculpt = SculptData.FromOSD(map["sculpt"]);
-
- prim.Textures = TextureEntry.FromOSD(map["textures"]);
- prim.Properties = new ObjectProperties();
-
- if (!string.IsNullOrEmpty(map["name"].AsString()))
- {
- prim.Properties.Name = map["name"].AsString();
- }
-
- if (!string.IsNullOrEmpty(map["description"].AsString()))
- {
- prim.Properties.Description = map["description"].AsString();
- }
-
- return prim;
- }
-
- public int SetExtraParamsFromBytes(byte[] data, int pos)
- {
- int i = pos;
- int totalLength = 1;
-
- if (data.Length == 0 || pos >= data.Length)
- return 0;
-
- byte extraParamCount = data[i++];
-
- for (int k = 0; k < extraParamCount; k++)
- {
- ExtraParamType type = (ExtraParamType)Utils.BytesToUInt16(data, i);
- i += 2;
-
- uint paramLength = Utils.BytesToUInt(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;
- }
-
- return totalLength;
- }
-
- public byte[] GetExtraParamsBytes()
- {
- byte[] flexible = null;
- byte[] light = null;
- byte[] sculpt = null;
- byte[] buffer = null;
- int size = 1;
- int pos = 0;
- byte count = 0;
-
- if (Flexible != null)
- {
- flexible = Flexible.GetBytes();
- size += flexible.Length + 6;
- ++count;
- }
- if (Light != null)
- {
- light = Light.GetBytes();
- size += light.Length + 6;
- ++count;
- }
- if (Sculpt != null)
- {
- sculpt = Sculpt.GetBytes();
- size += sculpt.Length + 6;
- ++count;
- }
-
- buffer = new byte[size];
- buffer[0] = count;
- ++pos;
-
- if (flexible != null)
- {
- Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Flexible), 0, buffer, pos, 2);
- pos += 2;
-
- Buffer.BlockCopy(Utils.UIntToBytes((uint)flexible.Length), 0, buffer, pos, 4);
- pos += 4;
-
- Buffer.BlockCopy(flexible, 0, buffer, pos, flexible.Length);
- pos += flexible.Length;
- }
- if (light != null)
- {
- Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Light), 0, buffer, pos, 2);
- pos += 2;
-
- Buffer.BlockCopy(Utils.UIntToBytes((uint)light.Length), 0, buffer, pos, 4);
- pos += 4;
-
- Buffer.BlockCopy(light, 0, buffer, pos, light.Length);
- pos += light.Length;
- }
- if (sculpt != null)
- {
- Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Sculpt), 0, buffer, pos, 2);
- pos += 2;
-
- Buffer.BlockCopy(Utils.UIntToBytes((uint)sculpt.Length), 0, buffer, pos, 4);
- pos += 4;
-
- Buffer.BlockCopy(sculpt, 0, buffer, pos, sculpt.Length);
- pos += sculpt.Length;
- }
-
- return buffer;
- }
-
- #endregion Public Methods
-
- #region Overrides
-
- public override bool Equals(object obj)
- {
- return (obj is Primitive) ? this == (Primitive)obj : false;
- }
-
- public bool Equals(Primitive other)
- {
- return this == other;
- }
-
- public override string ToString()
- {
- switch (PrimData.PCode)
- {
- case PCode.Prim:
- return String.Format("{0} ({1})", Type, ID);
- default:
- return String.Format("{0} ({1})", PrimData.PCode, ID);
- }
- }
-
- public override int GetHashCode()
- {
- return
- Position.GetHashCode() ^
- Velocity.GetHashCode() ^
- Acceleration.GetHashCode() ^
- Rotation.GetHashCode() ^
- AngularVelocity.GetHashCode() ^
- ClickAction.GetHashCode() ^
- (Flexible != null ? Flexible.GetHashCode() : 0) ^
- (Light != null ? Light.GetHashCode() : 0) ^
- (Sculpt != null ? Sculpt.GetHashCode() : 0) ^
- Flags.GetHashCode() ^
- PrimData.Material.GetHashCode() ^
- MediaURL.GetHashCode() ^
- //TODO: NameValues?
- (Properties != null ? Properties.OwnerID.GetHashCode() : 0) ^
- ParentID.GetHashCode() ^
- PrimData.PathBegin.GetHashCode() ^
- PrimData.PathCurve.GetHashCode() ^
- PrimData.PathEnd.GetHashCode() ^
- PrimData.PathRadiusOffset.GetHashCode() ^
- PrimData.PathRevolutions.GetHashCode() ^
- PrimData.PathScaleX.GetHashCode() ^
- PrimData.PathScaleY.GetHashCode() ^
- PrimData.PathShearX.GetHashCode() ^
- PrimData.PathShearY.GetHashCode() ^
- PrimData.PathSkew.GetHashCode() ^
- PrimData.PathTaperX.GetHashCode() ^
- PrimData.PathTaperY.GetHashCode() ^
- PrimData.PathTwist.GetHashCode() ^
- PrimData.PathTwistBegin.GetHashCode() ^
- PrimData.PCode.GetHashCode() ^
- PrimData.ProfileBegin.GetHashCode() ^
- PrimData.ProfileCurve.GetHashCode() ^
- PrimData.ProfileEnd.GetHashCode() ^
- PrimData.ProfileHollow.GetHashCode() ^
- ParticleSys.GetHashCode() ^
- TextColor.GetHashCode() ^
- TextureAnim.GetHashCode() ^
- (Textures != null ? Textures.GetHashCode() : 0) ^
- SoundRadius.GetHashCode() ^
- Scale.GetHashCode() ^
- Sound.GetHashCode() ^
- PrimData.State.GetHashCode() ^
- Text.GetHashCode() ^
- TreeSpecies.GetHashCode();
- }
-
- #endregion Overrides
-
- #region Operators
-
- public static bool operator ==(Primitive lhs, Primitive rhs)
- {
- if ((Object)lhs == null || (Object)rhs == null)
- {
- return (Object)rhs == (Object)lhs;
- }
- return (lhs.ID == rhs.ID);
- }
-
- public static bool operator !=(Primitive lhs, Primitive rhs)
- {
- if ((Object)lhs == null || (Object)rhs == null)
- {
- return (Object)rhs != (Object)lhs;
- }
- return !(lhs.ID == rhs.ID);
- }
-
- #endregion Operators
-
- #region Parameter Packing Methods
-
- public static ushort PackBeginCut(float beginCut)
- {
- return (ushort)Math.Round(beginCut / CUT_QUANTA);
- }
-
- public static ushort PackEndCut(float endCut)
- {
- return (ushort)(50000 - (ushort)Math.Round(endCut / CUT_QUANTA));
- }
-
- public static byte PackPathScale(float pathScale)
- {
- return (byte)(200 - (byte)Math.Round(pathScale / SCALE_QUANTA));
- }
-
- public static sbyte PackPathShear(float pathShear)
- {
- return (sbyte)Math.Round(pathShear / SHEAR_QUANTA);
- }
-
- ///
- /// Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew
- /// parameters in to signed eight bit values
- ///
- /// Floating point parameter to pack
- /// Signed eight bit value containing the packed parameter
- public static sbyte PackPathTwist(float pathTwist)
- {
- return (sbyte)Math.Round(pathTwist / SCALE_QUANTA);
- }
-
- public static sbyte PackPathTaper(float pathTaper)
- {
- return (sbyte)Math.Round(pathTaper / TAPER_QUANTA);
- }
-
- public static byte PackPathRevolutions(float pathRevolutions)
- {
- return (byte)Math.Round((pathRevolutions - 1f) / REV_QUANTA);
- }
-
- public static ushort PackProfileHollow(float profileHollow)
- {
- return (ushort)Math.Round(profileHollow / HOLLOW_QUANTA);
- }
-
- #endregion Parameter Packing Methods
-
- #region Parameter Unpacking Methods
-
- public static float UnpackBeginCut(ushort beginCut)
- {
- return (float)beginCut * CUT_QUANTA;
- }
-
- public static float UnpackEndCut(ushort endCut)
- {
- return (float)(50000 - endCut) * CUT_QUANTA;
- }
-
- public static float UnpackPathScale(byte pathScale)
- {
- return (float)(200 - pathScale) * SCALE_QUANTA;
- }
-
- public static float UnpackPathShear(sbyte pathShear)
- {
- return (float)pathShear * SHEAR_QUANTA;
- }
-
- ///
- /// Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew
- /// parameters from signed eight bit integers to floating point values
- ///
- /// Signed eight bit value to unpack
- /// Unpacked floating point value
- public static float UnpackPathTwist(sbyte pathTwist)
- {
- return (float)pathTwist * SCALE_QUANTA;
- }
-
- public static float UnpackPathTaper(sbyte pathTaper)
- {
- return (float)pathTaper * TAPER_QUANTA;
- }
-
- public static float UnpackPathRevolutions(byte pathRevolutions)
- {
- return (float)pathRevolutions * REV_QUANTA + 1f;
- }
-
- public static float UnpackProfileHollow(ushort profileHollow)
- {
- return (float)profileHollow * HOLLOW_QUANTA;
- }
-
- #endregion Parameter Unpacking Methods
- }
-}
+/*
+ * Copyright (c) 2006-2008, openmetaverse.org
+ * 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 openmetaverse.org 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;
+using OpenMetaverse.StructuredData;
+
+namespace OpenMetaverse
+{
+ public partial class Primitive : IEquatable
+ {
+ // Used for packing and unpacking parameters
+ protected const float CUT_QUANTA = 0.00002f;
+ protected const float SCALE_QUANTA = 0.01f;
+ protected const float SHEAR_QUANTA = 0.01f;
+ protected const float TAPER_QUANTA = 0.01f;
+ protected const float REV_QUANTA = 0.015f;
+ protected const float HOLLOW_QUANTA = 0.00002f;
+
+ #region Subclasses
+
+ ///
+ /// Parameters used to construct a visual representation of a primitive
+ ///
+ public struct ConstructionData
+ {
+ private const byte PROFILE_MASK = 0x0F;
+ private const byte HOLE_MASK = 0xF0;
+
+ ///
+ public byte profileCurve;
+ ///
+ public PathCurve PathCurve;
+ ///
+ public float PathEnd;
+ ///
+ public float PathRadiusOffset;
+ ///
+ public float PathSkew;
+ ///
+ public float PathScaleX;
+ ///
+ public float PathScaleY;
+ ///
+ public float PathShearX;
+ ///
+ public float PathShearY;
+ ///
+ public float PathTaperX;
+ ///
+ public float PathTaperY;
+ ///
+ public float PathBegin;
+ ///
+ public float PathTwist;
+ ///
+ public float PathTwistBegin;
+ ///
+ public float PathRevolutions;
+ ///
+ public float ProfileBegin;
+ ///
+ public float ProfileEnd;
+ ///
+ public float ProfileHollow;
+
+ ///
+ public Material Material;
+ ///
+ public byte State;
+ ///
+ public PCode PCode;
+
+ #region Properties
+
+ /// Attachment point to an avatar
+ public AttachmentPoint AttachmentPoint
+ {
+ get { return (AttachmentPoint)Utils.SwapWords(State); }
+ set { State = (byte)Utils.SwapWords((byte)value); }
+ }
+
+ ///
+ public ProfileCurve ProfileCurve
+ {
+ get { return (ProfileCurve)(profileCurve & PROFILE_MASK); }
+ set
+ {
+ profileCurve &= HOLE_MASK;
+ profileCurve |= (byte)value;
+ }
+ }
+
+ ///
+ public HoleType ProfileHole
+ {
+ get { return (HoleType)(profileCurve & HOLE_MASK); }
+ set
+ {
+ profileCurve &= PROFILE_MASK;
+ profileCurve |= (byte)value;
+ }
+ }
+
+ ///
+ public Vector2 PathBeginScale
+ {
+ get
+ {
+ Vector2 begin = new Vector2(1f, 1f);
+ if (PathScaleX > 1f)
+ begin.X = 2f - PathScaleX;
+ if (PathScaleY > 1f)
+ begin.Y = 2f - PathScaleY;
+ return begin;
+ }
+ }
+
+ ///
+ public Vector2 PathEndScale
+ {
+ get
+ {
+ Vector2 end = new Vector2(1f, 1f);
+ if (PathScaleX < 1f)
+ end.X = PathScaleX;
+ if (PathScaleY < 1f)
+ end.Y = PathScaleY;
+ return end;
+ }
+ }
+
+ #endregion Properties
+ }
+
+ ///
+ /// Information on the flexible properties of a primitive
+ ///
+ public class FlexibleData
+ {
+ ///
+ public int Softness;
+ ///
+ public float Gravity;
+ ///
+ public float Drag;
+ ///
+ public float Wind;
+ ///
+ public float Tension;
+ ///
+ public Vector3 Force;
+
+ ///
+ /// Default constructor
+ ///
+ public FlexibleData()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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 Vector3(data, pos);
+ }
+ else
+ {
+ Softness = 0;
+
+ Tension = 0.0f;
+ Drag = 0.0f;
+ Gravity = 0.0f;
+ Wind = 0.0f;
+ Force = Vector3.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;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public OSD GetOSD()
+ {
+ OSDMap map = new OSDMap();
+
+ map["simulate_lod"] = OSD.FromInteger(Softness);
+ map["gravity"] = OSD.FromReal(Gravity);
+ map["air_friction"] = OSD.FromReal(Drag);
+ map["wind_sensitivity"] = OSD.FromReal(Wind);
+ map["tension"] = OSD.FromReal(Tension);
+ map["user_force"] = OSD.FromVector3(Force);
+
+ return map;
+ }
+
+ public static FlexibleData FromOSD(OSD osd)
+ {
+ FlexibleData flex = new FlexibleData();
+
+ if (osd.Type == OSDType.Map)
+ {
+ OSDMap map = (OSDMap)osd;
+
+ flex.Softness = map["simulate_lod"].AsInteger();
+ flex.Gravity = (float)map["gravity"].AsReal();
+ flex.Drag = (float)map["air_friction"].AsReal();
+ flex.Wind = (float)map["wind_sensitivity"].AsReal();
+ flex.Tension = (float)map["tension"].AsReal();
+ flex.Force = ((OSDArray)map["user_force"]).AsVector3();
+ }
+
+ return flex;
+ }
+
+ public override int GetHashCode()
+ {
+ return
+ Softness.GetHashCode() ^
+ Gravity.GetHashCode() ^
+ Drag.GetHashCode() ^
+ Wind.GetHashCode() ^
+ Tension.GetHashCode() ^
+ Force.GetHashCode();
+ }
+ }
+
+ ///
+ /// Information on the light properties of a primitive
+ ///
+ public class LightData
+ {
+ ///
+ public Color4 Color;
+ ///
+ public float Intensity;
+ ///
+ public float Radius;
+ ///
+ public float Cutoff;
+ ///
+ public float Falloff;
+
+ ///
+ /// Default constructor
+ ///
+ public LightData()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public LightData(byte[] data, int pos)
+ {
+ if (data.Length - pos >= 16)
+ {
+ Color = new Color4(data, pos, false);
+ Radius = Utils.BytesToFloat(data, pos + 4);
+ Cutoff = Utils.BytesToFloat(data, pos + 8);
+ Falloff = Utils.BytesToFloat(data, pos + 12);
+
+ // Alpha in color is actually intensity
+ Intensity = Color.A;
+ Color.A = 1f;
+ }
+ else
+ {
+ Color = Color4.Black;
+ Radius = 0f;
+ Cutoff = 0f;
+ Falloff = 0f;
+ Intensity = 0f;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public byte[] GetBytes()
+ {
+ byte[] data = new byte[16];
+
+ // Alpha channel in color is intensity
+ Color4 tmpColor = Color;
+ tmpColor.A = Intensity;
+ tmpColor.GetBytes().CopyTo(data, 0);
+ Utils.FloatToBytes(Radius).CopyTo(data, 4);
+ Utils.FloatToBytes(Cutoff).CopyTo(data, 8);
+ Utils.FloatToBytes(Falloff).CopyTo(data, 12);
+
+ return data;
+ }
+
+ public OSD GetOSD()
+ {
+ OSDMap map = new OSDMap();
+
+ map["color"] = OSD.FromColor4(Color);
+ map["intensity"] = OSD.FromReal(Intensity);
+ map["radius"] = OSD.FromReal(Radius);
+ map["cutoff"] = OSD.FromReal(Cutoff);
+ map["falloff"] = OSD.FromReal(Falloff);
+
+ return map;
+ }
+
+ public static LightData FromOSD(OSD osd)
+ {
+ LightData light = new LightData();
+
+ if (osd.Type == OSDType.Map)
+ {
+ OSDMap map = (OSDMap)osd;
+
+ light.Color = ((OSDArray)map["color"]).AsColor4();
+ light.Intensity = (float)map["intensity"].AsReal();
+ light.Radius = (float)map["radius"].AsReal();
+ light.Cutoff = (float)map["cutoff"].AsReal();
+ light.Falloff = (float)map["falloff"].AsReal();
+ }
+
+ return light;
+ }
+
+ public override int GetHashCode()
+ {
+ return
+ Color.GetHashCode() ^
+ Intensity.GetHashCode() ^
+ Radius.GetHashCode() ^
+ Cutoff.GetHashCode() ^
+ Falloff.GetHashCode();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public override string ToString()
+ {
+ return String.Format("Color: {0} Intensity: {1} Radius: {2} Cutoff: {3} Falloff: {4}",
+ Color, Intensity, Radius, Cutoff, Falloff);
+ }
+ }
+
+ ///
+ /// Information on the sculpt properties of a sculpted primitive
+ ///
+ public class SculptData
+ {
+ public UUID SculptTexture;
+ private byte type;
+
+ public SculptType Type
+ {
+ get { return (SculptType)(type & 7); }
+ set { type = (byte)value; }
+ }
+
+ ///
+ /// Render inside out (inverts the normals).
+ ///
+ public bool Invert
+ {
+ get { return ((type & (byte)SculptType.Invert) != 0); }
+ }
+
+ ///
+ /// Render an X axis mirror of the sculpty.
+ ///
+ public bool Mirror
+ {
+ get { return ((type & (byte)SculptType.Mirror) != 0); }
+ }
+
+ ///
+ /// Default constructor
+ ///
+ public SculptData()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public SculptData(byte[] data, int pos)
+ {
+ if (data.Length >= 17)
+ {
+ SculptTexture = new UUID(data, pos);
+ type = data[pos + 16];
+ }
+ else
+ {
+ SculptTexture = UUID.Zero;
+ type = (byte)SculptType.None;
+ }
+ }
+
+ public byte[] GetBytes()
+ {
+ byte[] data = new byte[17];
+
+ SculptTexture.GetBytes().CopyTo(data, 0);
+ data[16] = type;
+
+ return data;
+ }
+
+ public OSD GetOSD()
+ {
+ OSDMap map = new OSDMap();
+
+ map["texture"] = OSD.FromUUID(SculptTexture);
+ map["type"] = OSD.FromInteger(type);
+
+ return map;
+ }
+
+ public static SculptData FromOSD(OSD osd)
+ {
+ SculptData sculpt = new SculptData();
+
+ if (osd.Type == OSDType.Map)
+ {
+ OSDMap map = (OSDMap)osd;
+
+ sculpt.SculptTexture = map["texture"].AsUUID();
+ sculpt.type = (byte)map["type"].AsInteger();
+ }
+
+ return sculpt;
+ }
+
+ public override int GetHashCode()
+ {
+ return SculptTexture.GetHashCode() ^ type.GetHashCode();
+ }
+ }
+
+ ///
+ /// Extended properties to describe an object
+ ///
+ public class ObjectProperties
+ {
+ ///
+ public UUID ObjectID;
+ ///
+ public UUID CreatorID;
+ ///
+ public UUID OwnerID;
+ ///
+ public UUID GroupID;
+ ///
+ public DateTime CreationDate;
+ ///
+ public Permissions Permissions;
+ ///
+ public int OwnershipCost;
+ ///
+ public SaleType SaleType;
+ ///
+ public int SalePrice;
+ ///
+ public byte AggregatePerms;
+ ///
+ public byte AggregatePermTextures;
+ ///
+ public byte AggregatePermTexturesOwner;
+ ///
+ public ObjectCategory Category;
+ ///
+ public short InventorySerial;
+ ///
+ public UUID ItemID;
+ ///
+ public UUID FolderID;
+ ///
+ public UUID FromTaskID;
+ ///
+ public UUID LastOwnerID;
+ ///
+ public string Name;
+ ///
+ public string Description;
+ ///
+ public string TouchName;
+ ///
+ public string SitName;
+ ///
+ public UUID[] TextureIDs;
+
+ ///
+ /// Default constructor
+ ///
+ public ObjectProperties()
+ {
+ Name = String.Empty;
+ Description = String.Empty;
+ TouchName = String.Empty;
+ SitName = String.Empty;
+ }
+
+ ///
+ /// Set the properties that are set in an ObjectPropertiesFamily packet
+ ///
+ /// that has
+ /// been partially filled by an ObjectPropertiesFamily packet
+ public void SetFamilyProperties(ObjectProperties props)
+ {
+ ObjectID = props.ObjectID;
+ OwnerID = props.OwnerID;
+ GroupID = props.GroupID;
+ Permissions = props.Permissions;
+ OwnershipCost = props.OwnershipCost;
+ SaleType = props.SaleType;
+ SalePrice = props.SalePrice;
+ Category = props.Category;
+ LastOwnerID = props.LastOwnerID;
+ Name = props.Name;
+ Description = props.Description;
+ }
+
+ public byte[] GetTextureIDBytes()
+ {
+ if (TextureIDs == null || TextureIDs.Length == 0)
+ return Utils.EmptyBytes;
+
+ byte[] bytes = new byte[16 * TextureIDs.Length];
+ for (int i = 0; i < TextureIDs.Length; i++)
+ TextureIDs[i].ToBytes(bytes, 16 * i);
+
+ return bytes;
+ }
+ }
+
+ ///
+ /// Describes physics attributes of the prim
+ ///
+ public class PhysicsProperties
+ {
+ /// Primitive's local ID
+ public uint LocalID;
+ /// Density (1000 for normal density)
+ public float Density;
+ /// Friction
+ public float Friction;
+ /// Gravity multiplier (1 for normal gravity)
+ public float GravityMultiplier;
+ /// Type of physics representation of this primitive in the simulator
+ public PhysicsShapeType PhysicsShapeType;
+ /// Restitution
+ public float Restitution;
+
+ ///
+ /// Creates PhysicsProperties from OSD
+ ///
+ /// OSDMap with incoming data
+ /// Deserialized PhysicsProperties object
+ public static PhysicsProperties FromOSD(OSD osd)
+ {
+ PhysicsProperties ret = new PhysicsProperties();
+
+ if (osd is OSDMap)
+ {
+ OSDMap map = (OSDMap)osd;
+ ret.LocalID = map["LocalID"];
+ ret.Density = map["Density"];
+ ret.Friction = map["Friction"];
+ ret.GravityMultiplier = map["GravityMultiplier"];
+ ret.Restitution = map["Restitution"];
+ ret.PhysicsShapeType = (PhysicsShapeType)map["PhysicsShapeType"].AsInteger();
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Serializes PhysicsProperties to OSD
+ ///
+ /// OSDMap with serialized PhysicsProperties data
+ public OSD GetOSD()
+ {
+ OSDMap map = new OSDMap(6);
+ map["LocalID"] = LocalID;
+ map["Density"] = Density;
+ map["Friction"] = Friction;
+ map["GravityMultiplier"] = GravityMultiplier;
+ map["Restitution"] = Restitution;
+ map["PhysicsShapeType"] = (int)PhysicsShapeType;
+ return map;
+ }
+ }
+
+ #endregion Subclasses
+
+ #region Public Members
+
+ ///
+ public UUID ID;
+ ///
+ public UUID GroupID;
+ ///
+ public uint LocalID;
+ ///
+ public uint ParentID;
+ ///
+ public ulong RegionHandle;
+ ///
+ public PrimFlags Flags;
+ /// Foliage type for this primitive. Only applicable if this
+ /// primitive is foliage
+ public Tree TreeSpecies;
+ /// Unknown
+ public byte[] ScratchPad;
+ ///
+ public Vector3 Position;
+ ///
+ public Vector3 Scale;
+ ///
+ public Quaternion Rotation = Quaternion.Identity;
+ ///
+ public Vector3 Velocity;
+ ///
+ public Vector3 AngularVelocity;
+ ///
+ public Vector3 Acceleration;
+ ///
+ public Vector4 CollisionPlane;
+ ///
+ public FlexibleData Flexible;
+ ///
+ public LightData Light;
+ ///
+ public SculptData Sculpt;
+ ///
+ public ClickAction ClickAction;
+ ///
+ public UUID Sound;
+ /// Identifies the owner if audio or a particle system is
+ /// active
+ public UUID OwnerID;
+ ///
+ public SoundFlags SoundFlags;
+ ///
+ public float SoundGain;
+ ///
+ public float SoundRadius;
+ ///
+ public string Text;
+ ///
+ public Color4 TextColor;
+ ///
+ public string MediaURL;
+ ///
+ public JointType Joint;
+ ///
+ public Vector3 JointPivot;
+ ///
+ public Vector3 JointAxisOrAnchor;
+ ///
+ public NameValue[] NameValues;
+ ///
+ public ConstructionData PrimData;
+ ///
+ public ObjectProperties Properties;
+ /// Objects physics engine propertis
+ public PhysicsProperties PhysicsProps;
+
+ #endregion Public Members
+
+ #region Properties
+
+ /// Uses basic heuristics to estimate the primitive shape
+ public PrimType Type
+ {
+ get
+ {
+ if (Sculpt != null && Sculpt.Type != SculptType.None)
+ return PrimType.Sculpt;
+
+ bool linearPath = (PrimData.PathCurve == PathCurve.Line || PrimData.PathCurve == PathCurve.Flexible);
+ float scaleY = PrimData.PathScaleY;
+
+ if (linearPath)
+ {
+ switch (PrimData.ProfileCurve)
+ {
+ case ProfileCurve.Circle:
+ return PrimType.Cylinder;
+ case ProfileCurve.Square:
+ return PrimType.Box;
+ case ProfileCurve.IsoTriangle:
+ case ProfileCurve.EqualTriangle:
+ case ProfileCurve.RightTriangle:
+ return PrimType.Prism;
+ case ProfileCurve.HalfCircle:
+ default:
+ return PrimType.Unknown;
+ }
+ }
+ else
+ {
+ switch (PrimData.PathCurve)
+ {
+ case PathCurve.Flexible:
+ return PrimType.Unknown;
+ case PathCurve.Circle:
+ switch (PrimData.ProfileCurve)
+ {
+ case ProfileCurve.Circle:
+ if (scaleY > 0.75f)
+ return PrimType.Sphere;
+ else
+ return PrimType.Torus;
+ case ProfileCurve.HalfCircle:
+ return PrimType.Sphere;
+ case ProfileCurve.EqualTriangle:
+ return PrimType.Ring;
+ case ProfileCurve.Square:
+ if (scaleY <= 0.75f)
+ return PrimType.Tube;
+ else
+ return PrimType.Unknown;
+ default:
+ return PrimType.Unknown;
+ }
+ case PathCurve.Circle2:
+ if (PrimData.ProfileCurve == ProfileCurve.Circle)
+ return PrimType.Sphere;
+ else
+ return PrimType.Unknown;
+ default:
+ return PrimType.Unknown;
+ }
+ }
+ }
+ }
+
+ #endregion Properties
+
+ #region Constructors
+
+ ///
+ /// Default constructor
+ ///
+ public Primitive()
+ {
+ // Default a few null property values to String.Empty
+ Text = String.Empty;
+ MediaURL = String.Empty;
+ }
+
+ public Primitive(Primitive prim)
+ {
+ ID = prim.ID;
+ GroupID = prim.GroupID;
+ LocalID = prim.LocalID;
+ ParentID = prim.ParentID;
+ RegionHandle = prim.RegionHandle;
+ Flags = prim.Flags;
+ TreeSpecies = prim.TreeSpecies;
+ if (prim.ScratchPad != null)
+ {
+ ScratchPad = new byte[prim.ScratchPad.Length];
+ Buffer.BlockCopy(prim.ScratchPad, 0, ScratchPad, 0, ScratchPad.Length);
+ }
+ else
+ ScratchPad = Utils.EmptyBytes;
+ Position = prim.Position;
+ Scale = prim.Scale;
+ Rotation = prim.Rotation;
+ Velocity = prim.Velocity;
+ AngularVelocity = prim.AngularVelocity;
+ Acceleration = prim.Acceleration;
+ CollisionPlane = prim.CollisionPlane;
+ Flexible = prim.Flexible;
+ Light = prim.Light;
+ Sculpt = prim.Sculpt;
+ ClickAction = prim.ClickAction;
+ Sound = prim.Sound;
+ OwnerID = prim.OwnerID;
+ SoundFlags = prim.SoundFlags;
+ SoundGain = prim.SoundGain;
+ SoundRadius = prim.SoundRadius;
+ Text = prim.Text;
+ TextColor = prim.TextColor;
+ MediaURL = prim.MediaURL;
+ Joint = prim.Joint;
+ JointPivot = prim.JointPivot;
+ JointAxisOrAnchor = prim.JointAxisOrAnchor;
+ if (prim.NameValues != null)
+ {
+ if (NameValues == null || NameValues.Length != prim.NameValues.Length)
+ NameValues = new NameValue[prim.NameValues.Length];
+ Array.Copy(prim.NameValues, NameValues, prim.NameValues.Length);
+ }
+ else
+ NameValues = null;
+ PrimData = prim.PrimData;
+ Properties = prim.Properties;
+ // FIXME: Get a real copy constructor for TextureEntry instead of serializing to bytes and back
+ if (prim.Textures != null)
+ {
+ byte[] textureBytes = prim.Textures.GetBytes();
+ Textures = new TextureEntry(textureBytes, 0, textureBytes.Length);
+ }
+ else
+ {
+ Textures = null;
+ }
+ TextureAnim = prim.TextureAnim;
+ ParticleSys = prim.ParticleSys;
+ }
+
+ #endregion Constructors
+
+ #region Public Methods
+
+ public virtual OSD GetOSD()
+ {
+ OSDMap path = new OSDMap(14);
+ path["begin"] = OSD.FromReal(PrimData.PathBegin);
+ path["curve"] = OSD.FromInteger((int)PrimData.PathCurve);
+ path["end"] = OSD.FromReal(PrimData.PathEnd);
+ path["radius_offset"] = OSD.FromReal(PrimData.PathRadiusOffset);
+ path["revolutions"] = OSD.FromReal(PrimData.PathRevolutions);
+ path["scale_x"] = OSD.FromReal(PrimData.PathScaleX);
+ path["scale_y"] = OSD.FromReal(PrimData.PathScaleY);
+ path["shear_x"] = OSD.FromReal(PrimData.PathShearX);
+ path["shear_y"] = OSD.FromReal(PrimData.PathShearY);
+ path["skew"] = OSD.FromReal(PrimData.PathSkew);
+ path["taper_x"] = OSD.FromReal(PrimData.PathTaperX);
+ path["taper_y"] = OSD.FromReal(PrimData.PathTaperY);
+ path["twist"] = OSD.FromReal(PrimData.PathTwist);
+ path["twist_begin"] = OSD.FromReal(PrimData.PathTwistBegin);
+
+ OSDMap profile = new OSDMap(4);
+ profile["begin"] = OSD.FromReal(PrimData.ProfileBegin);
+ profile["curve"] = OSD.FromInteger((int)PrimData.ProfileCurve);
+ profile["hole"] = OSD.FromInteger((int)PrimData.ProfileHole);
+ profile["end"] = OSD.FromReal(PrimData.ProfileEnd);
+ profile["hollow"] = OSD.FromReal(PrimData.ProfileHollow);
+
+ OSDMap volume = new OSDMap(2);
+ volume["path"] = path;
+ volume["profile"] = profile;
+
+ OSDMap prim = new OSDMap(20);
+ if (Properties != null)
+ {
+ prim["name"] = OSD.FromString(Properties.Name);
+ prim["description"] = OSD.FromString(Properties.Description);
+ }
+ else
+ {
+ prim["name"] = OSD.FromString("Object");
+ prim["description"] = OSD.FromString(String.Empty);
+ }
+
+ prim["phantom"] = OSD.FromBoolean(((Flags & PrimFlags.Phantom) != 0));
+ prim["physical"] = OSD.FromBoolean(((Flags & PrimFlags.Physics) != 0));
+ prim["position"] = OSD.FromVector3(Position);
+ prim["rotation"] = OSD.FromQuaternion(Rotation);
+ prim["scale"] = OSD.FromVector3(Scale);
+ prim["pcode"] = OSD.FromInteger((int)PrimData.PCode);
+ prim["material"] = OSD.FromInteger((int)PrimData.Material);
+ prim["shadows"] = OSD.FromBoolean(((Flags & PrimFlags.CastShadows) != 0));
+ prim["state"] = OSD.FromInteger(PrimData.State);
+
+ prim["id"] = OSD.FromUUID(ID);
+ prim["localid"] = OSD.FromUInteger(LocalID);
+ prim["parentid"] = OSD.FromUInteger(ParentID);
+
+ prim["volume"] = volume;
+
+ if (Textures != null)
+ prim["textures"] = Textures.GetOSD();
+
+ if (Light != null)
+ prim["light"] = Light.GetOSD();
+
+ if (Flexible != null)
+ prim["flex"] = Flexible.GetOSD();
+
+ if (Sculpt != null)
+ prim["sculpt"] = Sculpt.GetOSD();
+
+ return prim;
+ }
+
+ public static Primitive FromOSD(OSD osd)
+ {
+ Primitive prim = new Primitive();
+ Primitive.ConstructionData data;
+
+ OSDMap map = (OSDMap)osd;
+ OSDMap volume = (OSDMap)map["volume"];
+ OSDMap path = (OSDMap)volume["path"];
+ OSDMap profile = (OSDMap)volume["profile"];
+
+ #region Path/Profile
+
+ data.profileCurve = (byte)0;
+ data.Material = (Material)map["material"].AsInteger();
+ data.PCode = (PCode)map["pcode"].AsInteger();
+ data.State = (byte)map["state"].AsInteger();
+
+ data.PathBegin = (float)path["begin"].AsReal();
+ data.PathCurve = (PathCurve)path["curve"].AsInteger();
+ data.PathEnd = (float)path["end"].AsReal();
+ data.PathRadiusOffset = (float)path["radius_offset"].AsReal();
+ data.PathRevolutions = (float)path["revolutions"].AsReal();
+ data.PathScaleX = (float)path["scale_x"].AsReal();
+ data.PathScaleY = (float)path["scale_y"].AsReal();
+ data.PathShearX = (float)path["shear_x"].AsReal();
+ data.PathShearY = (float)path["shear_y"].AsReal();
+ data.PathSkew = (float)path["skew"].AsReal();
+ data.PathTaperX = (float)path["taper_x"].AsReal();
+ data.PathTaperY = (float)path["taper_y"].AsReal();
+ data.PathTwist = (float)path["twist"].AsReal();
+ data.PathTwistBegin = (float)path["twist_begin"].AsReal();
+
+ data.ProfileBegin = (float)profile["begin"].AsReal();
+ data.ProfileEnd = (float)profile["end"].AsReal();
+ data.ProfileHollow = (float)profile["hollow"].AsReal();
+ data.ProfileCurve = (ProfileCurve)profile["curve"].AsInteger();
+ data.ProfileHole = (HoleType)profile["hole"].AsInteger();
+
+ #endregion Path/Profile
+
+ prim.PrimData = data;
+
+ if (map["phantom"].AsBoolean())
+ prim.Flags |= PrimFlags.Phantom;
+
+ if (map["physical"].AsBoolean())
+ prim.Flags |= PrimFlags.Physics;
+
+ if (map["shadows"].AsBoolean())
+ prim.Flags |= PrimFlags.CastShadows;
+
+ prim.ID = map["id"].AsUUID();
+ prim.LocalID = map["localid"].AsUInteger();
+ prim.ParentID = map["parentid"].AsUInteger();
+ prim.Position = ((OSDArray)map["position"]).AsVector3();
+ prim.Rotation = ((OSDArray)map["rotation"]).AsQuaternion();
+ prim.Scale = ((OSDArray)map["scale"]).AsVector3();
+
+ if (map["flex"])
+ prim.Flexible = FlexibleData.FromOSD(map["flex"]);
+
+ if (map["light"])
+ prim.Light = LightData.FromOSD(map["light"]);
+
+ if (map["sculpt"])
+ prim.Sculpt = SculptData.FromOSD(map["sculpt"]);
+
+ prim.Textures = TextureEntry.FromOSD(map["textures"]);
+ prim.Properties = new ObjectProperties();
+
+ if (!string.IsNullOrEmpty(map["name"].AsString()))
+ {
+ prim.Properties.Name = map["name"].AsString();
+ }
+
+ if (!string.IsNullOrEmpty(map["description"].AsString()))
+ {
+ prim.Properties.Description = map["description"].AsString();
+ }
+
+ return prim;
+ }
+
+ public int SetExtraParamsFromBytes(byte[] data, int pos)
+ {
+ int i = pos;
+ int totalLength = 1;
+
+ if (data.Length == 0 || pos >= data.Length)
+ return 0;
+
+ byte extraParamCount = data[i++];
+
+ for (int k = 0; k < extraParamCount; k++)
+ {
+ ExtraParamType type = (ExtraParamType)Utils.BytesToUInt16(data, i);
+ i += 2;
+
+ uint paramLength = Utils.BytesToUInt(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;
+ }
+
+ return totalLength;
+ }
+
+ public byte[] GetExtraParamsBytes()
+ {
+ byte[] flexible = null;
+ byte[] light = null;
+ byte[] sculpt = null;
+ byte[] buffer = null;
+ int size = 1;
+ int pos = 0;
+ byte count = 0;
+
+ if (Flexible != null)
+ {
+ flexible = Flexible.GetBytes();
+ size += flexible.Length + 6;
+ ++count;
+ }
+ if (Light != null)
+ {
+ light = Light.GetBytes();
+ size += light.Length + 6;
+ ++count;
+ }
+ if (Sculpt != null)
+ {
+ sculpt = Sculpt.GetBytes();
+ size += sculpt.Length + 6;
+ ++count;
+ }
+
+ buffer = new byte[size];
+ buffer[0] = count;
+ ++pos;
+
+ if (flexible != null)
+ {
+ Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Flexible), 0, buffer, pos, 2);
+ pos += 2;
+
+ Buffer.BlockCopy(Utils.UIntToBytes((uint)flexible.Length), 0, buffer, pos, 4);
+ pos += 4;
+
+ Buffer.BlockCopy(flexible, 0, buffer, pos, flexible.Length);
+ pos += flexible.Length;
+ }
+ if (light != null)
+ {
+ Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Light), 0, buffer, pos, 2);
+ pos += 2;
+
+ Buffer.BlockCopy(Utils.UIntToBytes((uint)light.Length), 0, buffer, pos, 4);
+ pos += 4;
+
+ Buffer.BlockCopy(light, 0, buffer, pos, light.Length);
+ pos += light.Length;
+ }
+ if (sculpt != null)
+ {
+ Buffer.BlockCopy(Utils.UInt16ToBytes((ushort)ExtraParamType.Sculpt), 0, buffer, pos, 2);
+ pos += 2;
+
+ Buffer.BlockCopy(Utils.UIntToBytes((uint)sculpt.Length), 0, buffer, pos, 4);
+ pos += 4;
+
+ Buffer.BlockCopy(sculpt, 0, buffer, pos, sculpt.Length);
+ pos += sculpt.Length;
+ }
+
+ return buffer;
+ }
+
+ #endregion Public Methods
+
+ #region Overrides
+
+ public override bool Equals(object obj)
+ {
+ return (obj is Primitive) ? this == (Primitive)obj : false;
+ }
+
+ public bool Equals(Primitive other)
+ {
+ return this == other;
+ }
+
+ public override string ToString()
+ {
+ switch (PrimData.PCode)
+ {
+ case PCode.Prim:
+ return String.Format("{0} ({1})", Type, ID);
+ default:
+ return String.Format("{0} ({1})", PrimData.PCode, ID);
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return
+ Position.GetHashCode() ^
+ Velocity.GetHashCode() ^
+ Acceleration.GetHashCode() ^
+ Rotation.GetHashCode() ^
+ AngularVelocity.GetHashCode() ^
+ ClickAction.GetHashCode() ^
+ (Flexible != null ? Flexible.GetHashCode() : 0) ^
+ (Light != null ? Light.GetHashCode() : 0) ^
+ (Sculpt != null ? Sculpt.GetHashCode() : 0) ^
+ Flags.GetHashCode() ^
+ PrimData.Material.GetHashCode() ^
+ MediaURL.GetHashCode() ^
+ //TODO: NameValues?
+ (Properties != null ? Properties.OwnerID.GetHashCode() : 0) ^
+ ParentID.GetHashCode() ^
+ PrimData.PathBegin.GetHashCode() ^
+ PrimData.PathCurve.GetHashCode() ^
+ PrimData.PathEnd.GetHashCode() ^
+ PrimData.PathRadiusOffset.GetHashCode() ^
+ PrimData.PathRevolutions.GetHashCode() ^
+ PrimData.PathScaleX.GetHashCode() ^
+ PrimData.PathScaleY.GetHashCode() ^
+ PrimData.PathShearX.GetHashCode() ^
+ PrimData.PathShearY.GetHashCode() ^
+ PrimData.PathSkew.GetHashCode() ^
+ PrimData.PathTaperX.GetHashCode() ^
+ PrimData.PathTaperY.GetHashCode() ^
+ PrimData.PathTwist.GetHashCode() ^
+ PrimData.PathTwistBegin.GetHashCode() ^
+ PrimData.PCode.GetHashCode() ^
+ PrimData.ProfileBegin.GetHashCode() ^
+ PrimData.ProfileCurve.GetHashCode() ^
+ PrimData.ProfileEnd.GetHashCode() ^
+ PrimData.ProfileHollow.GetHashCode() ^
+ ParticleSys.GetHashCode() ^
+ TextColor.GetHashCode() ^
+ TextureAnim.GetHashCode() ^
+ (Textures != null ? Textures.GetHashCode() : 0) ^
+ SoundRadius.GetHashCode() ^
+ Scale.GetHashCode() ^
+ Sound.GetHashCode() ^
+ PrimData.State.GetHashCode() ^
+ Text.GetHashCode() ^
+ TreeSpecies.GetHashCode();
+ }
+
+ #endregion Overrides
+
+ #region Operators
+
+ public static bool operator ==(Primitive lhs, Primitive rhs)
+ {
+ if ((Object)lhs == null || (Object)rhs == null)
+ {
+ return (Object)rhs == (Object)lhs;
+ }
+ return (lhs.ID == rhs.ID);
+ }
+
+ public static bool operator !=(Primitive lhs, Primitive rhs)
+ {
+ if ((Object)lhs == null || (Object)rhs == null)
+ {
+ return (Object)rhs != (Object)lhs;
+ }
+ return !(lhs.ID == rhs.ID);
+ }
+
+ #endregion Operators
+
+ #region Parameter Packing Methods
+
+ public static ushort PackBeginCut(float beginCut)
+ {
+ return (ushort)Math.Round(beginCut / CUT_QUANTA);
+ }
+
+ public static ushort PackEndCut(float endCut)
+ {
+ return (ushort)(50000 - (ushort)Math.Round(endCut / CUT_QUANTA));
+ }
+
+ public static byte PackPathScale(float pathScale)
+ {
+ return (byte)(200 - (byte)Math.Round(pathScale / SCALE_QUANTA));
+ }
+
+ public static sbyte PackPathShear(float pathShear)
+ {
+ return (sbyte)Math.Round(pathShear / SHEAR_QUANTA);
+ }
+
+ ///
+ /// Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew
+ /// parameters in to signed eight bit values
+ ///
+ /// Floating point parameter to pack
+ /// Signed eight bit value containing the packed parameter
+ public static sbyte PackPathTwist(float pathTwist)
+ {
+ return (sbyte)Math.Round(pathTwist / SCALE_QUANTA);
+ }
+
+ public static sbyte PackPathTaper(float pathTaper)
+ {
+ return (sbyte)Math.Round(pathTaper / TAPER_QUANTA);
+ }
+
+ public static byte PackPathRevolutions(float pathRevolutions)
+ {
+ return (byte)Math.Round((pathRevolutions - 1f) / REV_QUANTA);
+ }
+
+ public static ushort PackProfileHollow(float profileHollow)
+ {
+ return (ushort)Math.Round(profileHollow / HOLLOW_QUANTA);
+ }
+
+ #endregion Parameter Packing Methods
+
+ #region Parameter Unpacking Methods
+
+ public static float UnpackBeginCut(ushort beginCut)
+ {
+ return (float)beginCut * CUT_QUANTA;
+ }
+
+ public static float UnpackEndCut(ushort endCut)
+ {
+ return (float)(50000 - endCut) * CUT_QUANTA;
+ }
+
+ public static float UnpackPathScale(byte pathScale)
+ {
+ return (float)(200 - pathScale) * SCALE_QUANTA;
+ }
+
+ public static float UnpackPathShear(sbyte pathShear)
+ {
+ return (float)pathShear * SHEAR_QUANTA;
+ }
+
+ ///
+ /// Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew
+ /// parameters from signed eight bit integers to floating point values
+ ///
+ /// Signed eight bit value to unpack
+ /// Unpacked floating point value
+ public static float UnpackPathTwist(sbyte pathTwist)
+ {
+ return (float)pathTwist * SCALE_QUANTA;
+ }
+
+ public static float UnpackPathTaper(sbyte pathTaper)
+ {
+ return (float)pathTaper * TAPER_QUANTA;
+ }
+
+ public static float UnpackPathRevolutions(byte pathRevolutions)
+ {
+ return (float)pathRevolutions * REV_QUANTA + 1f;
+ }
+
+ public static float UnpackProfileHollow(ushort profileHollow)
+ {
+ return (float)profileHollow * HOLLOW_QUANTA;
+ }
+
+ #endregion Parameter Unpacking Methods
+ }
+}
diff --git a/OpenMetaverseTypes/EnumsPrimitive.cs b/OpenMetaverseTypes/EnumsPrimitive.cs
index 33076b18..e5005e63 100644
--- a/OpenMetaverseTypes/EnumsPrimitive.cs
+++ b/OpenMetaverseTypes/EnumsPrimitive.cs
@@ -533,4 +533,17 @@ namespace OpenMetaverse
/// Open parcel media
OpenMedia = 6
}
+
+ ///
+ /// Type of physics representation used for this prim in the simulator
+ ///
+ public enum PhysicsShapeType : byte
+ {
+ /// Use prim physics form this object
+ Prim = 0,
+ /// No physics, prim doesn't collide
+ None,
+ /// Use convex hull represantion of this prim
+ ConvexHull
+ }
}
\ No newline at end of file