592 lines
18 KiB
C#
592 lines
18 KiB
C#
/*
|
|
* Copyright (c) Contributors, http://opensimulator.org/
|
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
|
*
|
|
* 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.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of the OpenSim Project 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 DEVELOPERS ``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 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.Xml.Serialization;
|
|
using libsecondlife;
|
|
|
|
namespace OpenSim.Framework
|
|
{
|
|
public enum ProfileShape : byte
|
|
{
|
|
Circle = 0,
|
|
Square = 1,
|
|
IsometricTriangle = 2,
|
|
EquilateralTriangle = 3,
|
|
RightTriangle = 4,
|
|
HalfCircle = 5
|
|
}
|
|
|
|
public enum HollowShape : byte
|
|
{
|
|
Same = 0,
|
|
Circle = 16,
|
|
Square = 32,
|
|
Triangle = 48
|
|
}
|
|
|
|
public enum PCodeEnum : byte
|
|
{
|
|
Primitive = 9,
|
|
Avatar = 47,
|
|
Grass = 95,
|
|
NewTree = 111,
|
|
ParticleSystem = 143,
|
|
Tree = 255
|
|
}
|
|
|
|
public enum Extrusion : byte
|
|
{
|
|
Straight = 16,
|
|
Curve1 = 32,
|
|
Curve2 = 48,
|
|
Flexible = 128
|
|
}
|
|
|
|
[Serializable]
|
|
public class PrimitiveBaseShape
|
|
{
|
|
private static readonly LLObject.TextureEntry m_defaultTexture;
|
|
|
|
private byte[] m_textureEntry;
|
|
|
|
public ushort PathBegin;
|
|
public byte PathCurve;
|
|
public ushort PathEnd;
|
|
public sbyte PathRadiusOffset;
|
|
public byte PathRevolutions;
|
|
public byte PathScaleX;
|
|
public byte PathScaleY;
|
|
public byte PathShearX;
|
|
public byte PathShearY;
|
|
public sbyte PathSkew;
|
|
public sbyte PathTaperX;
|
|
public sbyte PathTaperY;
|
|
public sbyte PathTwist;
|
|
public sbyte PathTwistBegin;
|
|
public byte PCode;
|
|
public ushort ProfileBegin;
|
|
|
|
public byte ProfileCurve;
|
|
|
|
public ushort ProfileEnd;
|
|
public ushort ProfileHollow;
|
|
public LLVector3 Scale;
|
|
public byte State;
|
|
// Sculpted
|
|
[XmlIgnore] public LLUUID SculptTexture = LLUUID.Zero;
|
|
[XmlIgnore] public byte SculptType = (byte)0;
|
|
|
|
// Flexi
|
|
[XmlIgnore] public int FlexiSoftness = 0;
|
|
[XmlIgnore] public float FlexiTension = 0f;
|
|
[XmlIgnore] public float FlexiDrag = 0f;
|
|
[XmlIgnore] public float FlexiGravity = 0f;
|
|
[XmlIgnore] public float FlexiWind= 0f;
|
|
[XmlIgnore] public float FlexiForceX = 0f;
|
|
[XmlIgnore] public float FlexiForceY = 0f;
|
|
[XmlIgnore] public float FlexiForceZ = 0f;
|
|
|
|
//Bright n sparkly
|
|
[XmlIgnore] public float LightColorR = 0f;
|
|
[XmlIgnore] public float LightColorG = 0f;
|
|
[XmlIgnore] public float LightColorB = 0f;
|
|
[XmlIgnore] public float LightColorA = 1f;
|
|
[XmlIgnore] public float LightRadius = 0f;
|
|
[XmlIgnore] public float LightCutoff = 0f;
|
|
[XmlIgnore] public float LightFalloff = 0f;
|
|
[XmlIgnore] public float LightIntensity = 1f;
|
|
[XmlIgnore] public bool FlexiEntry = false;
|
|
[XmlIgnore] public bool LightEntry = false;
|
|
[XmlIgnore] public bool SculptEntry = false;
|
|
|
|
|
|
static PrimitiveBaseShape()
|
|
{
|
|
m_defaultTexture =
|
|
new LLObject.TextureEntry(new LLUUID("89556747-24cb-43ed-920b-47caed15465f"));
|
|
}
|
|
|
|
public PrimitiveBaseShape()
|
|
{
|
|
PCode = (byte) PCodeEnum.Primitive;
|
|
ExtraParams = new byte[1];
|
|
Textures = m_defaultTexture;
|
|
}
|
|
|
|
[XmlIgnore]
|
|
public LLObject.TextureEntry Textures
|
|
{
|
|
get { return new LLObject.TextureEntry(m_textureEntry, 0, m_textureEntry.Length); }
|
|
|
|
set { m_textureEntry = value.ToBytes(); }
|
|
}
|
|
|
|
public byte[] TextureEntry
|
|
{
|
|
get { return m_textureEntry; }
|
|
|
|
set { m_textureEntry = value; }
|
|
}
|
|
|
|
public ProfileShape ProfileShape
|
|
{
|
|
get { return (ProfileShape) (ProfileCurve & 0xf); }
|
|
set
|
|
{
|
|
byte oldValueMasked = (byte) (ProfileCurve & 0xf0);
|
|
ProfileCurve = (byte) (oldValueMasked | (byte) value);
|
|
}
|
|
}
|
|
|
|
public HollowShape HollowShape
|
|
{
|
|
get { return (HollowShape) (ProfileCurve & 0xf0); }
|
|
set
|
|
{
|
|
byte oldValueMasked = (byte) (ProfileCurve & 0x0f);
|
|
ProfileCurve = (byte) (oldValueMasked | (byte) value);
|
|
}
|
|
}
|
|
|
|
public static PrimitiveBaseShape Default
|
|
{
|
|
get
|
|
{
|
|
PrimitiveBaseShape boxShape = CreateBox();
|
|
|
|
boxShape.SetScale(0.5f);
|
|
|
|
return boxShape;
|
|
}
|
|
}
|
|
|
|
|
|
public static PrimitiveBaseShape Create()
|
|
{
|
|
PrimitiveBaseShape shape = new PrimitiveBaseShape();
|
|
return shape;
|
|
}
|
|
|
|
public static PrimitiveBaseShape CreateBox()
|
|
{
|
|
PrimitiveBaseShape shape = Create();
|
|
|
|
shape.PathCurve = (byte) Extrusion.Straight;
|
|
shape.ProfileShape = ProfileShape.Square;
|
|
shape.PathScaleX = 100;
|
|
shape.PathScaleY = 100;
|
|
|
|
return shape;
|
|
}
|
|
|
|
public static PrimitiveBaseShape CreateCylinder()
|
|
{
|
|
PrimitiveBaseShape shape = Create();
|
|
|
|
shape.PathCurve = (byte) Extrusion.Curve1;
|
|
shape.ProfileShape = ProfileShape.Square;
|
|
|
|
shape.PathScaleX = 100;
|
|
shape.PathScaleY = 100;
|
|
|
|
return shape;
|
|
}
|
|
|
|
public void SetScale(float side)
|
|
{
|
|
Scale = new LLVector3(side, side, side);
|
|
}
|
|
|
|
public void SetHeigth(float heigth)
|
|
{
|
|
Scale.Z = heigth;
|
|
}
|
|
|
|
public void SetRadius(float radius)
|
|
{
|
|
Scale.X = Scale.Y = radius * 2f;
|
|
}
|
|
|
|
// TODO: void returns need to change of course
|
|
public virtual void GetMesh()
|
|
{
|
|
}
|
|
|
|
public PrimitiveBaseShape Copy()
|
|
{
|
|
return (PrimitiveBaseShape) MemberwiseClone();
|
|
}
|
|
|
|
public static PrimitiveBaseShape CreateCylinder(float radius, float heigth)
|
|
{
|
|
PrimitiveBaseShape shape = CreateCylinder();
|
|
|
|
shape.SetHeigth(heigth);
|
|
shape.SetRadius(radius);
|
|
|
|
return shape;
|
|
}
|
|
|
|
public void SetPathRange(LLVector3 pathRange)
|
|
{
|
|
PathBegin = LLObject.PackBeginCut(pathRange.X);
|
|
PathEnd = LLObject.PackEndCut(pathRange.Y);
|
|
}
|
|
|
|
public void SetSculptData(byte sculptType, LLUUID SculptTextureUUID)
|
|
{
|
|
SculptType = sculptType;
|
|
SculptTexture = SculptTextureUUID;
|
|
}
|
|
|
|
public void SetProfileRange(LLVector3 profileRange)
|
|
{
|
|
ProfileBegin = LLObject.PackBeginCut(profileRange.X);
|
|
ProfileEnd = LLObject.PackEndCut(profileRange.Y);
|
|
}
|
|
public byte[] ExtraParams
|
|
{
|
|
get
|
|
{
|
|
return ExtraParamsToBytes();
|
|
}
|
|
set
|
|
{
|
|
ReadInExtraParamsBytes(value);
|
|
}
|
|
}
|
|
|
|
public byte[] ExtraParamsToBytes()
|
|
{
|
|
ushort FlexiEP = 0x10;
|
|
ushort LightEP = 0x20;
|
|
ushort SculptEP = 0x30;
|
|
|
|
int i = 0;
|
|
uint TotalBytesLength = 5;
|
|
|
|
uint ExtraParamsNum = 0;
|
|
if (FlexiEntry)
|
|
{
|
|
ExtraParamsNum++;
|
|
TotalBytesLength += 16;// data
|
|
TotalBytesLength += 4; // type
|
|
}
|
|
if (LightEntry)
|
|
{
|
|
ExtraParamsNum++;
|
|
TotalBytesLength += 16;// data
|
|
TotalBytesLength += 4; // type
|
|
}
|
|
if (SculptEntry)
|
|
{
|
|
ExtraParamsNum++;
|
|
TotalBytesLength += 17;// data
|
|
TotalBytesLength += 4; // type
|
|
}
|
|
|
|
byte[] returnbytes = new byte[TotalBytesLength];
|
|
|
|
|
|
uint paramlength = ExtraParamsNum;
|
|
|
|
// Stick in the number of parameters
|
|
returnbytes[i++] = (byte)ExtraParamsNum;
|
|
|
|
if (FlexiEntry)
|
|
{
|
|
byte[] FlexiData = GetFlexiBytes();
|
|
|
|
returnbytes[i++] = (byte)(FlexiEP % 256);
|
|
returnbytes[i++] = (byte)((FlexiEP >> 8) % 256);
|
|
|
|
returnbytes[i++] = (byte)(FlexiData.Length % 256);
|
|
returnbytes[i++] = (byte)((FlexiData.Length >> 8) % 256);
|
|
returnbytes[i++] = (byte)((FlexiData.Length >> 16) % 256);
|
|
returnbytes[i++] = (byte)((FlexiData.Length >> 24) % 256);
|
|
Array.Copy(FlexiData, 0, returnbytes, i, FlexiData.Length);
|
|
i += FlexiData.Length;
|
|
}
|
|
if (LightEntry)
|
|
{
|
|
byte[] LightData = GetLightBytes();
|
|
|
|
returnbytes[i++] = (byte)(LightEP % 256);
|
|
returnbytes[i++] = (byte)((LightEP >> 8) % 256);
|
|
|
|
returnbytes[i++] = (byte)(LightData.Length % 256);
|
|
returnbytes[i++] = (byte)((LightData.Length >> 8) % 256);
|
|
returnbytes[i++] = (byte)((LightData.Length >> 16) % 256);
|
|
returnbytes[i++] = (byte)((LightData.Length >> 24) % 256);
|
|
Array.Copy(LightData, 0, returnbytes, i, LightData.Length);
|
|
i += LightData.Length;
|
|
}
|
|
if (SculptEntry)
|
|
{
|
|
byte[] SculptData = GetSculptBytes();
|
|
|
|
returnbytes[i++] = (byte)(SculptEP % 256);
|
|
returnbytes[i++] = (byte)((SculptEP >> 8) % 256);
|
|
|
|
returnbytes[i++] = (byte)(SculptData.Length % 256);
|
|
returnbytes[i++] = (byte)((SculptData.Length >> 8) % 256);
|
|
returnbytes[i++] = (byte)((SculptData.Length >> 16) % 256);
|
|
returnbytes[i++] = (byte)((SculptData.Length >> 24) % 256);
|
|
Array.Copy(SculptData, 0, returnbytes, i, SculptData.Length);
|
|
i += SculptData.Length;
|
|
}
|
|
|
|
if (!FlexiEntry && !LightEntry && !SculptEntry)
|
|
{
|
|
byte[] returnbyte = new byte[1];
|
|
returnbyte[0] = 0;
|
|
return returnbyte;
|
|
}
|
|
|
|
|
|
return returnbytes;
|
|
//m_log.Info("[EXTRAPARAMS]: Length = " + m_shape.ExtraParams.Length.ToString());
|
|
|
|
}
|
|
|
|
public void ReadInUpdateExtraParam(ushort type, bool inUse, byte[] data)
|
|
{
|
|
const ushort FlexiEP = 0x10;
|
|
const ushort LightEP = 0x20;
|
|
const ushort SculptEP = 0x30;
|
|
|
|
switch (type)
|
|
{
|
|
case FlexiEP:
|
|
if (!inUse)
|
|
{
|
|
FlexiEntry = false;
|
|
return;
|
|
}
|
|
ReadFlexiData(data, 0);
|
|
break;
|
|
|
|
case LightEP:
|
|
if (!inUse)
|
|
{
|
|
LightEntry = false;
|
|
return;
|
|
}
|
|
ReadLightData(data, 0);
|
|
break;
|
|
|
|
case SculptEP:
|
|
if (!inUse)
|
|
{
|
|
SculptEntry = false;
|
|
return;
|
|
}
|
|
ReadSculptData(data, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ReadInExtraParamsBytes(byte[] data)
|
|
{
|
|
const ushort FlexiEP = 0x10;
|
|
const ushort LightEP = 0x20;
|
|
const ushort SculptEP = 0x30;
|
|
|
|
bool lGotFlexi = false;
|
|
bool lGotLight = false;
|
|
bool lGotSculpt = false;
|
|
|
|
int i = 0;
|
|
byte extraParamCount = data[i++];
|
|
|
|
|
|
for (int k = 0; k < extraParamCount; k++)
|
|
{
|
|
ushort epType = Helpers.BytesToUInt16(data, i);
|
|
|
|
i += 2;
|
|
uint paramLength = Helpers.BytesToUIntBig(data, i);
|
|
|
|
i += 4;
|
|
switch (epType)
|
|
{
|
|
case FlexiEP:
|
|
ReadFlexiData(data, i);
|
|
lGotFlexi = true;
|
|
break;
|
|
|
|
case LightEP:
|
|
ReadLightData(data, i);
|
|
lGotLight = true;
|
|
break;
|
|
|
|
case SculptEP:
|
|
ReadSculptData(data, i);
|
|
lGotSculpt = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!lGotFlexi)
|
|
FlexiEntry = false;
|
|
if (!lGotLight)
|
|
LightEntry = false;
|
|
if (!lGotSculpt)
|
|
SculptEntry = false;
|
|
|
|
}
|
|
|
|
public void ReadSculptData(byte[] data, int pos)
|
|
{
|
|
byte[] SculptTextureUUID = new byte[16];
|
|
LLUUID SculptUUID = LLUUID.Zero;
|
|
byte SculptTypel = data[16+pos];
|
|
|
|
if (data.Length+pos >= 17)
|
|
{
|
|
SculptEntry = true;
|
|
SculptTextureUUID = new byte[16];
|
|
SculptTypel = data[16];
|
|
Array.Copy(data, pos, SculptTextureUUID,0, 16);
|
|
SculptUUID = new LLUUID(SculptTextureUUID, 0);
|
|
}
|
|
else
|
|
{
|
|
SculptEntry = false;
|
|
SculptUUID = LLUUID.Zero;
|
|
SculptTypel = 0x00;
|
|
}
|
|
|
|
|
|
SculptTexture = SculptUUID;
|
|
SculptType = SculptTypel;
|
|
//m_log.Info("[SCULPT]:" + SculptUUID.ToString());
|
|
}
|
|
|
|
public byte[] GetSculptBytes()
|
|
{
|
|
byte[] data = new byte[17];
|
|
|
|
SculptTexture.GetBytes().CopyTo(data, 0);
|
|
data[16] = (byte)SculptType;
|
|
|
|
return data;
|
|
}
|
|
public void ReadFlexiData(byte[] data, int pos)
|
|
{
|
|
if (data.Length-pos >= 5)
|
|
{
|
|
FlexiEntry = true;
|
|
FlexiSoftness = ((data[pos] & 0x80) >> 6) | ((data[pos + 1] & 0x80) >> 7);
|
|
|
|
FlexiTension = (float)(data[pos++] & 0x7F) / 10.0f;
|
|
FlexiDrag = (float)(data[pos++] & 0x7F) / 10.0f;
|
|
FlexiGravity = (float)(data[pos++] / 10.0f) - 10.0f;
|
|
FlexiWind = (float)data[pos++] / 10.0f;
|
|
LLVector3 lForce = new LLVector3(data, pos);
|
|
FlexiForceX = lForce.X;
|
|
FlexiForceY = lForce.Y;
|
|
FlexiForceZ = lForce.Z;
|
|
}
|
|
else
|
|
{
|
|
FlexiEntry = false;
|
|
FlexiSoftness = 0;
|
|
|
|
FlexiTension = 0.0f;
|
|
FlexiDrag = 0.0f;
|
|
FlexiGravity = 0.0f;
|
|
FlexiWind = 0.0f;
|
|
FlexiForceX = 0f;
|
|
FlexiForceY = 0f;
|
|
FlexiForceZ = 0f;
|
|
}
|
|
}
|
|
public byte[] GetFlexiBytes()
|
|
{
|
|
byte[] data = new byte[16];
|
|
int i = 0;
|
|
|
|
// Softness is packed in the upper bits of tension and drag
|
|
data[i] = (byte)((FlexiSoftness & 2) << 6);
|
|
data[i + 1] = (byte)((FlexiSoftness & 1) << 7);
|
|
|
|
data[i++] |= (byte)((byte)(FlexiTension * 10.01f) & 0x7F);
|
|
data[i++] |= (byte)((byte)(FlexiDrag * 10.01f) & 0x7F);
|
|
data[i++] = (byte)((FlexiGravity + 10.0f) * 10.01f);
|
|
data[i++] = (byte)(FlexiWind * 10.01f);
|
|
LLVector3 lForce = new LLVector3(FlexiForceX, FlexiForceY, FlexiForceZ);
|
|
lForce.GetBytes().CopyTo(data, i);
|
|
|
|
return data;
|
|
}
|
|
public void ReadLightData(byte[] data, int pos)
|
|
{
|
|
if (data.Length - pos >= 16)
|
|
{
|
|
LightEntry = true;
|
|
LLColor lColor = new LLColor(data, pos, false);
|
|
LightIntensity = lColor.A;
|
|
LightColorA = 1f;
|
|
LightColorR = lColor.R;
|
|
LightColorG = lColor.G;
|
|
LightColorB = lColor.B;
|
|
|
|
LightRadius = Helpers.BytesToFloat(data, pos + 4);
|
|
LightCutoff = Helpers.BytesToFloat(data, pos + 8);
|
|
LightFalloff = Helpers.BytesToFloat(data, pos + 12);
|
|
}
|
|
else
|
|
{
|
|
LightEntry = false;
|
|
LightColorA = 1f;
|
|
LightColorR = 0f;
|
|
LightColorG = 0f;
|
|
LightColorB = 0f;
|
|
LightRadius = 0f;
|
|
LightCutoff = 0f;
|
|
LightFalloff = 0f;
|
|
LightIntensity = 0f;
|
|
}
|
|
}
|
|
public byte[] GetLightBytes()
|
|
{
|
|
byte[] data = new byte[16];
|
|
|
|
// Alpha channel in color is intensity
|
|
LLColor tmpColor = new LLColor(LightColorR,LightColorG,LightColorB,LightIntensity);
|
|
|
|
tmpColor.GetBytes().CopyTo(data, 0);
|
|
Helpers.FloatToBytes(LightRadius).CopyTo(data, 4);
|
|
Helpers.FloatToBytes(LightCutoff).CopyTo(data, 8);
|
|
Helpers.FloatToBytes(LightFalloff).CopyTo(data, 12);
|
|
|
|
return data;
|
|
}
|
|
}
|
|
} |