* Added Utils.SHA1() git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@2321 52acb1d6-8a22-11de-b505-999d5b087335
1451 lines
48 KiB
C#
1451 lines
48 KiB
C#
/*
|
|
* 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
|
|
{
|
|
#region Enums
|
|
|
|
/// <summary>
|
|
/// Identifier code for primitive types
|
|
/// </summary>
|
|
public enum PCode : byte
|
|
{
|
|
/// <summary>None</summary>
|
|
None = 0,
|
|
/// <summary>A Primitive</summary>
|
|
Prim = 9,
|
|
/// <summary>A Avatar</summary>
|
|
Avatar = 47,
|
|
/// <summary>Linden grass</summary>
|
|
Grass = 95,
|
|
/// <summary>Linden tree</summary>
|
|
NewTree = 111,
|
|
/// <summary>A primitive that acts as the source for a particle stream</summary>
|
|
ParticleSystem = 143,
|
|
/// <summary>A Linden tree</summary>
|
|
Tree = 255
|
|
}
|
|
|
|
/// <summary>
|
|
/// Primary parameters for primitives such as Physics Enabled or Phantom
|
|
/// </summary>
|
|
[Flags]
|
|
public enum PrimFlags : uint
|
|
{
|
|
/// <summary>Deprecated</summary>
|
|
None = 0,
|
|
/// <summary>Whether physics are enabled for this object</summary>
|
|
Physics = 0x00000001,
|
|
/// <summary></summary>
|
|
CreateSelected = 0x00000002,
|
|
/// <summary></summary>
|
|
ObjectModify = 0x00000004,
|
|
/// <summary></summary>
|
|
ObjectCopy = 0x00000008,
|
|
/// <summary></summary>
|
|
ObjectAnyOwner = 0x00000010,
|
|
/// <summary></summary>
|
|
ObjectYouOwner = 0x00000020,
|
|
/// <summary></summary>
|
|
Scripted = 0x00000040,
|
|
/// <summary>Whether this object contains an active touch script</summary>
|
|
Touch = 0x00000080,
|
|
/// <summary></summary>
|
|
ObjectMove = 0x00000100,
|
|
/// <summary>Whether this object can receive payments</summary>
|
|
Money = 0x00000200,
|
|
/// <summary>Whether this object is phantom (no collisions)</summary>
|
|
Phantom = 0x00000400,
|
|
/// <summary></summary>
|
|
InventoryEmpty = 0x00000800,
|
|
/// <summary></summary>
|
|
JointHinge = 0x00001000,
|
|
/// <summary></summary>
|
|
JointP2P = 0x00002000,
|
|
/// <summary></summary>
|
|
JointLP2P = 0x00004000,
|
|
/// <summary>Deprecated</summary>
|
|
JointWheel = 0x00008000,
|
|
/// <summary></summary>
|
|
AllowInventoryDrop = 0x00010000,
|
|
/// <summary></summary>
|
|
ObjectTransfer = 0x00020000,
|
|
/// <summary></summary>
|
|
ObjectGroupOwned = 0x00040000,
|
|
/// <summary>Deprecated</summary>
|
|
ObjectYouOfficer = 0x00080000,
|
|
/// <summary></summary>
|
|
CameraDecoupled = 0x00100000,
|
|
/// <summary></summary>
|
|
AnimSource = 0x00200000,
|
|
/// <summary></summary>
|
|
CameraSource = 0x00400000,
|
|
/// <summary></summary>
|
|
CastShadows = 0x00800000,
|
|
/// <summary></summary>
|
|
ObjectOwnerModify = 0x10000000,
|
|
/// <summary></summary>
|
|
TemporaryOnRez = 0x20000000,
|
|
/// <summary></summary>
|
|
Temporary = 0x40000000,
|
|
/// <summary></summary>
|
|
ZlibCompressed = 0x80000000
|
|
}
|
|
|
|
public enum ProfileCurve : byte
|
|
{
|
|
Circle = 0x00,
|
|
Square = 0x01,
|
|
IsoTriangle = 0x02,
|
|
EqualTriangle = 0x03,
|
|
RightTriangle = 0x04,
|
|
HalfCircle = 0x05
|
|
}
|
|
|
|
public enum HoleType : byte
|
|
{
|
|
Same = 0x00,
|
|
Circle = 0x10,
|
|
Square = 0x20,
|
|
Triangle = 0x30
|
|
}
|
|
|
|
public enum PathCurve : byte
|
|
{
|
|
Line = 0x10,
|
|
Circle = 0x20,
|
|
Circle2 = 0x30,
|
|
Test = 0x40,
|
|
Flexible = 0x80
|
|
}
|
|
|
|
/// <summary>
|
|
/// Material type for a primitive
|
|
/// </summary>
|
|
public enum Material : byte
|
|
{
|
|
/// <summary></summary>
|
|
Stone = 0,
|
|
/// <summary></summary>
|
|
Metal,
|
|
/// <summary></summary>
|
|
Glass,
|
|
/// <summary></summary>
|
|
Wood,
|
|
/// <summary></summary>
|
|
Flesh,
|
|
/// <summary></summary>
|
|
Plastic,
|
|
/// <summary></summary>
|
|
Rubber,
|
|
/// <summary></summary>
|
|
Light
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used in a helper function to roughly determine prim shape
|
|
/// </summary>
|
|
public enum PrimType
|
|
{
|
|
Unknown,
|
|
Box,
|
|
Cylinder,
|
|
Prism,
|
|
Sphere,
|
|
Torus,
|
|
Tube,
|
|
Ring,
|
|
Sculpt
|
|
}
|
|
|
|
/// <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,
|
|
//[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
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public enum ObjectCategory
|
|
{
|
|
/// <summary></summary>
|
|
Invalid = -1,
|
|
/// <summary></summary>
|
|
None = 0,
|
|
/// <summary></summary>
|
|
Owner,
|
|
/// <summary></summary>
|
|
Group,
|
|
/// <summary></summary>
|
|
Other,
|
|
/// <summary></summary>
|
|
Selectected,
|
|
/// <summary></summary>
|
|
Temporary
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attachment points for objects on avatar bodies
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Both InventoryObject and InventoryAttachment types can be attached
|
|
///</remarks>
|
|
public enum AttachmentPoint : byte
|
|
{
|
|
/// <summary>Right hand if object was not previously attached</summary>
|
|
Default = 0,
|
|
/// <summary>Chest</summary>
|
|
Chest = 1,
|
|
/// <summary>Skull</summary>
|
|
Skull,
|
|
/// <summary>Left shoulder</summary>
|
|
LeftShoulder,
|
|
/// <summary>Right shoulder</summary>
|
|
RightShoulder,
|
|
/// <summary>Left hand</summary>
|
|
LeftHand,
|
|
/// <summary>Right hand</summary>
|
|
RightHand,
|
|
/// <summary>Left foot</summary>
|
|
LeftFoot,
|
|
/// <summary>Right foot</summary>
|
|
RightFoot,
|
|
/// <summary>Spine</summary>
|
|
Spine,
|
|
/// <summary>Pelvis</summary>
|
|
Pelvis,
|
|
/// <summary>Mouth</summary>
|
|
Mouth,
|
|
/// <summary>Chin</summary>
|
|
Chin,
|
|
/// <summary>Left ear</summary>
|
|
LeftEar,
|
|
/// <summary>Right ear</summary>
|
|
RightEar,
|
|
/// <summary>Left eyeball</summary>
|
|
LeftEyeball,
|
|
/// <summary>Right eyeball</summary>
|
|
RightEyeball,
|
|
/// <summary>Nose</summary>
|
|
Nose,
|
|
/// <summary>Right upper arm</summary>
|
|
RightUpperArm,
|
|
/// <summary>Right forearm</summary>
|
|
RightForearm,
|
|
/// <summary>Left upper arm</summary>
|
|
LeftUpperArm,
|
|
/// <summary>Left forearm</summary>
|
|
LeftForearm,
|
|
/// <summary>Right hip</summary>
|
|
RightHip,
|
|
/// <summary>Right upper leg</summary>
|
|
RightUpperLeg,
|
|
/// <summary>Right lower leg</summary>
|
|
RightLowerLeg,
|
|
/// <summary>Left hip</summary>
|
|
LeftHip,
|
|
/// <summary>Left upper leg</summary>
|
|
LeftUpperLeg,
|
|
/// <summary>Left lower leg</summary>
|
|
LeftLowerLeg,
|
|
/// <summary>Stomach</summary>
|
|
Stomach,
|
|
/// <summary>Left pectoral</summary>
|
|
LeftPec,
|
|
/// <summary>Right pectoral</summary>
|
|
RightPec,
|
|
/// <summary>HUD Center position 2</summary>
|
|
HUDCenter2,
|
|
/// <summary>HUD Top-right</summary>
|
|
HUDTopRight,
|
|
/// <summary>HUD Top</summary>
|
|
HUDTop,
|
|
/// <summary>HUD Top-left</summary>
|
|
HUDTopLeft,
|
|
/// <summary>HUD Center</summary>
|
|
HUDCenter,
|
|
/// <summary>HUD Bottom-left</summary>
|
|
HUDBottomLeft,
|
|
/// <summary>HUD Bottom</summary>
|
|
HUDBottom,
|
|
/// <summary>HUD Bottom-right</summary>
|
|
HUDBottomRight
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tree foliage types
|
|
/// </summary>
|
|
public enum Tree : byte
|
|
{
|
|
/// <summary>Pine1 tree</summary>
|
|
Pine1 = 0,
|
|
/// <summary>Oak tree</summary>
|
|
Oak,
|
|
/// <summary>Tropical Bush1</summary>
|
|
TropicalBush1,
|
|
/// <summary>Palm1 tree</summary>
|
|
Palm1,
|
|
/// <summary>Dogwood tree</summary>
|
|
Dogwood,
|
|
/// <summary>Tropical Bush2</summary>
|
|
TropicalBush2,
|
|
/// <summary>Palm2 tree</summary>
|
|
Palm2,
|
|
/// <summary>Cypress1 tree</summary>
|
|
Cypress1,
|
|
/// <summary>Cypress2 tree</summary>
|
|
Cypress2,
|
|
/// <summary>Pine2 tree</summary>
|
|
Pine2,
|
|
/// <summary>Plumeria</summary>
|
|
Plumeria,
|
|
/// <summary>Winter pinetree1</summary>
|
|
WinterPine1,
|
|
/// <summary>Winter Aspen tree</summary>
|
|
WinterAspen,
|
|
/// <summary>Winter pinetree2</summary>
|
|
WinterPine2,
|
|
/// <summary>Eucalyptus tree</summary>
|
|
Eucalyptus,
|
|
/// <summary>Fern</summary>
|
|
Fern,
|
|
/// <summary>Eelgrass</summary>
|
|
Eelgrass,
|
|
/// <summary>Sea Sword</summary>
|
|
SeaSword,
|
|
/// <summary>Kelp1 plant</summary>
|
|
Kelp1,
|
|
/// <summary>Beach grass</summary>
|
|
BeachGrass1,
|
|
/// <summary>Kelp2 plant</summary>
|
|
Kelp2
|
|
}
|
|
|
|
/// <summary>
|
|
/// Grass foliage types
|
|
/// </summary>
|
|
public enum Grass : byte
|
|
{
|
|
/// <summary></summary>
|
|
Grass0 = 0,
|
|
/// <summary></summary>
|
|
Grass1,
|
|
/// <summary></summary>
|
|
Grass2,
|
|
/// <summary></summary>
|
|
Grass3,
|
|
/// <summary></summary>
|
|
Grass4,
|
|
/// <summary></summary>
|
|
Undergrowth1
|
|
}
|
|
|
|
/// <summary>
|
|
/// Action associated with clicking on an object
|
|
/// </summary>
|
|
public enum ClickAction : byte
|
|
{
|
|
/// <summary>Touch object</summary>
|
|
Touch = 0,
|
|
/// <summary>Sit on object</summary>
|
|
Sit = 1,
|
|
/// <summary>Purchase object or contents</summary>
|
|
Buy = 2,
|
|
/// <summary>Pay the object</summary>
|
|
Pay = 3,
|
|
/// <summary>Open task inventory</summary>
|
|
OpenTask = 4,
|
|
/// <summary>Play parcel media</summary>
|
|
PlayMedia = 5,
|
|
/// <summary>Open parcel media</summary>
|
|
OpenMedia = 6
|
|
}
|
|
|
|
#endregion Enums
|
|
|
|
public partial class Primitive : IEquatable<Primitive>
|
|
{
|
|
// 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
|
|
|
|
/// <summary>
|
|
/// Parameters used to construct a visual representation of a primitive
|
|
/// </summary>
|
|
public struct ConstructionData
|
|
{
|
|
private const byte PROFILE_MASK = 0x0F;
|
|
private const byte HOLE_MASK = 0xF0;
|
|
|
|
/// <summary></summary>
|
|
public byte profileCurve;
|
|
/// <summary></summary>
|
|
public PathCurve PathCurve;
|
|
/// <summary></summary>
|
|
public float PathEnd;
|
|
/// <summary></summary>
|
|
public float PathRadiusOffset;
|
|
/// <summary></summary>
|
|
public float PathSkew;
|
|
/// <summary></summary>
|
|
public float PathScaleX;
|
|
/// <summary></summary>
|
|
public float PathScaleY;
|
|
/// <summary></summary>
|
|
public float PathShearX;
|
|
/// <summary></summary>
|
|
public float PathShearY;
|
|
/// <summary></summary>
|
|
public float PathTaperX;
|
|
/// <summary></summary>
|
|
public float PathTaperY;
|
|
/// <summary></summary>
|
|
public float PathBegin;
|
|
/// <summary></summary>
|
|
public float PathTwist;
|
|
/// <summary></summary>
|
|
public float PathTwistBegin;
|
|
/// <summary></summary>
|
|
public float PathRevolutions;
|
|
/// <summary></summary>
|
|
public float ProfileBegin;
|
|
/// <summary></summary>
|
|
public float ProfileEnd;
|
|
/// <summary></summary>
|
|
public float ProfileHollow;
|
|
|
|
/// <summary></summary>
|
|
public Material Material;
|
|
/// <summary></summary>
|
|
public byte State;
|
|
/// <summary></summary>
|
|
public PCode PCode;
|
|
|
|
#region Properties
|
|
|
|
/// <summary></summary>
|
|
public ProfileCurve ProfileCurve
|
|
{
|
|
get { return (ProfileCurve)(profileCurve & PROFILE_MASK); }
|
|
set
|
|
{
|
|
profileCurve &= HOLE_MASK;
|
|
profileCurve |= (byte)value;
|
|
}
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public HoleType ProfileHole
|
|
{
|
|
get { return (HoleType)(profileCurve & HOLE_MASK); }
|
|
set
|
|
{
|
|
profileCurve &= PROFILE_MASK;
|
|
profileCurve |= (byte)value;
|
|
}
|
|
}
|
|
|
|
/// <summary></summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary></summary>
|
|
public Vector2 PathEndScale
|
|
{
|
|
get
|
|
{
|
|
Vector2 end = new Vector2(1f, 1f);
|
|
if (PathScaleX < 1f)
|
|
end.X = PathScaleX;
|
|
if (PathScaleY < 1f)
|
|
end.Y = PathScaleY;
|
|
return end;
|
|
}
|
|
}
|
|
|
|
/// <summary>Uses basic heuristics to estimate the primitive shape</summary>
|
|
public PrimType Type
|
|
{
|
|
get
|
|
{
|
|
bool linearPath = (PathCurve == PathCurve.Line || PathCurve == PathCurve.Flexible);
|
|
float scaleY = PathScaleY;
|
|
|
|
if (linearPath)
|
|
{
|
|
switch (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 (PathCurve)
|
|
{
|
|
case PathCurve.Flexible:
|
|
return PrimType.Unknown;
|
|
case PathCurve.Circle:
|
|
switch (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 (ProfileCurve == ProfileCurve.Circle)
|
|
return PrimType.Sphere;
|
|
else
|
|
return PrimType.Unknown;
|
|
default:
|
|
return PrimType.Unknown;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Properties
|
|
|
|
public override string ToString()
|
|
{
|
|
return Type.ToString();
|
|
}
|
|
}
|
|
|
|
/// <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 Vector3 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 Vector3(data, pos);
|
|
}
|
|
else
|
|
{
|
|
Softness = 0;
|
|
|
|
Tension = 0.0f;
|
|
Drag = 0.0f;
|
|
Gravity = 0.0f;
|
|
Wind = 0.0f;
|
|
Force = Vector3.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>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Information on the light properties of a primitive
|
|
/// </summary>
|
|
public struct LightData
|
|
{
|
|
/// <summary></summary>
|
|
public Color4 Color;
|
|
/// <summary></summary>
|
|
public float Intensity;
|
|
/// <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 - 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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
return String.Format("Color: {0} Intensity: {1} Radius: {2} Cutoff: {3} Falloff: {4}",
|
|
Color, Intensity, Radius, Cutoff, Falloff);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Information on the sculpt properties of a sculpted primitive
|
|
/// </summary>
|
|
public struct SculptData
|
|
{
|
|
public UUID SculptTexture;
|
|
public SculptType Type;
|
|
|
|
public SculptData(byte[] data, int pos)
|
|
{
|
|
if (data.Length >= 17)
|
|
{
|
|
SculptTexture = new UUID(data, pos);
|
|
Type = (SculptType)data[pos + 16];
|
|
}
|
|
else
|
|
{
|
|
SculptTexture = UUID.Zero;
|
|
Type = SculptType.None;
|
|
}
|
|
}
|
|
|
|
public byte[] GetBytes()
|
|
{
|
|
byte[] data = new byte[17];
|
|
|
|
SculptTexture.GetBytes().CopyTo(data, 0);
|
|
data[16] = (byte)Type;
|
|
|
|
return data;
|
|
}
|
|
|
|
public OSD GetOSD()
|
|
{
|
|
OSDMap map = new OSDMap();
|
|
|
|
map["texture"] = OSD.FromUUID(SculptTexture);
|
|
map["type"] = OSD.FromInteger((int)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 = (SculptType)map["type"].AsInteger();
|
|
}
|
|
|
|
return sculpt;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extended properties to describe an object
|
|
/// </summary>
|
|
public struct ObjectProperties
|
|
{
|
|
/// <summary></summary>
|
|
public UUID ObjectID;
|
|
/// <summary></summary>
|
|
public UUID CreatorID;
|
|
/// <summary></summary>
|
|
public UUID OwnerID;
|
|
/// <summary></summary>
|
|
public UUID GroupID;
|
|
/// <summary></summary>
|
|
public DateTime CreationDate;
|
|
/// <summary></summary>
|
|
public Permissions Permissions;
|
|
/// <summary></summary>
|
|
public int OwnershipCost;
|
|
/// <summary></summary>
|
|
public SaleType SaleType;
|
|
/// <summary></summary>
|
|
public int SalePrice;
|
|
/// <summary></summary>
|
|
public byte AggregatePerms;
|
|
/// <summary></summary>
|
|
public byte AggregatePermTextures;
|
|
/// <summary></summary>
|
|
public byte AggregatePermTexturesOwner;
|
|
/// <summary></summary>
|
|
public ObjectCategory Category;
|
|
/// <summary></summary>
|
|
public short InventorySerial;
|
|
/// <summary></summary>
|
|
public UUID ItemID;
|
|
/// <summary></summary>
|
|
public UUID FolderID;
|
|
/// <summary></summary>
|
|
public UUID FromTaskID;
|
|
/// <summary></summary>
|
|
public UUID LastOwnerID;
|
|
/// <summary></summary>
|
|
public string Name;
|
|
/// <summary></summary>
|
|
public string Description;
|
|
/// <summary></summary>
|
|
public string TouchName;
|
|
/// <summary></summary>
|
|
public string SitName;
|
|
/// <summary></summary>
|
|
public UUID[] TextureIDs;
|
|
|
|
/// <summary>
|
|
/// Set the properties that are set in an ObjectPropertiesFamily packet
|
|
/// </summary>
|
|
/// <param name="props"><seealso cref="ObjectProperties"/> that has
|
|
/// been partially filled by an ObjectPropertiesFamily packet</param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
#endregion Subclasses
|
|
|
|
#region Public Members
|
|
|
|
/// <summary></summary>
|
|
public UUID ID;
|
|
/// <summary></summary>
|
|
public UUID GroupID;
|
|
/// <summary></summary>
|
|
public uint LocalID;
|
|
/// <summary></summary>
|
|
public uint ParentID;
|
|
/// <summary></summary>
|
|
public ulong RegionHandle;
|
|
/// <summary></summary>
|
|
public PrimFlags Flags;
|
|
/// <summary>Unknown</summary>
|
|
public byte[] GenericData;
|
|
/// <summary></summary>
|
|
public Vector3 Position;
|
|
/// <summary></summary>
|
|
public Vector3 Scale;
|
|
/// <summary></summary>
|
|
public Quaternion Rotation;
|
|
/// <summary></summary>
|
|
public Vector3 Velocity;
|
|
/// <summary></summary>
|
|
public Vector3 AngularVelocity;
|
|
/// <summary></summary>
|
|
public Vector3 Acceleration;
|
|
/// <summary></summary>
|
|
public Vector4 CollisionPlane;
|
|
/// <summary></summary>
|
|
public FlexibleData Flexible;
|
|
/// <summary></summary>
|
|
public LightData Light;
|
|
/// <summary></summary>
|
|
public SculptData Sculpt;
|
|
/// <summary></summary>
|
|
public ClickAction ClickAction;
|
|
/// <summary></summary>
|
|
public UUID Sound;
|
|
/// <summary>Identifies the owner if audio or a particle system is
|
|
/// active</summary>
|
|
public UUID OwnerID;
|
|
/// <summary></summary>
|
|
public byte SoundFlags;
|
|
/// <summary></summary>
|
|
public float SoundGain;
|
|
/// <summary></summary>
|
|
public float SoundRadius;
|
|
/// <summary></summary>
|
|
public string Text;
|
|
/// <summary></summary>
|
|
public Color4 TextColor;
|
|
/// <summary></summary>
|
|
public string MediaURL;
|
|
/// <summary></summary>
|
|
public JointType Joint;
|
|
/// <summary></summary>
|
|
public Vector3 JointPivot;
|
|
/// <summary></summary>
|
|
public Vector3 JointAxisOrAnchor;
|
|
/// <summary></summary>
|
|
public NameValue[] NameValues;
|
|
/// <summary></summary>
|
|
public ConstructionData PrimData;
|
|
/// <summary></summary>
|
|
public ObjectProperties Properties;
|
|
|
|
#endregion Public Members
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Default constructor
|
|
/// </summary>
|
|
public Primitive()
|
|
{
|
|
// Default a few null property values to String.Empty
|
|
Text = String.Empty;
|
|
MediaURL = String.Empty;
|
|
Properties.Name = String.Empty;
|
|
Properties.Description = String.Empty;
|
|
Properties.TouchName = String.Empty;
|
|
Properties.SitName = String.Empty;
|
|
}
|
|
|
|
public Primitive(Primitive prim)
|
|
{
|
|
ID = prim.ID;
|
|
GroupID = prim.GroupID;
|
|
LocalID = prim.LocalID;
|
|
ParentID = prim.ParentID;
|
|
RegionHandle = prim.RegionHandle;
|
|
Flags = prim.Flags;
|
|
if (prim.GenericData != null)
|
|
Buffer.BlockCopy(prim.GenericData, 0, GenericData, 0, prim.GenericData.Length);
|
|
else
|
|
GenericData = null;
|
|
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)
|
|
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.ToBytes();
|
|
Textures = new TextureEntry(textureBytes, 0, textureBytes.Length);
|
|
}
|
|
else
|
|
{
|
|
Textures = null;
|
|
}
|
|
TextureAnim = prim.TextureAnim;
|
|
ParticleSys = prim.ParticleSys;
|
|
}
|
|
|
|
#endregion Constructors
|
|
|
|
#region Public Methods
|
|
|
|
public 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(9);
|
|
prim["name"] = OSD.FromString(Properties.Name);
|
|
prim["description"] = OSD.FromString(Properties.Description);
|
|
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["material"] = OSD.FromInteger((int)PrimData.Material);
|
|
prim["shadows"] = OSD.FromBoolean(((Flags & PrimFlags.CastShadows) != 0));
|
|
prim["textures"] = Textures.GetOSD();
|
|
prim["volume"] = volume;
|
|
if (ParentID != 0)
|
|
prim["parentid"] = OSD.FromInteger(ParentID);
|
|
|
|
prim["light"] = Light.GetOSD();
|
|
prim["flex"] = Flexible.GetOSD();
|
|
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.State = 0;
|
|
data.Material = (Material)map["material"].AsInteger();
|
|
data.PCode = PCode.Prim; // TODO: Put this in SD
|
|
|
|
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.ParentID = (uint)map["parentid"].AsInteger();
|
|
prim.Position = ((OSDArray)map["position"]).AsVector3();
|
|
prim.Rotation = ((OSDArray)map["rotation"]).AsQuaternion();
|
|
prim.Scale = ((OSDArray)map["scale"]).AsVector3();
|
|
prim.Flexible = FlexibleData.FromOSD(map["flex"]);
|
|
prim.Light = LightData.FromOSD(map["light"]);
|
|
prim.Sculpt = SculptData.FromOSD(map["sculpt"]);
|
|
prim.Textures = TextureEntry.FromOSD(map["textures"]);
|
|
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;
|
|
}
|
|
|
|
#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})", PrimData.Type, ID);
|
|
default:
|
|
return String.Format("{0} ({1})", PrimData.PCode, ID);
|
|
}
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return ID.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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew
|
|
/// parameters in to signed eight bit values
|
|
/// </summary>
|
|
/// <param name="pathTwist">Floating point parameter to pack</param>
|
|
/// <returns>Signed eight bit value containing the packed parameter</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew
|
|
/// parameters from signed eight bit integers to floating point values
|
|
/// </summary>
|
|
/// <param name="pathTwist">Signed eight bit value to unpack</param>
|
|
/// <returns>Unpacked floating point value</returns>
|
|
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
|
|
}
|
|
}
|