diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000..2cfaa256
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,34 @@
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+ schedule:
+ - cron: '40 14 * * 6'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'csharp' ]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: ${{ matrix.language }}
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index e4301fef..97283b77 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -3,6 +3,7 @@ name: .NET
on:
push:
branches: [ develop ]
+
pull_request:
branches: [ develop ]
@@ -12,14 +13,40 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
+
- name: Setup .NET
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
- dotnet-version: 5.0.x
+ dotnet-version: 6.0.x
+
- name: Restore dependencies
run: dotnet restore
+
- name: Build
- run: dotnet build --no-restore
+ run: dotnet build --no-restore -p:Configuration=Release
+
- name: Test
- run: dotnet test --no-build --verbosity normal
+ run: dotnet test --no-restore --no-build --verbosity normal
+
+ - name: Bump version and push tag
+ id: tag_version
+ uses: mathieudutour/github-tag-action@v6.1
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Pack
+ run: dotnet pack -p:Configuration=Release NGC.LibOpenMetaverse
+
+ - name: Publish Package
+ run: dotnet nuget push build/Release/*.nupkg --source https://nuget.pkg.github.com/OpenSim-NGC/index.json
+
+ - name: Create Release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ steps.bump_version.outputs.new_tag }}
+ release_name: Release ${{ github.ref }}
+ body: ${{ steps.tag_version.outputs.changelog }}
+
diff --git a/CSJ2K/CSJ2K.csproj b/CSJ2K/CSJ2K.csproj
index 19099d30..2defd4bf 100644
--- a/CSJ2K/CSJ2K.csproj
+++ b/CSJ2K/CSJ2K.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
CSJ2K
CSJ2K
JPEG2000 decoding library
diff --git a/Directory.Build.props b/Directory.Build.props
index 5614607e..8ac8092e 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,15 +1,17 @@
+
- 0.10.0.0
OpenMetaverse
Utopa Skye LLC, OpenMetaverse Developers
Utopia Skye LLC
-
+ 1.3.1
+ 1.3.1
+ 1.3.1
+ 1.3.1
+
+
- 1.1.8
- 1.1.7
- 1.1.7
- 1.1.7
+ LibOpenMetaverse is an OpenSim Core compatible Open Metaverse support library
BSD-3-Clause
https://github.com/OpenSim-NGC/libopenmetaverse
false
@@ -17,5 +19,13 @@
https://github.com/OpenSim-NGC/libopenmetaverse.git
git
master
+ true
+
+
+
+ $(SolutionDir)\obj\$(Configuration)\$(MSBuildProjectName)\
+ $(SolutionDir)\obj\$(Configuration)\$(MSBuildProjectName)\
+ $(SolutionDir)\build\$(Configuration)\$(AssemblyName)\
+ $(OutputPath)
diff --git a/LICENSE.txt b/LICENSE.txt
index 43b484b2..426f81ff 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,7 @@
+ Copyright (c) Opensimulator, http://opensimulator.org/
+ All rights reserved.
+
Copyright (c) 2006-2016, openmetaverse.co
All rights reserved.
diff --git a/OpenMetaverse.GUI/AvatarList.cs b/OpenMetaverse.GUI/AvatarList.cs
index 0276b7c0..b29d5f0e 100644
--- a/OpenMetaverse.GUI/AvatarList.cs
+++ b/OpenMetaverse.GUI/AvatarList.cs
@@ -97,10 +97,10 @@ public AvatarList()
this.ListViewItemSorter = _ColumnSorter;
EventHandler clickHandler = new EventHandler(defaultMenuItem_Click);
- this.ContextMenu = new ContextMenu();
- this.ContextMenu.MenuItems.Add("Offer Teleport", clickHandler);
- this.ContextMenu.MenuItems.Add("Teleport To", clickHandler);
- this.ContextMenu.MenuItems.Add("Walk To", clickHandler);
+ this.ContextMenuStrip = new ContextMenuStrip();
+ this.ContextMenuStrip.Items.Add("Offer Teleport", null, clickHandler);
+ this.ContextMenuStrip.Items.Add("Teleport To", null, clickHandler);
+ this.ContextMenuStrip.Items.Add("Walk To", null, clickHandler);
this.DoubleBuffered = true;
this.ListViewItemSorter = _ColumnSorter;
@@ -360,7 +360,7 @@ private void UpdateCoarseInfo(Simulator sim, List newEntries, List r
private void defaultMenuItem_Click(object sender, EventArgs e)
{
- MenuItem menuItem = (MenuItem)sender;
+ ToolStripItem menuItem = (ToolStripItem)sender;
switch (menuItem.Text)
{
diff --git a/OpenMetaverse.GUI/InventoryTree.cs b/OpenMetaverse.GUI/InventoryTree.cs
index 12e1352d..bea7c58d 100644
--- a/OpenMetaverse.GUI/InventoryTree.cs
+++ b/OpenMetaverse.GUI/InventoryTree.cs
@@ -38,13 +38,13 @@ namespace OpenMetaverse.GUI
public class InventoryTree : TreeView
{
private GridClient _Client;
- private ContextMenu _ContextMenu;
+ private ContextMenuStrip _ContextMenu;
private UUID _SelectedItemID;
///
/// Gets or sets the context menu associated with this control
///
- public ContextMenu Menu
+ public ContextMenuStrip Menu
{
get { return _ContextMenu; }
set { _ContextMenu = value; }
@@ -65,9 +65,9 @@ public GridClient Client
public InventoryTree()
{
EventHandler clickHandler = new EventHandler(defaultMenuItem_Click);
- _ContextMenu = new ContextMenu();
- _ContextMenu.MenuItems.Add("Wear", clickHandler);
- _ContextMenu.MenuItems.Add("Detach", clickHandler);
+ _ContextMenu = new ContextMenuStrip();
+ _ContextMenu.Items.Add("Wear", null, clickHandler);
+ _ContextMenu.Items.Add("Detach", null, clickHandler);
this.NodeMouseClick += new TreeNodeMouseClickEventHandler(InventoryTree_NodeMouseClick);
this.BeforeExpand += new TreeViewCancelEventHandler(InventoryTree_BeforeExpand);
@@ -172,7 +172,7 @@ private void InitializeClient(GridClient client)
private void defaultMenuItem_Click(object sender, EventArgs e)
{
- MenuItem menuItem = (MenuItem)sender;
+ ToolStripItem menuItem = (ToolStripItem)sender;
InventoryItem item = (InventoryItem)Client.Inventory.Store[_SelectedItemID];
diff --git a/OpenMetaverse.GUI/OpenMetaverse.GUI.csproj b/OpenMetaverse.GUI/OpenMetaverse.GUI.csproj
index ca293378..2f56293c 100644
--- a/OpenMetaverse.GUI/OpenMetaverse.GUI.csproj
+++ b/OpenMetaverse.GUI/OpenMetaverse.GUI.csproj
@@ -1,18 +1,14 @@
Local
- net48
+ net6.0-windows
+ true
1591,1574,0419,0618
True
-
-
- False
-
-
diff --git a/OpenMetaverse.PrimMesher/OpenMetaverse.PrimMesher.csproj b/OpenMetaverse.PrimMesher/OpenMetaverse.PrimMesher.csproj
index e5e844ae..0097f7e7 100644
--- a/OpenMetaverse.PrimMesher/OpenMetaverse.PrimMesher.csproj
+++ b/OpenMetaverse.PrimMesher/OpenMetaverse.PrimMesher.csproj
@@ -1,6 +1,6 @@
- net48
+ net6.0
Dhalia Trimble, OpenSim Contributors, Cinder Roxley
OpenMetaverse.PrimMesher
OpenMetaverse.PrimMesher
@@ -15,6 +15,6 @@
TRACE;VERTEX_INDEXER
-
+
\ No newline at end of file
diff --git a/OpenMetaverse.Rendering.Meshmerizer/OpenMetaverse.Rendering.Meshmerizer.csproj b/OpenMetaverse.Rendering.Meshmerizer/OpenMetaverse.Rendering.Meshmerizer.csproj
index ef3a8ebe..02cdadad 100644
--- a/OpenMetaverse.Rendering.Meshmerizer/OpenMetaverse.Rendering.Meshmerizer.csproj
+++ b/OpenMetaverse.Rendering.Meshmerizer/OpenMetaverse.Rendering.Meshmerizer.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
True
1591,1574,0419,0618
true
diff --git a/OpenMetaverse.Rendering.Simple/OpenMetaverse.Rendering.Simple.csproj b/OpenMetaverse.Rendering.Simple/OpenMetaverse.Rendering.Simple.csproj
index 690861d8..794c4f26 100644
--- a/OpenMetaverse.Rendering.Simple/OpenMetaverse.Rendering.Simple.csproj
+++ b/OpenMetaverse.Rendering.Simple/OpenMetaverse.Rendering.Simple.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
True
1591,1574,0419,0618
true
diff --git a/OpenMetaverse.StructuredData/JSON/OSDJson.cs b/OpenMetaverse.StructuredData/JSON/OSDJson.cs
index 6205e2d9..5390a494 100644
--- a/OpenMetaverse.StructuredData/JSON/OSDJson.cs
+++ b/OpenMetaverse.StructuredData/JSON/OSDJson.cs
@@ -6,8 +6,6 @@
using System.Globalization;
using System.IO;
using System.Text;
-using LitJson;
-using OpenMetaverse;
namespace OpenMetaverse.StructuredData
{
diff --git a/OpenMetaverse.StructuredData/LLSD/NotationLLSD.cs b/OpenMetaverse.StructuredData/LLSD/NotationLLSD.cs
index 17c70f0e..9454c2e1 100644
--- a/OpenMetaverse.StructuredData/LLSD/NotationLLSD.cs
+++ b/OpenMetaverse.StructuredData/LLSD/NotationLLSD.cs
@@ -232,7 +232,7 @@ private static OSD DeserializeLLSDNotationElement(TextReader reader)
if (reader.Read(uuidBuf, 0, 36) < 36)
throw new OSDException("Notation LLSD parsing: Unexpected end of stream in UUID.");
UUID lluuid;
- if (!UUID.TryParse(new String(uuidBuf), out lluuid))
+ if (!UUID.TryParse(new String(uuidBuf).AsSpan(), out lluuid))
throw new OSDException("Notation LLSD parsing: Invalid UUID discovered.");
osd = OSD.FromUUID(lluuid);
break;
diff --git a/OpenMetaverse.StructuredData/LLSD/XmlLLSD.cs b/OpenMetaverse.StructuredData/LLSD/XmlLLSD.cs
index 6c875442..a4bcf099 100644
--- a/OpenMetaverse.StructuredData/LLSD/XmlLLSD.cs
+++ b/OpenMetaverse.StructuredData/LLSD/XmlLLSD.cs
@@ -265,7 +265,7 @@ public static void EscapeToXML(string s, StringBuilder sb)
case '"':
sb.Append(""");
break;
- case '\\':
+ case '\'':
sb.Append("'");
break;
default:
@@ -295,7 +295,7 @@ public static void EscapeASCIIToXML(osUTF8 ms, string s)
case '"':
ms.Append(osUTF8Const.XMLamp_quot);
break;
- case '\\':
+ case '\'':
ms.Append(osUTF8Const.XMLamp_apos);
break;
default:
@@ -325,7 +325,7 @@ public static void EscapeToXML(osUTF8 ms, string s)
case '"':
ms.Append(osUTF8Const.XMLamp_quot);
break;
- case '\\':
+ case '\'':
ms.Append(osUTF8Const.XMLamp_apos);
break;
default:
@@ -355,7 +355,7 @@ public static void EscapeToXML(osUTF8 ms, osUTF8 s)
case (byte)'"':
ms.Append(osUTF8Const.XMLamp_quot);
break;
- case (byte)'\\':
+ case (byte)'\'':
ms.Append(osUTF8Const.XMLamp_apos);
break;
default:
@@ -636,8 +636,7 @@ private static OSD ParseLLSDXmlElement(XmlTextReader reader)
if (reader.Read())
{
- int value = 0;
- Int32.TryParse(reader.ReadString().Trim(), out value);
+ Int32.TryParse(reader.ReadString().Trim(), out int value);
ret = OSD.FromInteger(value);
break;
}
@@ -653,7 +652,7 @@ private static OSD ParseLLSDXmlElement(XmlTextReader reader)
if (reader.Read())
{
- double value = 0d;
+ double value;
string str = reader.ReadString().Trim().ToLower();
if (str == "nan")
@@ -676,8 +675,7 @@ private static OSD ParseLLSDXmlElement(XmlTextReader reader)
if (reader.Read())
{
- UUID value = UUID.Zero;
- UUID.TryParse(reader.ReadString().Trim(), out value);
+ UUID.TryParse(reader.ReadString().AsSpan(), out UUID value);
ret = OSD.FromUUID(value);
break;
}
@@ -693,12 +691,12 @@ private static OSD ParseLLSDXmlElement(XmlTextReader reader)
if (reader.Read())
{
- DateTime value = Utils.Epoch;
- DateTime.TryParse(reader.ReadString().Trim(), out value);
- ret = OSD.FromDate(value);
+ if(DateTime.TryParse(reader.ReadString().Trim(), out DateTime value))
+ ret = OSD.FromDate(value);
+ else
+ ret = OSD.FromDate(Utils.Epoch);
break;
}
-
ret = OSD.FromDate(Utils.Epoch);
break;
case "string":
diff --git a/OpenMetaverse.StructuredData/OpenMetaverse.StructuredData.csproj b/OpenMetaverse.StructuredData/OpenMetaverse.StructuredData.csproj
index ceb92dee..9e1770a4 100644
--- a/OpenMetaverse.StructuredData/OpenMetaverse.StructuredData.csproj
+++ b/OpenMetaverse.StructuredData/OpenMetaverse.StructuredData.csproj
@@ -1,7 +1,7 @@
Local
- net48;netstandard2.0
+ net6.0
1591,1574,0419,0618
true
true
@@ -12,4 +12,4 @@
-
\ No newline at end of file
+
diff --git a/OpenMetaverse.StructuredData/StructuredData.cs b/OpenMetaverse.StructuredData/StructuredData.cs
index 9015198b..549ea050 100644
--- a/OpenMetaverse.StructuredData/StructuredData.cs
+++ b/OpenMetaverse.StructuredData/StructuredData.cs
@@ -30,6 +30,7 @@
using System.IO;
using System.Reflection;
using System.Text;
+using System.Runtime.CompilerServices;
namespace OpenMetaverse.StructuredData
{
@@ -102,14 +103,13 @@ public virtual bool AsBoolean()
double d = ((OSDReal)this).value;
return (!Double.IsNaN(d) && d != 0);
case OSDType.String:
- string s = ((OSDString)this).value;
- if (String.IsNullOrEmpty(s))
- return false;
- if (s == "0" || s.ToLower() == "false")
+ if (string.IsNullOrEmpty(((OSDString)this).value) ||
+ ((OSDString)this).value.Equals("0") ||
+ ((OSDString)this).value.Equals("false", StringComparison.InvariantCultureIgnoreCase))
return false;
return true;
case OSDType.UUID:
- return (((OSDUUID)this).value.IsZero()) ? false : true;
+ return ((OSDUUID)this).value.IsNotZero();
case OSDType.Map:
return ((OSDMap)this).dicvalue.Count > 0;
case OSDType.Array:
@@ -145,16 +145,13 @@ public virtual int AsInteger()
return Int32.MinValue;
return (int)Math.Round(v);
case OSDType.String:
- string s = ((OSDString)this).value;
- double dbl;
- if (Double.TryParse(s, out dbl))
+ if (Double.TryParse(((OSDString)this).value.AsSpan(), out double dbl))
return (int)Math.Floor(dbl);
else
return 0;
case OSDType.OSDUTF8:
- string us = ((OSDUTF8)this).value.ToString();
- double udbl;
- if (Double.TryParse(us, out udbl))
+ var us = ((OSDUTF8)this).value.ToString().AsSpan();
+ if (Double.TryParse(us, out double udbl))
return (int)Math.Floor(udbl);
else
return 0;
@@ -167,10 +164,12 @@ public virtual int AsInteger()
List l = ((OSDArray)this).value;
if (l.Count < 4)
return 0;
- byte[] by = new byte[4];
- for (int i = 0; i < 4; i++)
- by[i] = (byte)l[i].AsInteger();
- return (by[0] << 24) | (by[1] << 16) | (by[2] << 8) | by[3];
+ return
+ (byte)l[0].AsInteger() << 24 |
+ (byte)l[1].AsInteger() << 16 |
+ (byte)l[2].AsInteger() << 8 |
+ (byte)l[3].AsInteger();
+
case OSDType.Date:
return (int)Utils.DateTimeToUnixTime(((OSDDate)this).value);
default:
@@ -196,16 +195,12 @@ public virtual uint AsUInteger()
return UInt32.MinValue;
return (uint)Math.Round(v);
case OSDType.String:
- string s = ((OSDString)this).value;
- double dbl;
- if (Double.TryParse(s, out dbl))
+ if (Double.TryParse(((OSDString)this).value.AsSpan(), out double dbl))
return (uint)Math.Floor(dbl);
else
return 0;
case OSDType.OSDUTF8:
- string us = ((OSDUTF8)this).value.ToString();
- double udbl;
- if (Double.TryParse(us, out udbl))
+ if (Double.TryParse(((OSDUTF8)this).value.ToString().AsSpan(), out double udbl))
return (uint)Math.Floor(udbl);
else
return 0;
@@ -221,10 +216,11 @@ public virtual uint AsUInteger()
List l = ((OSDArray)this).value;
if (l.Count < 4)
return 0;
- byte[] by = new byte[4];
- for (int i = 0; i < 4; i++)
- by[i] = (byte)l[i].AsInteger();
- return (uint)((by[0] << 24) | (by[1] << 16) | (by[2] << 8) | by[3]);
+ return (
+ ((uint)(byte)l[0].AsInteger() << 24) |
+ ((uint)(byte)l[1].AsInteger() << 16) |
+ ((uint)(byte)l[2].AsInteger() << 8) |
+ (byte)l[3].AsInteger());
default:
return 0;
}
@@ -248,16 +244,13 @@ public virtual long AsLong()
return Int64.MinValue;
return (long)Math.Round(v);
case OSDType.String:
- string s = ((OSDString)this).value;
- double dbl;
- if (Double.TryParse(s, out dbl))
+ if (Double.TryParse(((OSDString)this).value, out double dbl))
return (long)Math.Floor(dbl);
else
return 0;
case OSDType.OSDUTF8:
- string us = ((OSDUTF8)this).value.ToString();
- double udbl;
- if (Double.TryParse(us, out udbl))
+ var us = ((OSDUTF8)this).value.ToString().AsSpan();
+ if (Double.TryParse(us, out double udbl))
return (long)Math.Floor(udbl);
else
return 0;
@@ -283,18 +276,15 @@ public virtual long AsLong()
List l = ((OSDArray)this).value;
if (l.Count < 8)
return 0;
- byte[] b = new byte[8];
- for (int i = 0; i < 8; i++)
- b[i] = (byte)l[i].AsInteger();
- return (
- ((long)b[0] << 56) |
- ((long)b[1] << 48) |
- ((long)b[2] << 40) |
- ((long)b[3] << 32) |
- ((long)b[4] << 24) |
- ((long)b[5] << 16) |
- ((long)b[6] << 8) |
- b[7]);
+ return
+ ((long)(byte)l[0].AsInteger() << 56) |
+ ((long)(byte)l[1].AsInteger() << 48) |
+ ((long)(byte)l[2].AsInteger() << 40) |
+ ((long)(byte)l[3].AsInteger() << 32) |
+ ((long)(byte)l[4].AsInteger() << 24) |
+ ((long)(byte)l[5].AsInteger() << 16) |
+ ((long)(byte)l[6].AsInteger() << 8) |
+ (byte)l[7].AsInteger();
}
default:
return 0;
@@ -319,16 +309,12 @@ public virtual ulong AsULong()
return UInt64.MinValue;
return (ulong)Math.Round(v);
case OSDType.String:
- string s = ((OSDString)this).value;
- double dbl;
- if (Double.TryParse(s, out dbl))
+ if (Double.TryParse(((OSDString)this).value.AsSpan(), out double dbl))
return (ulong)Math.Floor(dbl);
else
return 0;
case OSDType.OSDUTF8:
- string us = ((OSDUTF8)this).value.ToString();
- double udbl;
- if (Double.TryParse(us, out udbl))
+ if (Double.TryParse(((OSDUTF8)this).value.ToString().AsSpan(), out double udbl))
return (ulong)Math.Floor(udbl);
else
return 0;
@@ -354,18 +340,15 @@ public virtual ulong AsULong()
List l = ((OSDArray)this).value;
if (l.Count < 8)
return 0;
- byte[] b = new byte[8];
- for (int i = 0; i < 8; i++)
- b[i] = (byte)l[i].AsInteger();
return (
- ((ulong)b[0] << 56) |
- ((ulong)b[1] << 48) |
- ((ulong)b[2] << 40) |
- ((ulong)b[3] << 32) |
- ((ulong)b[4] << 24) |
- ((ulong)b[5] << 16) |
- ((ulong)b[6] << 8) |
- b[7]);
+ ((ulong)(byte)l[0].AsInteger() << 56) |
+ ((ulong)(byte)l[1].AsInteger() << 48) |
+ ((ulong)(byte)l[2].AsInteger() << 40) |
+ ((ulong)(byte)l[3].AsInteger() << 32) |
+ ((ulong)(byte)l[4].AsInteger() << 24) |
+ ((ulong)(byte)l[5].AsInteger() << 16) |
+ ((ulong)(byte)l[6].AsInteger() << 8) |
+ (byte)l[7].AsInteger());
}
default:
return 0;
@@ -383,16 +366,12 @@ public virtual double AsReal()
case OSDType.Real:
return ((OSDReal)this).value;
case OSDType.String:
- string s = ((OSDString)this).value;
- double dbl;
- if (Double.TryParse(s, out dbl))
+ if (Double.TryParse(((OSDString)this).value.AsSpan(), out double dbl))
return dbl;
else
return 0;
case OSDType.OSDUTF8:
- string us = ((OSDUTF8)this).value.ToString();
- double udbl;
- if (Double.TryParse(us, out udbl))
+ if (Double.TryParse(((OSDUTF8)this).value.ToString().AsSpan(), out double udbl))
return udbl;
else
return 0;
@@ -449,14 +428,13 @@ public virtual UUID AsUUID()
switch (Type)
{
case OSDType.String:
- UUID uuid;
- if (UUID.TryParse(((OSDString)this).value, out uuid))
+ if (UUID.TryParse(((OSDString)this).value.AsSpan(), out UUID uuid))
return uuid;
else
return UUID.Zero;
case OSDType.OSDUTF8:
UUID ouuid;
- if (UUID.TryParse(((OSDUTF8)this).value.ToString(), out ouuid))
+ if (UUID.TryParse(((OSDUTF8)this).value.ToString().AsSpan(), out ouuid))
return ouuid;
else
return UUID.Zero;
@@ -577,19 +555,19 @@ public Vector3 AsVector3()
switch (Type)
{
case OSDType.String:
- return Vector3.Parse(((OSDString)this).value);
+ return Vector3.Parse(((OSDString)this).value.AsSpan());
case OSDType.OSDUTF8:
- return Vector3.Parse(((OSDUTF8)this).value.ToString());
+ return Vector3.Parse(((OSDUTF8)this).value.ToString().AsSpan());
case OSDType.Array:
List l = ((OSDArray)this).value;
- Vector3 vector = Vector3.Zero;
if (l.Count == 3)
{
- vector.X = (float)l[0].AsReal();
- vector.Y = (float)l[1].AsReal();
- vector.Z = (float)l[2].AsReal();
+ return new Vector3(
+ (float)l[0].AsReal(),
+ (float)l[1].AsReal(),
+ (float)l[2].AsReal());
}
- return vector;
+ return Vector3.Zero;
default:
return Vector3.Zero;
}
@@ -600,9 +578,9 @@ public Vector3d AsVector3d()
switch (Type)
{
case OSDType.String:
- return Vector3d.Parse(((OSDString)this).value);
+ return Vector3d.Parse(((OSDString)this).value.AsSpan());
case OSDType.OSDUTF8:
- return Vector3d.Parse(((OSDUTF8)this).value.ToString());
+ return Vector3d.Parse(((OSDUTF8)this).value.ToString().AsSpan());
case OSDType.Array:
List l = ((OSDArray)this).value;
Vector3d vector = Vector3d.Zero;
@@ -690,35 +668,22 @@ public virtual void Clear() { }
public virtual OSD Copy()
{
- switch (Type)
+ return Type switch
{
- case OSDType.Boolean:
- return new OSDBoolean(((OSDBoolean)this).value);
- case OSDType.Integer:
- return new OSDInteger(((OSDInteger)this).value);
- case OSDType.Real:
- return new OSDReal(((OSDReal)this).value);
- case OSDType.String:
- return new OSDString(((OSDString)this).value);
- case OSDType.OSDUTF8:
- return new OSDUTF8(((OSDUTF8)this).value);
- case OSDType.UUID:
- return new OSDUUID(((OSDUUID)this).value);
- case OSDType.Date:
- return new OSDDate(((OSDDate)this).value);
- case OSDType.URI:
- return new OSDUri(((OSDUri)this).value);
- case OSDType.Binary:
- return new OSDBinary(((OSDBinary)this).value);
- case OSDType.Map:
- return new OSDMap(((OSDMap)this).dicvalue);
- case OSDType.Array:
- return new OSDArray(((OSDArray)this).value);
- case OSDType.LLSDxml:
- return new OSDBoolean(((OSDBoolean)this).value);
- default:
- return new OSD();
- }
+ OSDType.Boolean => new OSDBoolean(((OSDBoolean)this).value),
+ OSDType.Integer => new OSDInteger(((OSDInteger)this).value),
+ OSDType.Real => new OSDReal(((OSDReal)this).value),
+ OSDType.String => new OSDString(((OSDString)this).value),
+ OSDType.OSDUTF8 => new OSDUTF8(((OSDUTF8)this).value),
+ OSDType.UUID => new OSDUUID(((OSDUUID)this).value),
+ OSDType.Date => new OSDDate(((OSDDate)this).value),
+ OSDType.URI => new OSDUri(((OSDUri)this).value),
+ OSDType.Binary => new OSDBinary(((OSDBinary)this).value),
+ OSDType.Map => new OSDMap(((OSDMap)this).dicvalue),
+ OSDType.Array => new OSDArray(((OSDArray)this).value),
+ OSDType.LLSDxml => new OSDBoolean(((OSDBoolean)this).value),
+ _ => new OSD(),
+ };
}
public override string ToString()
@@ -765,106 +730,109 @@ public override string ToString()
return "undef";
}
}
-
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromBoolean(bool value) { return new OSDBoolean(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromInteger(int value) { return new OSDInteger(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromInteger(uint value) { return new OSDInteger((int)value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromInteger(short value) { return new OSDInteger((int)value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromInteger(ushort value) { return new OSDInteger((int)value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromInteger(sbyte value) { return new OSDInteger((int)value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromInteger(byte value) { return new OSDInteger((int)value); }
- public static OSD FromUInteger(uint value) { return new OSDBinary(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)] public static OSD FromUInteger(uint value) { return new OSDBinary(value); }
public static OSD FromLong(long value) { return new OSDBinary(value); }
- public static OSD FromULong(ulong value) { return new OSDBinary(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)] public static OSD FromULong(ulong value) { return new OSDBinary(value); }
public static OSD FromReal(double value) { return new OSDReal(value); }
- public static OSD FromReal(float value) { return new OSDReal((double)value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)] public static OSD FromReal(float value) { return new OSDReal((double)value); }
public static OSD FromString(string value) { return new OSDString(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromUUID(UUID value) { return new OSDUUID(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromDate(DateTime value) { return new OSDDate(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromUri(Uri value) { return new OSDUri(value); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromBinary(byte[] value) { return new OSDBinary(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromVector2(Vector2 value)
{
- OSDArray array = new OSDArray();
- array.Add(OSD.FromReal(value.X));
- array.Add(OSD.FromReal(value.Y));
- return array;
+ return new OSDArray() { OSD.FromReal(value.X), OSD.FromReal(value.Y) };
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromVector3(Vector3 value)
{
- OSDArray array = new OSDArray();
- array.Add(OSD.FromReal(value.X));
- array.Add(OSD.FromReal(value.Y));
- array.Add(OSD.FromReal(value.Z));
- return array;
+ return new OSDArray() { OSD.FromReal(value.X), OSD.FromReal(value.Y), OSD.FromReal(value.Z) };
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromVector3d(Vector3d value)
{
- OSDArray array = new OSDArray();
- array.Add(OSD.FromReal(value.X));
- array.Add(OSD.FromReal(value.Y));
- array.Add(OSD.FromReal(value.Z));
- return array;
+ return new OSDArray() { OSD.FromReal(value.X), OSD.FromReal(value.Y), OSD.FromReal(value.Z) };
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromVector4(Vector4 value)
{
- OSDArray array = new OSDArray();
- array.Add(OSD.FromReal(value.X));
- array.Add(OSD.FromReal(value.Y));
- array.Add(OSD.FromReal(value.Z));
- array.Add(OSD.FromReal(value.W));
- return array;
+ return new OSDArray() { OSD.FromReal(value.X), OSD.FromReal(value.Y), OSD.FromReal(value.Z), OSD.FromReal(value.W) };
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromQuaternion(Quaternion value)
{
- OSDArray array = new OSDArray();
- array.Add(OSD.FromReal(value.X));
- array.Add(OSD.FromReal(value.Y));
- array.Add(OSD.FromReal(value.Z));
- array.Add(OSD.FromReal(value.W));
- return array;
+ return new OSDArray() { OSD.FromReal(value.X), OSD.FromReal(value.Y), OSD.FromReal(value.Z), OSD.FromReal(value.W) };
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static OSD FromColor4(Color4 value)
{
- OSDArray array = new OSDArray();
- array.Add(OSD.FromReal(value.R));
- array.Add(OSD.FromReal(value.G));
- array.Add(OSD.FromReal(value.B));
- array.Add(OSD.FromReal(value.A));
- return array;
+ return new OSDArray() { OSD.FromReal(value.R), OSD.FromReal(value.G), OSD.FromReal(value.B), OSD.FromReal(value.A) };
}
public static OSD FromObject(object value)
{
if (value == null) { return new OSD(); }
- else if (value is bool) { return new OSDBoolean((bool)value); }
- else if (value is int) { return new OSDInteger((int)value); }
- else if (value is uint) { return new OSDBinary((uint)value); }
- else if (value is short) { return new OSDInteger((int)(short)value); }
- else if (value is ushort) { return new OSDInteger((int)(ushort)value); }
- else if (value is sbyte) { return new OSDInteger((int)(sbyte)value); }
- else if (value is byte) { return new OSDInteger((int)(byte)value); }
- else if (value is double) { return new OSDReal((double)value); }
- else if (value is float) { return new OSDReal((double)(float)value); }
- else if (value is string) { return new OSDString((string)value); }
- else if (value is UUID) { return new OSDUUID((UUID)value); }
- else if (value is DateTime) { return new OSDDate((DateTime)value); }
- else if (value is Uri) { return new OSDUri((Uri)value); }
- else if (value is byte[]) { return new OSDBinary((byte[])value); }
- else if (value is long) { return new OSDBinary((long)value); }
- else if (value is ulong) { return new OSDBinary((ulong)value); }
- else if (value is Vector2) { return FromVector2((Vector2)value); }
- else if (value is Vector3) { return FromVector3((Vector3)value); }
- else if (value is Vector3d) { return FromVector3d((Vector3d)value); }
- else if (value is Vector4) { return FromVector4((Vector4)value); }
- else if (value is Quaternion) { return FromQuaternion((Quaternion)value); }
- else if (value is Color4) { return FromColor4((Color4)value); }
+ else if (value is bool bv) { return new OSDBoolean(bv); }
+ else if (value is int iv) { return new OSDInteger(iv); }
+ else if (value is uint uiv) { return new OSDBinary(uiv); }
+ else if (value is short sv) { return new OSDInteger((int)sv); }
+ else if (value is ushort usv) { return new OSDInteger((int)usv); }
+ else if (value is sbyte sbv) { return new OSDInteger((int)sbv); }
+ else if (value is byte btv) { return new OSDInteger((int)btv); }
+ else if (value is double dv) { return new OSDReal(dv); }
+ else if (value is float fv) { return new OSDReal((double)fv); }
+ else if (value is string stv) { return new OSDString(stv); }
+ else if (value is UUID uidv) { return new OSDUUID(uidv); }
+ else if (value is DateTime dtmv) { return new OSDDate(dtmv); }
+ else if (value is Uri uriv) { return new OSDUri(uriv); }
+ else if (value is byte[] btav) { return new OSDBinary(btav); }
+ else if (value is long lv) { return new OSDBinary(lv); }
+ else if (value is ulong ulv) { return new OSDBinary(ulv); }
+ else if (value is Vector2 v2v) { return FromVector2(v2v); }
+ else if (value is Vector3 v3v) { return FromVector3(v3v); }
+ else if (value is Vector3d v3dv) { return FromVector3d(v3dv); }
+ else if (value is Vector4 v4v) { return FromVector4(v4v); }
+ else if (value is Quaternion qv) { return FromQuaternion(qv); }
+ else if (value is Color4 c4v) { return FromColor4(c4v); }
else return new OSD();
}
@@ -953,14 +921,14 @@ public static object ToObject(Type type, OSD value)
}
else if (type == typeof(OSDArray))
{
- OSDArray newArray = new OSDArray();
+ OSDArray newArray = new();
foreach (OSD o in (OSDArray)value)
newArray.Add(o);
return newArray;
}
else if (type == typeof(OSDMap))
{
- OSDMap newMap = new OSDMap();
+ OSDMap newMap = new();
foreach (KeyValuePair o in (OSDMap)value)
newMap.Add(o);
return newMap;
@@ -973,46 +941,86 @@ public static object ToObject(Type type, OSD value)
#region Implicit Conversions
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(bool value) { return new OSDBoolean(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(int value) { return new OSDInteger(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(uint value) { return new OSDInteger((int)value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(short value) { return new OSDInteger((int)value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(ushort value) { return new OSDInteger((int)value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(sbyte value) { return new OSDInteger((int)value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(byte value) { return new OSDInteger((int)value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(long value) { return new OSDBinary(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(ulong value) { return new OSDBinary(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(double value) { return new OSDReal(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(float value) { return new OSDReal(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(string value) { return new OSDString(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(UUID value) { return new OSDUUID(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(DateTime value) { return new OSDDate(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Uri value) { return new OSDUri(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(byte[] value) { return new OSDBinary(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Vector2 value) { return OSD.FromVector2(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Vector3 value) { return OSD.FromVector3(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Vector3d value) { return OSD.FromVector3d(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Vector4 value) { return OSD.FromVector4(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Quaternion value) { return OSD.FromQuaternion(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator OSD(Color4 value) { return OSD.FromColor4(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator bool(OSD value) { return value.AsBoolean(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator int(OSD value) { return value.AsInteger(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator uint(OSD value) { return value.AsUInteger(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator long(OSD value) { return value.AsLong(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ulong(OSD value) { return value.AsULong(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator double(OSD value) { return value.AsReal(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator float(OSD value) { return (float)value.AsReal(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator string(OSD value) { return value.AsString(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator UUID(OSD value) { return value.AsUUID(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator DateTime(OSD value) { return value.AsDate(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Uri(OSD value) { return value.AsUri(); }
- public static implicit operator byte[](OSD value) { return value.AsBinary(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector2(OSD value) { return value.AsVector2(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator byte[](OSD value) { return value.AsBinary(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector3(OSD value) { return value.AsVector3(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector3d(OSD value) { return value.AsVector3d(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector4(OSD value) { return value.AsVector4(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Quaternion(OSD value) { return value.AsQuaternion(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Color4(OSD value) { return value.AsColor4(); }
#endregion Implicit Conversions
@@ -1029,7 +1037,7 @@ public static OSDMap SerializeMembers(object obj)
Type t = obj.GetType();
FieldInfo[] fields = t.GetFields();
- OSDMap map = new OSDMap(fields.Length);
+ OSDMap map = new(fields.Length);
for (int i = 0; i < fields.Length; i++)
{
@@ -1064,8 +1072,7 @@ public static void DeserializeMembers(ref object obj, OSDMap serialized)
FieldInfo field = fields[i];
if (!Attribute.IsDefined(field, typeof(NonSerializedAttribute)))
{
- OSD serializedField;
- if (serialized.TryGetValue(field.Name, out serializedField))
+ if (serialized.TryGetValue(field.Name, out OSD serializedField))
field.SetValue(obj, ToObject(field.FieldType, serializedField));
}
}
@@ -1085,12 +1092,19 @@ public OSDBoolean(bool value)
this.value = value;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool AsBoolean() { return value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int AsInteger() { return value ? 1 : 0; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override double AsReal() { return value ? 1d : 0d; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string AsString() { return value ? "1" : "0"; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override byte[] AsBinary() { return value ? trueBinary : falseBinary; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override OSD Copy() { return new OSDBoolean(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() { return AsString(); }
}
@@ -1107,15 +1121,25 @@ public OSDInteger(int value)
this.value = value;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool AsBoolean() { return value != 0; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int AsInteger() { return value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override uint AsUInteger() { return (uint)value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override long AsLong() { return value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override ulong AsULong() { return (ulong)value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override double AsReal() { return (double)value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string AsString() { return value.ToString(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override byte[] AsBinary() { return Utils.IntToBytesBig(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override OSD Copy() { return new OSDInteger(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() { return AsString(); }
}
@@ -1178,10 +1202,14 @@ public override ulong AsULong()
return (ulong)Math.Round(value);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override double AsReal() { return value; }
// "r" ensures the value will correctly round-trip back through Double.TryParse
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string AsString() { return value.ToString("r", Utils.EnUsCulture); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override byte[] AsBinary() { return Utils.DoubleToBytesBig(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() { return AsString(); }
}
@@ -1204,8 +1232,11 @@ public OSDllsdxml(string value)
this.value = String.Empty;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string AsString() { return value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override byte[] AsBinary() { return Encoding.UTF8.GetBytes(value); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() { return AsString(); }
}
@@ -1258,8 +1289,7 @@ public override bool AsBoolean()
public override int AsInteger()
{
- double dbl;
- if (Double.TryParse(value.ToString(), out dbl))
+ if (Double.TryParse(value.ToString().AsSpan(), out double dbl))
return (int)Math.Floor(dbl);
else
return 0;
@@ -1267,8 +1297,7 @@ public override int AsInteger()
public override uint AsUInteger()
{
- double dbl;
- if (Double.TryParse(value.ToString(), out dbl))
+ if (Double.TryParse(value.ToString().AsSpan(), out double dbl))
return (uint)Math.Floor(dbl);
else
return 0;
@@ -1276,8 +1305,7 @@ public override uint AsUInteger()
public override long AsLong()
{
- double dbl;
- if (Double.TryParse(value.ToString(), out dbl))
+ if (Double.TryParse(value.ToString().AsSpan(), out double dbl))
return (long)Math.Floor(dbl);
else
return 0;
@@ -1285,8 +1313,7 @@ public override long AsLong()
public override ulong AsULong()
{
- double dbl;
- if (Double.TryParse(value.ToString(), out dbl))
+ if (Double.TryParse(value.ToString().AsSpan(), out double dbl))
return (ulong)Math.Floor(dbl);
else
return 0;
@@ -1294,8 +1321,7 @@ public override ulong AsULong()
public override double AsReal()
{
- double dbl;
- if (Double.TryParse(value.ToString(), out dbl))
+ if (Double.TryParse(value.ToString().AsSpan(), out double dbl))
return dbl;
else
return 0d;
@@ -1306,8 +1332,7 @@ public override double AsReal()
public override UUID AsUUID()
{
- UUID uuid;
- if (UUID.TryParse(value.ToString(), out uuid))
+ if (UUID.TryParse(value.ToString().AsSpan(), out UUID uuid))
return uuid;
else
return UUID.Zero;
@@ -1315,8 +1340,7 @@ public override UUID AsUUID()
public override DateTime AsDate()
{
- DateTime dt;
- if (DateTime.TryParse(value.ToString(), out dt))
+ if (DateTime.TryParse(value.ToString().AsSpan(), out DateTime dt))
return dt;
else
return Utils.Epoch;
@@ -1324,8 +1348,7 @@ public override DateTime AsDate()
public override Uri AsUri()
{
- Uri uri;
- if (Uri.TryCreate(value.ToString(), UriKind.RelativeOrAbsolute, out uri))
+ if (Uri.TryCreate(value.ToString(), UriKind.RelativeOrAbsolute, out Uri uri))
return uri;
else
return null;
@@ -1344,10 +1367,7 @@ public OSDString(string value)
{
Type = OSDType.String;
// Refuse to hold null pointers
- if (value != null)
- this.value = value;
- else
- this.value = String.Empty;
+ this.value = value ?? string.Empty;
}
public override bool AsBoolean()
@@ -1355,7 +1375,7 @@ public override bool AsBoolean()
if (String.IsNullOrEmpty(value))
return false;
- if (value == "0" || value.ToLower() == "false")
+ if (value.Equals("0") || value.Equals( "false", StringComparison.InvariantCultureIgnoreCase))
return false;
return true;
@@ -1363,8 +1383,7 @@ public override bool AsBoolean()
public override int AsInteger()
{
- double dbl;
- if (Double.TryParse(value, out dbl))
+ if (Double.TryParse(value, out double dbl))
return (int)Math.Floor(dbl);
else
return 0;
@@ -1372,8 +1391,7 @@ public override int AsInteger()
public override uint AsUInteger()
{
- double dbl;
- if (Double.TryParse(value, out dbl))
+ if (Double.TryParse(value, out double dbl))
return (uint)Math.Floor(dbl);
else
return 0;
@@ -1381,8 +1399,7 @@ public override uint AsUInteger()
public override long AsLong()
{
- double dbl;
- if (Double.TryParse(value, out dbl))
+ if (Double.TryParse(value, out double dbl))
return (long)Math.Floor(dbl);
else
return 0;
@@ -1390,8 +1407,7 @@ public override long AsLong()
public override ulong AsULong()
{
- double dbl;
- if (Double.TryParse(value, out dbl))
+ if (Double.TryParse(value, out double dbl))
return (ulong)Math.Floor(dbl);
else
return 0;
@@ -1399,8 +1415,7 @@ public override ulong AsULong()
public override double AsReal()
{
- double dbl;
- if (Double.TryParse(value, out dbl))
+ if (Double.TryParse(value, out double dbl))
return dbl;
else
return 0d;
@@ -1411,8 +1426,7 @@ public override double AsReal()
public override UUID AsUUID()
{
- UUID uuid;
- if (UUID.TryParse(value, out uuid))
+ if (UUID.TryParse(value.AsSpan(), out UUID uuid))
return uuid;
else
return UUID.Zero;
@@ -1420,8 +1434,7 @@ public override UUID AsUUID()
public override DateTime AsDate()
{
- DateTime dt;
- if (DateTime.TryParse(value, out dt))
+ if (DateTime.TryParse(value, out DateTime dt))
return dt;
else
return Utils.Epoch;
@@ -1429,8 +1442,7 @@ public override DateTime AsDate()
public override Uri AsUri()
{
- Uri uri;
- if (Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out uri))
+ if (Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out Uri uri))
return uri;
else
return null;
@@ -1452,11 +1464,17 @@ public OSDUUID(UUID value)
this.value = value;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override OSD Copy() { return new OSDUUID(value); }
- public override bool AsBoolean() { return (value.IsZero()) ? false : true; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool AsBoolean() { return value.IsNotZero(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string AsString() { return value.ToString(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override UUID AsUUID() { return value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override byte[] AsBinary() { return value.GetBytes(); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() { return AsString(); }
}
@@ -1699,8 +1717,7 @@ public OSD this[string key]
{
get
{
- OSD llsd;
- if (dicvalue.TryGetValue(key, out llsd))
+ if (dicvalue.TryGetValue(key, out OSD llsd))
return llsd;
else
return new OSD();
@@ -1708,36 +1725,43 @@ public OSD this[string key]
set { dicvalue[key] = value; }
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ContainsKey(string key)
{
return dicvalue.ContainsKey(key);
}
-
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(string key, OSD llsd)
{
dicvalue.Add(key, llsd);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(KeyValuePair kvp)
{
dicvalue.Add(kvp.Key, kvp.Value);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Remove(string key)
{
return dicvalue.Remove(key);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetValue(string key, out OSD llsd)
{
return dicvalue.TryGetValue(key, out llsd);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Clear()
{
dicvalue.Clear();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(KeyValuePair kvp)
{
// This is a bizarre function... we don't really implement it
@@ -1750,11 +1774,13 @@ public void CopyTo(KeyValuePair[] array, int index)
throw new NotImplementedException();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Remove(KeyValuePair kvp)
{
return dicvalue.Remove(kvp.Key);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public System.Collections.IDictionaryEnumerator GetEnumerator()
{
return dicvalue.GetEnumerator();
@@ -1973,36 +1999,43 @@ public OSD this[int index]
set { this.value[index] = value; }
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public int IndexOf(OSD llsd)
{
return value.IndexOf(llsd);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Insert(int index, OSD llsd)
{
value.Insert(index, llsd);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveAt(int index)
{
value.RemoveAt(index);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(OSD llsd)
{
value.Add(llsd);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Clear()
{
value.Clear();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(OSD llsd)
{
return value.Contains(llsd);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(string element)
{
for (int i = 0; i < value.Count; i++)
@@ -2019,6 +2052,7 @@ public void CopyTo(OSD[] array, int index)
throw new NotImplementedException();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Remove(OSD llsd)
{
return value.Remove(llsd);
diff --git a/OpenMetaverse.Tests/OpenMetaverse.Tests.csproj b/OpenMetaverse.Tests/OpenMetaverse.Tests.csproj
index 1ec7eb15..ac4a41ec 100644
--- a/OpenMetaverse.Tests/OpenMetaverse.Tests.csproj
+++ b/OpenMetaverse.Tests/OpenMetaverse.Tests.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
True
1591,1574,0419,0618
diff --git a/OpenMetaverse.Types/Color4.cs b/OpenMetaverse.Types/Color4.cs
index 99d0e7cf..9f132558 100644
--- a/OpenMetaverse.Types/Color4.cs
+++ b/OpenMetaverse.Types/Color4.cs
@@ -69,9 +69,7 @@ public Color4(float r, float g, float b, float a)
// Quick check to see if someone is doing something obviously wrong
// like using float values from 0.0 - 255.0
if (r > 1f || g > 1f || b > 1f || a > 1f)
- throw new ArgumentException(
- String.Format("Attempting to initialize Color4 with out of range values <{0},{1},{2},{3}>",
- r, g, b, a));
+ throw new ArgumentException($"Attempting to initialize Color4 with out of range values <{r},{g},{b},{a}>");
// Valid range is from 0.0 to 1.0
R = Utils.Clamp(r, 0f, 1f);
@@ -248,17 +246,19 @@ public void ToBytes(byte[] dest, int pos)
/// instead of 255)
public void ToBytes(byte[] dest, int pos, bool inverted)
{
- dest[pos + 0] = Utils.FloatToByte(R, 0f, 1f);
- dest[pos + 1] = Utils.FloatToByte(G, 0f, 1f);
- dest[pos + 2] = Utils.FloatToByte(B, 0f, 1f);
- dest[pos + 3] = Utils.FloatToByte(A, 0f, 1f);
-
- if (inverted)
+ if (!inverted)
+ {
+ dest[pos + 0] = Utils.FloatZeroOneToByte(R);
+ dest[pos + 1] = Utils.FloatZeroOneToByte(G);
+ dest[pos + 2] = Utils.FloatZeroOneToByte(B);
+ dest[pos + 3] = Utils.FloatZeroOneToByte(A);
+ }
+ else
{
- dest[pos + 0] = (byte)(255 - dest[pos + 0]);
- dest[pos + 1] = (byte)(255 - dest[pos + 1]);
- dest[pos + 2] = (byte)(255 - dest[pos + 2]);
- dest[pos + 3] = (byte)(255 - dest[pos + 3]);
+ dest[pos + 0] = (byte)(255 - Utils.FloatZeroOneToByte(R));
+ dest[pos + 1] = (byte)(255 - Utils.FloatZeroOneToByte(G));
+ dest[pos + 2] = (byte)(255 - Utils.FloatZeroOneToByte(B));
+ dest[pos + 3] = (byte)(255 - Utils.FloatZeroOneToByte(A));
}
}
@@ -280,8 +280,8 @@ public float GetHue()
{
const float HUE_MAX = 360f;
- float max = Math.Max(Math.Max(R, G), B);
- float min = Math.Min(Math.Min(R, B), B);
+ float max = MathF.Max(MathF.Max(R, G), B);
+ float min = MathF.Min(MathF.Min(R, B), B);
if (max == min)
{
@@ -313,22 +313,17 @@ public float GetHue()
///
public void ClampValues()
{
- if (R < 0f)
- R = 0f;
- if (G < 0f)
- G = 0f;
- if (B < 0f)
- B = 0f;
- if (A < 0f)
- A = 0f;
- if (R > 1f)
- R = 1f;
- if (G > 1f)
- G = 1f;
- if (B > 1f)
- B = 1f;
- if (A > 1f)
- A = 1f;
+ if (R < 0f) R = 0f;
+ else if (R > 1f) R = 1f;
+
+ if (G < 0f) G = 0f;
+ else if(G > 1f) G = 1f;
+
+ if (B < 0f) B = 0f;
+ else if (B > 1f) B = 1f;
+
+ if (A < 0f) A = 0f;
+ else if (A > 1f) A = 1f;
}
#endregion Public Methods
@@ -444,12 +439,12 @@ public static Color4 Lerp(Color4 value1, Color4 value2, float amount)
public override string ToString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}, {2}, {3}>", R, G, B, A);
+ return String.Format(Utils.EnUsCulture, $"<{R}, {G}, {B}, {A}>");
}
public string ToRGBString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}, {2}>", R, G, B);
+ return String.Format(Utils.EnUsCulture, $"<{R}, {G}, {B}>");
}
public override bool Equals(object obj)
@@ -481,7 +476,7 @@ public override int GetHashCode()
return !(lhs == rhs);
}
- public static Color4 operator +(Color4 lhs, Color4 rhs)
+ public static Color4 operator +(Color4 lhs, in Color4 rhs)
{
lhs.R += rhs.R;
lhs.G += rhs.G;
@@ -492,7 +487,7 @@ public override int GetHashCode()
return lhs;
}
- public static Color4 operator -(Color4 lhs, Color4 rhs)
+ public static Color4 operator -(Color4 lhs, in Color4 rhs)
{
lhs.R -= rhs.R;
lhs.G -= rhs.G;
@@ -503,7 +498,7 @@ public override int GetHashCode()
return lhs;
}
- public static Color4 operator *(Color4 lhs, Color4 rhs)
+ public static Color4 operator *(Color4 lhs, in Color4 rhs)
{
lhs.R *= rhs.R;
lhs.G *= rhs.G;
@@ -517,9 +512,9 @@ public override int GetHashCode()
#endregion Operators
/// A Color4 with zero RGB values and fully opaque (alpha 1.0)
- public readonly static Color4 Black = new Color4(0f, 0f, 0f, 1f);
+ public readonly static Color4 Black = new(0f, 0f, 0f, 1f);
/// A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0)
- public readonly static Color4 White = new Color4(1f, 1f, 1f, 1f);
+ public readonly static Color4 White = new(1f, 1f, 1f, 1f);
}
}
diff --git a/OpenMetaverse.Types/Enums.cs b/OpenMetaverse.Types/Enums.cs
index cfa5c346..e7bb202c 100644
--- a/OpenMetaverse.Types/Enums.cs
+++ b/OpenMetaverse.Types/Enums.cs
@@ -104,7 +104,9 @@ public enum AssetType : sbyte
/// Linden mesh format
Mesh = 49,
- Settings = 56
+ Settings = 56,
+ /// Render material
+ Material = 57
}
///
@@ -170,6 +172,8 @@ public enum FolderType : sbyte
MarkplaceStock = 54,
/// Settings folder
Settings = 56,
+ /// Render materials folder
+ Material = 57,
/// Hypergrid Suitcase folder
Suitcase = 100
}
@@ -236,6 +240,8 @@ public enum InventoryType : sbyte
Mesh = 22,
Settings = 25,
+
+ Material = 26
}
///
diff --git a/OpenMetaverse.Types/EnumsPrimitive.cs b/OpenMetaverse.Types/EnumsPrimitive.cs
index e0a94eb3..47d2568f 100644
--- a/OpenMetaverse.Types/EnumsPrimitive.cs
+++ b/OpenMetaverse.Types/EnumsPrimitive.cs
@@ -234,6 +234,9 @@ public enum ExtraParamType : ushort
LightImage = 0x40,
/// Whether this object is a mesh
Mesh = 0x60,
+ MeshFlag = 0x70,
+ RenderMaterial = 0x80,
+ ReflectionProbe = 0x90
}
///
diff --git a/OpenMetaverse.Types/Matrix3x3.cs b/OpenMetaverse.Types/Matrix3x3.cs
index 4ffff538..a807808b 100644
--- a/OpenMetaverse.Types/Matrix3x3.cs
+++ b/OpenMetaverse.Types/Matrix3x3.cs
@@ -108,7 +108,7 @@ public Matrix3x3(float roll, float pitch, float yaw)
this = CreateFromEulers(roll, pitch, yaw);
}
- public Matrix3x3( Matrix3x3 m)
+ public Matrix3x3(Matrix3x3 m)
{
M11 = m.M11;
M12 = m.M12;
@@ -157,25 +157,25 @@ public float Trace()
/// Z euler angle
public void GetEulerAngles(out float roll, out float pitch, out float yaw)
{
- double angleX, angleY, angleZ;
- double cx, cy, cz; // cosines
- double sx, sz; // sines
+ float angleX, angleY, angleZ;
+ float cx, cy, cz; // cosines
+ float sx, sz; // sines
- angleY = Math.Asin(Utils.Clamp(M13, -1f, 1f));
- cy = Math.Cos(angleY);
+ angleY = MathF.Asin(Utils.Clamp(M13, -1f, 1f));
+ cy = MathF.Cos(angleY);
- if (Math.Abs(cy) > 0.005f)
+ if (MathF.Abs(cy) > 0.005f)
{
// No gimbal lock
cx = M33 / cy;
sx = (-M23) / cy;
- angleX = (float)Math.Atan2(sx, cx);
+ angleX = MathF.Atan2(sx, cx);
cz = M11 / cy;
sz = (-M12) / cy;
- angleZ = (float)Math.Atan2(sz, cz);
+ angleZ = MathF.Atan2(sz, cz);
}
else
{
@@ -185,13 +185,13 @@ public void GetEulerAngles(out float roll, out float pitch, out float yaw)
cz = M22;
sz = M21;
- angleZ = Math.Atan2(sz, cz);
+ angleZ = MathF.Atan2(sz, cz);
}
// Return only positive angles in [0,360]
- if (angleX < 0) angleX += 360d;
- if (angleY < 0) angleY += 360d;
- if (angleZ < 0) angleZ += 360d;
+ if (angleX < 0) angleX += 360f;
+ if (angleY < 0) angleY += 360f;
+ if (angleZ < 0) angleZ += 360f;
roll = (float)angleX;
pitch = (float)angleY;
@@ -209,7 +209,7 @@ public Quaternion GetQuaternion()
if (trace > Single.Epsilon)
{
- float s = 0.5f / (float)Math.Sqrt(trace);
+ float s = 0.5f / MathF.Sqrt(trace);
quat.X = (M32 - M23) * s;
quat.Y = (M13 - M31) * s;
@@ -220,7 +220,7 @@ public Quaternion GetQuaternion()
{
if (M11 > M22 && M11 > M33)
{
- float s = 2.0f * (float)Math.Sqrt(1.0f + M11 - M22 - M33);
+ float s = 2.0f * MathF.Sqrt(1.0f + M11 - M22 - M33);
quat.X = 0.25f * s;
quat.Y = (M12 + M21) / s;
@@ -229,7 +229,7 @@ public Quaternion GetQuaternion()
}
else if (M22 > M33)
{
- float s = 2.0f * (float)Math.Sqrt(1.0f + M22 - M11 - M33);
+ float s = 2.0f * MathF.Sqrt(1.0f + M22 - M11 - M33);
quat.X = (M12 + M21) / s;
quat.Y = 0.25f * s;
@@ -238,7 +238,7 @@ public Quaternion GetQuaternion()
}
else
{
- float s = 2.0f * (float)Math.Sqrt(1.0f + M33 - M11 - M22);
+ float s = 2.0f * MathF.Sqrt(1.0f + M33 - M11 - M22);
quat.X = (M13 + M31) / s;
quat.Y = (M23 + M32) / s;
@@ -252,9 +252,9 @@ public Quaternion GetQuaternion()
public bool Decompose(out Vector3 scale, out Quaternion rotation)
{
- float sx = (float)Math.Sqrt(M11 * M11 + M12 * M12 + M13 * M13);
- float sy = (float)Math.Sqrt(M21 * M21 + M22 * M22 + M23 * M23);
- float sz = (float)Math.Sqrt(M31 * M31 + M32 * M32 + M33 * M33);
+ float sx = MathF.Sqrt(M11 * M11 + M12 * M12 + M13 * M13);
+ float sy = MathF.Sqrt(M21 * M21 + M22 * M22 + M23 * M23);
+ float sz = MathF.Sqrt(M31 * M31 + M32 * M32 + M33 * M33);
scale = new Vector3(sx, sy, sz);
if (sx == 0.0 || sy == 0.0 || sz == 0.0)
@@ -276,7 +276,7 @@ public bool Decompose(out Vector3 scale, out Quaternion rotation)
#region Static Methods
- public static Matrix3x3 Add( Matrix3x3 matrix1, Matrix3x3 matrix2)
+ public static Matrix3x3 Add(Matrix3x3 matrix1, in Matrix3x3 matrix2)
{
return new Matrix3x3(
matrix1.M11 + matrix2.M11,
@@ -299,8 +299,8 @@ public static Matrix3x3 CreateFromAxisAngle(Vector3 axis, float angle)
float x = axis.X;
float y = axis.Y;
float z = axis.Z;
- float sin = (float)Math.Sin(angle);
- float cos = (float)Math.Cos(angle);
+ float sin = MathF.Sin(angle);
+ float cos = MathF.Cos(angle);
float xx = x * x;
float yy = y * y;
float zz = z * z;
@@ -331,12 +331,12 @@ public static Matrix3x3 CreateFromAxisAngle(Vector3 axis, float angle)
/// Z euler angle in radians
public static Matrix3x3 CreateFromEulers(float roll, float pitch, float yaw)
{
- float a = (float)Math.Cos(roll);
- float b = (float)Math.Sin(roll);
- float c = (float)Math.Cos(pitch);
- float d = (float)Math.Sin(pitch);
- float e = (float)Math.Cos(yaw);
- float f = (float)Math.Sin(yaw);
+ float a = MathF.Cos(roll);
+ float b = MathF.Sin(roll);
+ float c = MathF.Cos(pitch);
+ float d = MathF.Sin(pitch);
+ float e = MathF.Cos(yaw);
+ float f = MathF.Sin(yaw);
float ad = a * d;
float bd = b * d;
@@ -388,8 +388,8 @@ public static Matrix3x3 CreateFromQuaternion(Quaternion rot)
public static Matrix3x3 CreateRotationX(float radians)
{
- float cos = (float)Math.Cos(radians);
- float sin = (float)Math.Sin(radians);
+ float cos = MathF.Cos(radians);
+ float sin = MathF.Sin(radians);
return new Matrix3x3(
1f, 0f, 0f,
@@ -400,8 +400,8 @@ public static Matrix3x3 CreateRotationX(float radians)
public static Matrix3x3 CreateRotationY(float radians)
{
- float cos = (float)Math.Cos(radians);
- float sin = (float)Math.Sin(radians);
+ float cos = MathF.Cos(radians);
+ float sin = MathF.Sin(radians);
return new Matrix3x3(
cos, 0f, -sin,
@@ -412,8 +412,8 @@ public static Matrix3x3 CreateRotationY(float radians)
public static Matrix3x3 CreateRotationZ(float radians)
{
- float cos = (float)Math.Cos(radians);
- float sin = (float)Math.Sin(radians);
+ float cos = MathF.Cos(radians);
+ float sin = MathF.Sin(radians);
return new Matrix3x3(
cos, sin, 0f,
@@ -431,7 +431,7 @@ public static Matrix3x3 CreateScale(Vector3 scale)
);
}
- public static Matrix3x3 Divide( Matrix3x3 matrix1, Matrix3x3 matrix2)
+ public static Matrix3x3 Divide(Matrix3x3 matrix1, Matrix3x3 matrix2)
{
return new Matrix3x3(
matrix1.M11 / matrix2.M11,
@@ -448,7 +448,7 @@ public static Matrix3x3 Divide( Matrix3x3 matrix1, Matrix3x3 matrix2)
);
}
- public static Matrix3x3 Divide( Matrix3x3 matrix1, float divider)
+ public static Matrix3x3 Divide(Matrix3x3 matrix1, float divider)
{
float oodivider = 1f / divider;
return new Matrix3x3(
@@ -466,7 +466,7 @@ public static Matrix3x3 Divide( Matrix3x3 matrix1, float divider)
);
}
- public static Matrix3x3 Lerp( Matrix3x3 matrix1, Matrix3x3 matrix2, float amount)
+ public static Matrix3x3 Lerp(Matrix3x3 matrix1, Matrix3x3 matrix2, float amount)
{
return new Matrix3x3(
matrix1.M11 + ((matrix2.M11 - matrix1.M11) * amount),
@@ -483,7 +483,7 @@ public static Matrix3x3 Lerp( Matrix3x3 matrix1, Matrix3x3 matrix2, float amou
);
}
- public static Matrix3x3 Multiply( Matrix3x3 matrix1, Matrix3x3 matrix2)
+ public static Matrix3x3 Multiply(Matrix3x3 matrix1, Matrix3x3 matrix2)
{
return new Matrix3x3(
matrix1.M11 * matrix2.M11 + matrix1.M12 * matrix2.M21 + matrix1.M13 * matrix2.M31,
@@ -500,7 +500,7 @@ public static Matrix3x3 Multiply( Matrix3x3 matrix1, Matrix3x3 matrix2)
);
}
- public static Matrix3x3 Multiply( Matrix3x3 matrix1, float scaleFactor)
+ public static Matrix3x3 Multiply(Matrix3x3 matrix1, float scaleFactor)
{
Matrix3x3 matrix;
matrix.M11 = matrix1.M11 * scaleFactor;
@@ -518,7 +518,7 @@ public static Matrix3x3 Multiply( Matrix3x3 matrix1, float scaleFactor)
return matrix;
}
- public static Matrix3x3 Negate( Matrix3x3 matrix)
+ public static Matrix3x3 Negate(Matrix3x3 matrix)
{
return new Matrix3x3(
-matrix.M11, -matrix.M12, -matrix.M13,
@@ -527,7 +527,7 @@ public static Matrix3x3 Negate( Matrix3x3 matrix)
);
}
- public static Matrix3x3 Subtract( Matrix3x3 matrix1, Matrix3x3 matrix2)
+ public static Matrix3x3 Subtract(Matrix3x3 matrix1, Matrix3x3 matrix2)
{
return new Matrix3x3(
matrix1.M11 - matrix2.M11,
@@ -544,7 +544,7 @@ public static Matrix3x3 Subtract( Matrix3x3 matrix1, Matrix3x3 matrix2)
);
}
- public static Matrix3x3 Transform( Matrix3x3 value, Quaternion rotation)
+ public static Matrix3x3 Transform(Matrix3x3 value, Quaternion rotation)
{
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
@@ -598,20 +598,20 @@ public static Matrix3x3 Inverse3x3(Matrix3x3 matrix)
return (Adjoint3x3(matrix) / matrix.Determinant3x3());
}
- public static Matrix3x3 Adjoint3x3( Matrix3x3 matrix)
+ public static Matrix3x3 Adjoint3x3(Matrix3x3 matrix)
{
Matrix3x3 adjointMatrix = new Matrix3x3();
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
- adjointMatrix[i,j] = (float)(Math.Pow(-1, i + j) * (Minor(matrix, i, j).Determinant3x3()));
+ adjointMatrix[i,j] = MathF.Pow(-1, i + j) * (Minor(matrix, i, j).Determinant3x3());
}
adjointMatrix = Transpose(adjointMatrix);
return adjointMatrix;
}
- public static Matrix3x3 Inverse( Matrix3x3 matrix)
+ public static Matrix3x3 Inverse(Matrix3x3 matrix)
{
if (matrix.Determinant() == 0f)
throw new ArgumentException("Singular matrix inverse not possible");
@@ -619,13 +619,13 @@ public static Matrix3x3 Inverse( Matrix3x3 matrix)
return (Adjoint(matrix) / matrix.Determinant());
}
- public static Matrix3x3 Adjoint( Matrix3x3 matrix)
+ public static Matrix3x3 Adjoint(Matrix3x3 matrix)
{
- Matrix3x3 adjointMatrix = new Matrix3x3();
+ Matrix3x3 adjointMatrix = new();
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
- adjointMatrix[i,j] = (float)(Math.Pow(-1, i + j) * ((Minor(matrix, i, j)).Determinant3x3()));
+ adjointMatrix[i,j] = MathF.Pow(-1, i + j) * ((Minor(matrix, i, j)).Determinant3x3());
}
adjointMatrix = Transpose(adjointMatrix);
@@ -634,7 +634,7 @@ public static Matrix3x3 Adjoint( Matrix3x3 matrix)
public static Matrix3x3 Minor(Matrix3x3 matrix, int row, int col)
{
- Matrix3x3 minor = new Matrix3x3();
+ Matrix3x3 minor = new();
int m = 0, n = 0;
for (int i = 0; i < 3; i++)
@@ -694,47 +694,47 @@ public override string ToString()
#region Operators
- public static bool operator ==( Matrix3x3 left, Matrix3x3 right)
+ public static bool operator ==(Matrix3x3 left, Matrix3x3 right)
{
return left.Equals(right);
}
- public static bool operator !=( Matrix3x3 left, Matrix3x3 right)
+ public static bool operator !=(Matrix3x3 left, Matrix3x3 right)
{
return !left.Equals(right);
}
- public static Matrix3x3 operator +( Matrix3x3 left, Matrix3x3 right)
+ public static Matrix3x3 operator +(Matrix3x3 left, Matrix3x3 right)
{
return Add(left, right);
}
- public static Matrix3x3 operator -( Matrix3x3 matrix)
+ public static Matrix3x3 operator -(Matrix3x3 matrix)
{
return Negate(matrix);
}
- public static Matrix3x3 operator -( Matrix3x3 left, Matrix3x3 right)
+ public static Matrix3x3 operator -(Matrix3x3 left, Matrix3x3 right)
{
return Subtract(left, right);
}
- public static Matrix3x3 operator *( Matrix3x3 left, Matrix3x3 right)
+ public static Matrix3x3 operator *(Matrix3x3 left, Matrix3x3 right)
{
return Multiply(left, right);
}
- public static Matrix3x3 operator *( Matrix3x3 left, float scalar)
+ public static Matrix3x3 operator *(Matrix3x3 left, float scalar)
{
return Multiply(left, scalar);
}
- public static Matrix3x3 operator /( Matrix3x3 left, Matrix3x3 right)
+ public static Matrix3x3 operator /(Matrix3x3 left, Matrix3x3 right)
{
return Divide(left, right);
}
- public static Matrix3x3 operator /( Matrix3x3 matrix, float divider)
+ public static Matrix3x3 operator /(Matrix3x3 matrix, float divider)
{
return Divide(matrix, divider);
}
@@ -875,10 +875,10 @@ public Vector3 this[int row]
#endregion Operators
/// A 3x3 matrix containing all zeroes
- public static readonly Matrix3x3 Zero = new Matrix3x3();
+ public static readonly Matrix3x3 Zero = new();
/// A 3x3 identity matrix
- public static readonly Matrix3x3 Identity = new Matrix3x3(
+ public static readonly Matrix3x3 Identity = new(
1f, 0f, 0f,
0f, 1f, 0f,
0f, 0f, 1f);
diff --git a/OpenMetaverse.Types/Matrix4.cs b/OpenMetaverse.Types/Matrix4.cs
index 4321bb20..fb5d5edd 100644
--- a/OpenMetaverse.Types/Matrix4.cs
+++ b/OpenMetaverse.Types/Matrix4.cs
@@ -185,25 +185,25 @@ public float Trace()
/// Z euler angle
public void GetEulerAngles(out float roll, out float pitch, out float yaw)
{
- double angleX, angleY, angleZ;
- double cx, cy, cz; // cosines
- double sx, sz; // sines
+ float angleX, angleY, angleZ;
+ float cx, cy, cz; // cosines
+ float sx, sz; // sines
- angleY = Math.Asin(Utils.Clamp(M13, -1f, 1f));
- cy = Math.Cos(angleY);
+ angleY = MathF.Asin(Utils.Clamp(M13, -1f, 1f));
+ cy = MathF.Cos(angleY);
- if (Math.Abs(cy) > 0.005f)
+ if (MathF.Abs(cy) > 0.005f)
{
// No gimbal lock
cx = M33 / cy;
sx = (-M23) / cy;
- angleX = (float)Math.Atan2(sx, cx);
+ angleX = MathF.Atan2(sx, cx);
cz = M11 / cy;
sz = (-M12) / cy;
- angleZ = (float)Math.Atan2(sz, cz);
+ angleZ = MathF.Atan2(sz, cz);
}
else
{
@@ -213,17 +213,17 @@ public void GetEulerAngles(out float roll, out float pitch, out float yaw)
cz = M22;
sz = M21;
- angleZ = Math.Atan2(sz, cz);
+ angleZ = MathF.Atan2(sz, cz);
}
// Return only positive angles in [0,360]
- if (angleX < 0) angleX += 360d;
- if (angleY < 0) angleY += 360d;
- if (angleZ < 0) angleZ += 360d;
+ if (angleX < 0) angleX += 360f;
+ if (angleY < 0) angleY += 360f;
+ if (angleZ < 0) angleZ += 360f;
- roll = (float)angleX;
- pitch = (float)angleY;
- yaw = (float)angleZ;
+ roll = angleX;
+ pitch = angleY;
+ yaw = angleZ;
}
///
@@ -237,7 +237,7 @@ public Quaternion GetQuaternion()
if (trace > Single.Epsilon)
{
- float s = 0.5f / (float)Math.Sqrt(trace);
+ float s = 0.5f / MathF.Sqrt(trace);
quat.X = (M32 - M23) * s;
quat.Y = (M13 - M31) * s;
@@ -248,7 +248,7 @@ public Quaternion GetQuaternion()
{
if (M11 > M22 && M11 > M33)
{
- float s = 2.0f * (float)Math.Sqrt(1.0f + M11 - M22 - M33);
+ float s = 2.0f * MathF.Sqrt(1.0f + M11 - M22 - M33);
quat.X = 0.25f * s;
quat.Y = (M12 + M21) / s;
@@ -257,7 +257,7 @@ public Quaternion GetQuaternion()
}
else if (M22 > M33)
{
- float s = 2.0f * (float)Math.Sqrt(1.0f + M22 - M11 - M33);
+ float s = 2.0f * MathF.Sqrt(1.0f + M22 - M11 - M33);
quat.X = (M12 + M21) / s;
quat.Y = 0.25f * s;
@@ -266,7 +266,7 @@ public Quaternion GetQuaternion()
}
else
{
- float s = 2.0f * (float)Math.Sqrt(1.0f + M33 - M11 - M22);
+ float s = 2.0f * MathF.Sqrt(1.0f + M33 - M11 - M22);
quat.X = (M13 + M31) / s;
quat.Y = (M23 + M32) / s;
@@ -286,9 +286,9 @@ public bool Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 tr
float ys = (Math.Sign(M21 * M22 * M23 * M24) < 0) ? -1 : 1;
float zs = (Math.Sign(M31 * M32 * M33 * M34) < 0) ? -1 : 1;
- xs *= (float)Math.Sqrt(M11 * M11 + M12 * M12 + M13 * M13);
- ys *= (float)Math.Sqrt(M21 * M21 + M22 * M22 + M23 * M23);
- zs *= (float)Math.Sqrt(M31 * M31 + M32 * M32 + M33 * M33);
+ xs *= MathF.Sqrt(M11 * M11 + M12 * M12 + M13 * M13);
+ ys *= MathF.Sqrt(M21 * M21 + M22 * M22 + M23 * M23);
+ zs *= MathF.Sqrt(M31 * M31 + M32 * M32 + M33 * M33);
scale = new Vector3(xs, ys, zs);
@@ -343,8 +343,8 @@ public static Matrix4 CreateFromAxisAngle(Vector3 axis, float angle)
float x = axis.X;
float y = axis.Y;
float z = axis.Z;
- float sin = (float)Math.Sin(angle);
- float cos = (float)Math.Cos(angle);
+ float sin = MathF.Sin(angle);
+ float cos = MathF.Cos(angle);
float xx = x * x;
float yy = y * y;
float zz = z * z;
@@ -386,12 +386,12 @@ public static Matrix4 CreateFromEulers(float roll, float pitch, float yaw)
float a, b, c, d, e, f;
float ad, bd;
- a = (float)Math.Cos(roll);
- b = (float)Math.Sin(roll);
- c = (float)Math.Cos(pitch);
- d = (float)Math.Sin(pitch);
- e = (float)Math.Cos(yaw);
- f = (float)Math.Sin(yaw);
+ a = MathF.Cos(roll);
+ b = MathF.Sin(roll);
+ c = MathF.Cos(pitch);
+ d = MathF.Sin(pitch);
+ e = MathF.Cos(yaw);
+ f = MathF.Sin(yaw);
ad = a * d;
bd = b * d;
@@ -491,8 +491,8 @@ public static Matrix4 CreateRotationX(float radians)
{
Matrix4 matrix;
- float cos = (float)Math.Cos(radians);
- float sin = (float)Math.Sin(radians);
+ float cos = MathF.Cos(radians);
+ float sin = MathF.Sin(radians);
matrix.M11 = 1f;
matrix.M12 = 0f;
@@ -521,8 +521,8 @@ public static Matrix4 CreateRotationY(float radians)
{
Matrix4 matrix;
- float cos = (float)Math.Cos(radians);
- float sin = (float)Math.Sin(radians);
+ float cos = MathF.Cos(radians);
+ float sin = MathF.Sin(radians);
matrix.M11 = cos;
matrix.M12 = 0f;
@@ -551,8 +551,8 @@ public static Matrix4 CreateRotationZ(float radians)
{
Matrix4 matrix;
- float cos = (float)Math.Cos(radians);
- float sin = (float)Math.Sin(radians);
+ float cos = MathF.Cos(radians);
+ float sin = MathF.Sin(radians);
matrix.M11 = cos;
matrix.M12 = sin;
@@ -933,7 +933,7 @@ public static Matrix4 Adjoint3x3(Matrix4 matrix)
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
- adjointMatrix[i, j] = (float)(Math.Pow(-1, i + j) * (Minor(matrix, i, j).Determinant3x3()));
+ adjointMatrix[i,j] = MathF.Pow(-1, i + j) * (Minor(matrix, i, j).Determinant3x3());
}
adjointMatrix = Transpose(adjointMatrix);
@@ -954,7 +954,7 @@ public static Matrix4 Adjoint(Matrix4 matrix)
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
- adjointMatrix[i, j] = (float)(Math.Pow(-1, i + j) * ((Minor(matrix, i, j)).Determinant3x3()));
+ adjointMatrix[i,j] = MathF.Pow(-1, i + j) * ((Minor(matrix, i, j)).Determinant3x3());
}
adjointMatrix = Transpose(adjointMatrix);
@@ -1260,7 +1260,7 @@ public Vector4 this[int row]
public static readonly Matrix4 Zero = new Matrix4();
/// A 4x4 identity matrix
- public static readonly Matrix4 Identity = new Matrix4(
+ public static readonly Matrix4 Identity = new(
1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f,
diff --git a/OpenMetaverse.Types/OSUTF8.cs b/OpenMetaverse.Types/OSUTF8.cs
index 02cdf759..27b48b94 100644
--- a/OpenMetaverse.Types/OSUTF8.cs
+++ b/OpenMetaverse.Types/OSUTF8.cs
@@ -38,6 +38,8 @@ Ubit Umarov (Leal Duarte) 2020
using System.Text;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.Intrinsics;
namespace OpenMetaverse
{
@@ -182,7 +184,7 @@ public override bool Equals(object obj)
public unsafe bool Equals(osUTF8Slice o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
byte[] otherdata = o.m_data;
@@ -237,7 +239,7 @@ public unsafe bool Equals(byte[] o)
public unsafe bool Equals(osUTF8 o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
byte[] otherdata = o.m_data;
@@ -266,6 +268,22 @@ public bool Equals(string s)
return Equals(o);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(osUTF8 value1, osUTF8 value2)
+ {
+ if (value1 is null)
+ return value2 is null;
+ return value1.Equals(value2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(osUTF8 value1, osUTF8 value2)
+ {
+ if (value1 is null)
+ return !(value2 is null);
+ return !value1.Equals(value2);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(char c)
{
@@ -274,7 +292,7 @@ public bool Equals(char c)
public unsafe bool ACSIILowerEquals(osUTF8 o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
fixed (byte* a = m_data, b = o.m_data)
@@ -299,7 +317,7 @@ public unsafe bool ACSIILowerEquals(osUTF8 o)
public unsafe bool ACSIILowerEquals(osUTF8Slice o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
fixed (byte* a = m_data, b = o.m_data)
@@ -543,7 +561,7 @@ public unsafe void AppendUUID(UUID u)
{
CheckCapacity(36);
fixed (byte* d = m_data)
- Utils.UUIDToByteDashString(ref u, d + m_len);
+ Utils.UUIDToByteDashString(u, d + m_len);
m_len += 36;
}
@@ -987,43 +1005,113 @@ public unsafe static bool TryParseUUID(osUTF8 inp, out UUID result)
if (val[13] != '-' || val[18] != '-' || val[23] != '-')
return false;
+ if (Sse42.IsSupported)
+ {
+ Vector128 input = Unsafe.As>(ref Unsafe.AsRef(val));
+ Vector128 upper = Ssse3.Shuffle(input, Vector128.Create(0, 2, 4, 6, 9, 11, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lower = Ssse3.Shuffle(input, Vector128.Create(1, 3, 5, 7, 10, 12, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 16 + 3));
+ Vector128 upperhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 2, 5, 7, 9, 11, 13, 15));
+ Vector128 lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1, 3, 6, 8, 10, 12, 14, 0xff));
+ upper = Sse2.Or(upper, upperhalf);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ upper = Sse41.Insert(upper, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 16)), 7);
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 17)), 7);
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 35)), 15);
+
+ Vector128 charf = Vector128.Create((byte)'f');
+ Vector128 tmpcmp = Sse2.Subtract(charf, lower);
+ int cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+
+ tmpcmp = Sse2.Subtract(charf, upper);
+ cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+
+ Vector128 charTolower = Vector128.Create((byte)0x20);
+ Vector128 lowerLetters = Sse2.Or(lower, charTolower);
+ Vector128 upperLetters = Sse2.Or(upper, charTolower);
+
+ Vector128 letterTohex = Vector128.Create((byte)('a' - '0' - 10));
+ lowerLetters = Sse2.Subtract(lowerLetters, letterTohex);
+ upperLetters = Sse2.Subtract(upperLetters, letterTohex);
+
+ Vector128 char9 = Vector128.Create((byte)'9');
+ Vector128 above9lower = (Sse2.CompareGreaterThan(lower.AsSByte(), char9.AsSByte())).AsByte();
+
+ Vector128 ten = Vector128.Create((byte)('0' + 10));
+ tmpcmp = Sse2.Subtract(lowerLetters, ten);
+ tmpcmp = Sse2.And(tmpcmp, above9lower);
+ cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+ Vector128 above9upper = (Sse2.CompareGreaterThan(upper.AsSByte(), char9.AsSByte())).AsByte();
+
+ tmpcmp = Sse2.Subtract(upperLetters, ten);
+ tmpcmp = Sse2.And(tmpcmp, above9upper);
+ cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+
+ lower = Sse41.BlendVariable(lower, lowerLetters, above9lower);
+ upper = Sse41.BlendVariable(upper, upperLetters, above9upper);
+ Vector128 charzero = Vector128.Create((byte)'0');
+ lower = Sse2.Subtract(lower, charzero);
+ cmp = Sse2.MoveMask(lower);
+ if (cmp != 0)
+ throw new Exception("bad");
+ upper = Sse2.Subtract(upper, charzero);
+ cmp = Sse2.MoveMask(upper);
+ if (cmp != 0)
+ throw new Exception("bad");
+ upper = Sse2.ShiftLeftLogical(upper.AsUInt16(), 4).AsByte();
+ lower = Sse2.Or(lower, upper);
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref Unsafe.AsRef(in result)) = lower;
+ return true;
+ }
+
if (BitConverter.IsLittleEndian)
{
- result.bytea3 = (byte)Utils.HexToByte(val, 0);
- result.bytea2 = (byte)Utils.HexToByte(val, 2);
- result.bytea1 = (byte)Utils.HexToByte(val, 4);
- result.bytea0 = (byte)Utils.HexToByte(val, 6);
+ result.bytea3 = Utils.HexToByte(val, 0);
+ result.bytea2 = Utils.HexToByte(val, 2);
+ result.bytea1 = Utils.HexToByte(val, 4);
+ result.bytea0 = Utils.HexToByte(val, 6);
- result.byteb1 = (byte)Utils.HexToByte(val, 9);
- result.byteb0 = (byte)Utils.HexToByte(val, 11);
+ result.byteb1 = Utils.HexToByte(val, 9);
+ result.byteb0 = Utils.HexToByte(val, 11);
- result.bytec1 = (byte)Utils.HexToByte(val, 14);
- result.bytec0 = (byte)Utils.HexToByte(val, 16);
+ result.bytec1 = Utils.HexToByte(val, 14);
+ result.bytec0 = Utils.HexToByte(val, 16);
}
else
{
- result.bytea0 = (byte)Utils.HexToByte(val, 0);
- result.bytea1 = (byte)Utils.HexToByte(val, 2);
- result.bytea2 = (byte)Utils.HexToByte(val, 4);
- result.bytea3 = (byte)Utils.HexToByte(val, 6);
+ result.bytea0 = Utils.HexToByte(val, 0);
+ result.bytea1 = Utils.HexToByte(val, 2);
+ result.bytea2 = Utils.HexToByte(val, 4);
+ result.bytea3 = Utils.HexToByte(val, 6);
- result.byteb0 = (byte)Utils.HexToByte(val, 9);
- result.byteb1 = (byte)Utils.HexToByte(val, 11);
+ result.byteb0 = Utils.HexToByte(val, 9);
+ result.byteb1 = Utils.HexToByte(val, 11);
- result.bytec0 = (byte)Utils.HexToByte(val, 14);
- result.bytec1 = (byte)Utils.HexToByte(val, 16);
+ result.bytec0 = Utils.HexToByte(val, 14);
+ result.bytec1 = Utils.HexToByte(val, 16);
}
- result.d = (byte)Utils.HexToByte(val, 19);
- result.e = (byte)Utils.HexToByte(val, 21);
+ result.d = Utils.HexToByte(val, 19);
+ result.e = Utils.HexToByte(val, 21);
- result.f = (byte)Utils.HexToByte(val, 24);
- result.g = (byte)Utils.HexToByte(val, 26);
- result.h = (byte)Utils.HexToByte(val, 28);
- result.i = (byte)Utils.HexToByte(val, 30);
- result.j = (byte)Utils.HexToByte(val, 32);
- result.k = (byte)Utils.HexToByte(val, 34);
+ result.f = Utils.HexToByte(val, 24);
+ result.g = Utils.HexToByte(val, 26);
+ result.h = Utils.HexToByte(val, 28);
+ result.i = Utils.HexToByte(val, 30);
+ result.j = Utils.HexToByte(val, 32);
+ result.k = Utils.HexToByte(val, 34);
return true;
}
else
@@ -1128,17 +1216,17 @@ public static byte[] GetASCIIBytes(string s)
public static bool IsNullOrEmpty(osUTF8 u)
{
- return (u == null || u.m_len == 0);
+ return (u is null || u.m_len == 0);
}
public static bool IsEmpty(osUTF8 u)
{
- return (u == null || u.m_len == 0);
+ return (u is null || u.m_len == 0);
}
public static unsafe bool IsNullOrWhitespace(osUTF8 u)
{
- if(u == null || u.m_len == 0)
+ if(u is null || u.m_len == 0)
return true;
byte[] data = u.m_data;
for (int i = 0; i < u.m_len; ++i)
diff --git a/OpenMetaverse.Types/OSUTF8Constants.cs b/OpenMetaverse.Types/OSUTF8Constants.cs
index 5840a8f8..25213dd3 100644
--- a/OpenMetaverse.Types/OSUTF8Constants.cs
+++ b/OpenMetaverse.Types/OSUTF8Constants.cs
@@ -130,9 +130,9 @@ public static class osUTF8Const
public static readonly byte[] XMLelement_sale_info_Mid = osUTF8.GetASCIIBytes("sale_type");
public static readonly byte[] XMLelement_sale_info_End = osUTF8.GetASCIIBytes("");
- public static readonly byte[] OSUTF8null = osUTF8.GetASCIIBytes("null");
- public static readonly byte[] OSUTF8true = osUTF8.GetASCIIBytes("true");
- public static readonly byte[] OSUTF8false = osUTF8.GetASCIIBytes("false");
+ public static readonly byte[] OSUTF8null = { (byte)'n', (byte)'u', (byte)'l', (byte)'l' };
+ public static readonly byte[] OSUTF8true = { (byte)'t', (byte)'r', (byte)'u', (byte)'e' };
+ public static readonly byte[] OSUTF8false = { (byte)'f', (byte)'a', (byte)'l', (byte)'s', (byte)'e' };
public static readonly byte[] base64Bytes = {(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F',(byte)'G',(byte)'H',(byte)'I',(byte)'J',(byte)'K',(byte)'L',(byte)'M',(byte)'N',(byte)'O',
(byte)'P',(byte)'Q',(byte)'R',(byte)'S',(byte)'T',(byte)'U',(byte)'V',(byte)'W',(byte)'X',(byte)'Y',(byte)'Z',(byte)'a',(byte)'b',(byte)'c',(byte)'d',
diff --git a/OpenMetaverse.Types/OSUTF8Slice.cs b/OpenMetaverse.Types/OSUTF8Slice.cs
index c9b42b7f..21c5947d 100644
--- a/OpenMetaverse.Types/OSUTF8Slice.cs
+++ b/OpenMetaverse.Types/OSUTF8Slice.cs
@@ -38,6 +38,9 @@ Ubit Umarov (Leal Duarte) 2020
using System.Text;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.Intrinsics;
namespace OpenMetaverse
{
@@ -132,7 +135,7 @@ public byte this[int i]
i = 0;
else if (i >= m_data.Length)
i = m_data.Length - 1;
- return m_data[i];
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i));
}
set
{
@@ -140,7 +143,7 @@ public byte this[int i]
{
i += m_offset;
if(i < m_len)
- m_data[i] = value;
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)) = value;
}
}
}
@@ -202,22 +205,22 @@ public void FromBytes(byte[] source, int offset, int len)
public static bool IsNullOrEmpty(osUTF8Slice u)
{
- return (u == null || u.m_len == 0);
+ return (u is null || u.m_len == 0);
}
public static bool IsEmpty(osUTF8Slice u)
{
- return (u == null || u.m_len == 0);
+ return (u is null || u.m_len == 0);
}
public static unsafe bool IsNullOrWhitespace(osUTF8Slice u)
{
- if (u == null || u.m_len == 0)
+ if (u is null || u.m_len == 0)
return true;
byte[] data = u.m_data;
for (int i = u.m_offset; i < u.m_offset + u.m_len; ++i)
{
- if (data[i] != 0x20)
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(data), i)) != 0x20)
return false;
}
return true;
@@ -226,26 +229,11 @@ public static unsafe bool IsNullOrWhitespace(osUTF8Slice u)
public unsafe override int GetHashCode()
{
int hash = m_len;
- if (m_len < 8)
+ for (int i = m_offset; i < m_offset + m_len; ++i)
{
- for (int i = m_offset; i < m_offset + m_len; ++i)
- {
- hash += m_data[i];
- hash <<= 3;
- hash += hash >> 26;
- }
- }
- else
- {
- fixed (byte* a = &m_data[m_offset])
- {
- for (int i = 0; i < m_len; ++i)
- {
- hash += a[i];
- hash <<= 5;
- hash += hash >> 26;
- }
- }
+ hash += Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i));
+ hash <<= 3;
+ hash += hash >> 26;
}
return hash & 0x7fffffff;
}
@@ -260,103 +248,64 @@ public override string ToString()
public override bool Equals(object obj)
{
- if (obj == null)
+ if (obj is null)
return false;
- if (obj is osUTF8)
- return Equals((osUTF8)obj);
+ if (obj is osUTF8 o8)
+ return Equals(o8);
- if (obj is osUTF8Slice)
- return Equals((osUTF8Slice)obj);
+ if (obj is osUTF8Slice o8s)
+ return Equals(o8s);
- if (obj is string)
- return Equals((string)obj);
+ if (obj is string os)
+ return Equals(os);
- if (obj is byte[])
- return Equals((byte[])obj);
+ if (obj is byte[] oba)
+ return Equals(oba);
return false;
}
- public unsafe bool Equals(osUTF8Slice o)
+ public bool Equals(osUTF8Slice o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
byte[] otherdata = o.m_data;
-
- if (m_len < 8)
- {
- for (int i = m_offset, j = o.m_offset; i < m_offset + m_len; ++i, ++j)
- {
- if (m_data[i] != otherdata[j])
- return false;
- }
- return true;
- }
-
- fixed (byte* a = &m_data[m_offset], b = &otherdata[o.m_offset])
+ for (int i = m_offset, j = o.m_offset; i < m_offset + m_len; ++i, ++j)
{
- for (int i = 0; i < m_len; ++i)
- {
- if (a[i] != b[i])
- return false;
- }
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)) !=
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(otherdata), j)))
+ return false;
}
-
return true;
}
- public unsafe bool Equals(osUTF8 o)
+ public bool Equals(osUTF8 o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
byte[] otherdata = o.m_data;
-
- if (m_len < 8)
+ for (int i = m_offset, j = 0; i < m_offset + m_len; ++i, ++j)
{
- for (int i = m_offset, j = 0; i < m_offset + m_len; ++i, ++j)
- {
- if (m_data[i] != otherdata[j])
- return false;
- }
- return true;
- }
-
- fixed (byte* a = &m_data[m_offset], b = otherdata)
- {
- for (int i = 0; i < m_len; ++i)
- {
- if (a[i] != b[i])
- return false;
- }
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)) !=
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(otherdata), j)))
+ return false;
}
return true;
}
- public unsafe bool Equals(byte[] o)
+ public bool Equals(byte[] o)
{
if (o == null || m_len != o.Length)
return false;
- if (m_len < 8)
+ for (int i = m_offset, j = 0; i < m_offset + m_len; ++i, ++j)
{
- for (int i = m_offset, j = 0; i < m_offset + m_len; ++i, ++j)
- {
- if (m_data[i] != o[j])
- return false;
- }
- return true;
- }
-
- fixed (byte* a = &m_data[m_offset], b = o)
- {
- for (int i = 0; i < m_len; ++i)
- {
- if (a[i] != b[i])
- return false;
- }
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)) !=
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(o), j)))
+ return false;
}
return true;
}
@@ -365,19 +314,36 @@ public bool Equals(string s)
{
if(string.IsNullOrEmpty(s))
return m_len == 0;
- osUTF8 o = new osUTF8(s);
+ osUTF8 o = new(s);
return Equals(o);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(osUTF8Slice value1, osUTF8Slice value2)
+ {
+ if (value1 is null)
+ return value2 is null;
+ return value1.Equals(value2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(osUTF8Slice value1, osUTF8Slice value2)
+ {
+ if (value1 is null)
+ return value2 is not null;
+ return !value1.Equals(value2);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(char c)
{
- return m_len == 1 && m_data[m_offset] == (byte)c;
+ return m_len == 1 &&
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == (byte)c;
}
public unsafe bool ACSIILowerEquals(osUTF8 o)
{
- if (o == null || m_len != o.m_len)
+ if (o is null || m_len != o.m_len)
return false;
fixed (byte* a = &m_data[m_offset], b = o.m_data)
@@ -522,7 +488,7 @@ public void AppendASCII(char c)
{
int indx = m_offset + m_len;
CheckCapacity(ref indx, 1);
- m_data[indx] = (byte)c;
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), indx)) = (byte)c;
++m_len;
}
@@ -647,22 +613,22 @@ public osUTF8Slice SubUTF8(int start, int len)
int last = start + len - 1;
// cut at code points;
- if (start > 0 && (m_data[start] & 0x80) != 0)
+ if (start > 0 && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start)) & 0x80) != 0)
{
do
{
--last;
}
- while (start > 0 && (m_data[start] & 0xc0) != 0xc0);
+ while (start > 0 && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start)) & 0xc0) != 0xc0);
}
- if (last > start && (m_data[last] & 0x80) != 0)
+ if (last > start && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)) & 0x80) != 0)
{
do
{
--last;
}
- while (last > start && (m_data[last] & 0xc0) != 0xc0);
+ while (last > start && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)) & 0xc0) != 0xc0);
}
return new osUTF8Slice(m_data, start, last - start + 1);
@@ -709,22 +675,22 @@ public void SubUTF8Self(int start, int len)
int last = start + len - 1;
// cut at code points;
- if (start > 0 && (m_data[start] & 0x80) != 0)
+ if (start > 0 && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start)) & 0x80) != 0)
{
do
{
--last;
}
- while (start > 0 && (m_data[start] & 0xc0) != 0xc0);
+ while (start > 0 && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start)) & 0xc0) != 0xc0);
}
- if (last > start && (m_data[last] & 0x80) != 0)
+ if (last > start && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)) & 0x80) != 0)
{
do
{
--last;
}
- while (last > start && (m_data[last] & 0xc0) != 0xc0);
+ while (last > start && (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)) & 0xc0) != 0xc0);
}
m_offset = start;
@@ -770,7 +736,7 @@ private bool checkAny(byte b, char[] chars)
// inplace remove white spaces at start
public void SelfTrimStart()
{
- while (m_len > 0 && m_data[m_offset] == 0x20)
+ while (m_len > 0 && Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == 0x20)
{
++m_offset;
--m_len;
@@ -779,7 +745,7 @@ public void SelfTrimStart()
public void SelfTrimStart(byte b)
{
- while (m_len > 0 && m_data[m_offset] == b)
+ while (m_len > 0 && Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == b)
{
++m_offset;
--m_len;
@@ -788,7 +754,7 @@ public void SelfTrimStart(byte b)
public void SelfTrimStart(byte[] b)
{
- while (m_len > 0 && checkAny(m_data[m_offset], b))
+ while (m_len > 0 && checkAny(Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)), b))
{
++m_offset;
--m_len;
@@ -797,7 +763,7 @@ public void SelfTrimStart(byte[] b)
public void SelfTrimStart(char[] b)
{
- while (m_len > 0 && checkAny(m_data[m_offset], b))
+ while (m_len > 0 && checkAny(Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)), b))
{
++m_offset;
--m_len;
@@ -809,7 +775,7 @@ public void SelfTrimEnd()
if (m_len == 0)
return;
int last = m_offset + m_len - 1;
- while (m_len > 0 && m_data[last] == 0x20)
+ while (m_len > 0 && Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)) == 0x20)
{
--last;
--m_len;
@@ -821,7 +787,7 @@ public void SelfTrimEnd(byte b)
if (m_len == 0)
return;
int last = m_offset + m_len - 1;
- while (m_len > 0 && m_data[last] == b)
+ while (m_len > 0 && Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)) == b)
{
--last;
--m_len;
@@ -833,7 +799,7 @@ public void SelfTrimEnd(byte[] b)
if (m_len == 0)
return;
int last = m_offset + m_len - 1;
- while (m_len > 0 && checkAny(m_data[last], b))
+ while (m_len > 0 && checkAny(Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)), b))
{
--last;
--m_len;
@@ -845,7 +811,7 @@ public void SelfTrimEnd(char[] b)
if (m_len == 0)
return;
int last = m_offset + m_len - 1;
- while (m_len > 0 && checkAny(m_data[last], b))
+ while (m_len > 0 && checkAny(Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), last)), b))
{
--last;
--m_len;
@@ -1023,22 +989,22 @@ public bool StartsWith(string s)
public bool StartsWith(byte b)
{
- return m_data[m_offset] == b;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == b;
}
public bool StartsWith(char b)
{
- return m_data[m_offset] == (byte)b;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == (byte)b;
}
public bool EndsWith(byte b)
{
- return m_data[m_offset + m_len - 1] == b;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset + m_len - 1)) == b;
}
public bool EndsWith(char b)
{
- return m_data[m_offset + m_len - 1] == (byte)b;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset + m_len - 1)) == (byte)b;
}
public unsafe bool EndsWith(osUTF8Slice other)
@@ -1100,22 +1066,9 @@ public bool EndsWith(string s)
public unsafe int IndexOf(byte b)
{
- if (m_len > 8)
- {
- fixed (byte* a = &m_data[m_offset])
- {
- for (int i = 0; i < m_len; ++i)
- {
- if (a[i] == b)
- return i;
- }
- return -1;
- }
- }
-
for (int i = m_offset; i < m_offset + m_len; ++i)
{
- if (m_data[i] == b)
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)) == b)
return i - m_offset;
}
return -1;
@@ -1210,48 +1163,24 @@ public int IndexOf(string s)
return IndexOf(o);
}
- public unsafe int IndexOfAny(byte[] b)
+ public int IndexOfAny(byte[] b)
{
- if (m_len < 8)
- {
- for (int i = m_offset; i < m_offset + m_len; ++i)
- {
- if (checkAny(m_data[i], b))
- return i - m_offset;
- }
- return -1;
- }
- fixed (byte* a = &m_data[m_offset])
+ for (int i = m_offset; i < m_offset + m_len; ++i)
{
- for (int i = 0; i < m_len; ++i)
- {
- if (checkAny(a[i], b))
- return i;
- }
- return -1;
+ if (checkAny(Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)), b))
+ return i - m_offset;
}
+ return -1;
}
- public unsafe int IndexOfAny(char[] b)
+ public int IndexOfAny(char[] b)
{
- if (m_len < 8)
- {
- for (int i = m_offset; i < m_offset + m_len; ++i)
- {
- if (checkAny(m_data[i], b))
- return i - m_offset;
- }
- return -1;
- }
- fixed (byte* a = &m_data[m_offset])
+ for (int i = m_offset; i < m_offset + m_len; ++i)
{
- for (int i = 0; i < m_len; ++i)
- {
- if (checkAny(a[i], b))
- return i;
- }
- return -1;
+ if (checkAny(Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i)), b))
+ return i - m_offset;
}
+ return -1;
}
public bool Contains(osUTF8Slice other)
@@ -1363,35 +1292,15 @@ public unsafe bool ReadLine(out osUTF8Slice line)
int lineend = -1;
byte b = 0;
- if (m_len < 8)
- {
- for (int i = m_offset; i < m_offset + m_len; ++i)
- {
- b = m_data[i];
- if (b == (byte)'\r' || b == (byte)'\n')
- {
- if (i > 0 && m_data[i - 1] == (byte)'\\')
- continue;
- lineend = i;
- break;
- }
- }
- }
- else
+ for (int i = m_offset; i < m_offset + m_len; ++i)
{
- fixed (byte* a = &m_data[m_offset])
+ b = Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i));
+ if (b == (byte)'\r' || b == (byte)'\n')
{
- for (int i = 0; i < m_len; ++i)
- {
- b = a[i];
- if (b == (byte)'\r' || b == (byte)'\n')
- {
- if (i > 0 && a[i - 1] == (byte)'\\')
- continue;
- lineend = i + m_offset;
- break;
- }
- }
+ if (i > 0 && Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i - 1)) == (byte)'\\')
+ continue;
+ lineend = i;
+ break;
}
}
@@ -1425,7 +1334,7 @@ public unsafe bool ReadLine(out osUTF8Slice line)
if (b == (byte)'\r')
{
- if (m_data[m_offset] == (byte)'\n')
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == (byte)'\n')
{
++m_offset;
--m_len;
@@ -1445,35 +1354,15 @@ public unsafe bool SkipLine()
int lineend = -1;
byte b = 0;
- if (m_len < 8)
+ for (int i = m_offset; i < m_offset + m_len; ++i)
{
- for (int i = m_offset; i < m_offset + m_len; ++i)
+ b = Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i));
+ if (b == (byte)'\r' || b == (byte)'\n')
{
- b = m_data[i];
- if (b == (byte)'\r' || b == (byte)'\n')
- {
- if (i > 0 && m_data[i - 1] == (byte)'\\')
- continue;
- lineend = i;
- break;
- }
- }
- }
- else
- {
- fixed (byte* a = &m_data[m_offset])
- {
- for (int i = 0; i < m_len; ++i)
- {
- b = a[i];
- if (b == (byte)'\r' || b == (byte)'\n')
- {
- if (i > 0 && a[i - 1] == (byte)'\\')
- continue;
- lineend = i + m_offset;
- break;
- }
- }
+ if (i > 0 && Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), i - 1)) == (byte)'\\')
+ continue;
+ lineend = i;
+ break;
}
}
@@ -1504,7 +1393,7 @@ public unsafe bool SkipLine()
if (b == (byte)'\r')
{
- if (m_data[m_offset] == (byte)'\n')
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), m_offset)) == (byte)'\n')
{
++m_offset;
--m_len;
@@ -1581,12 +1470,12 @@ public bool TryParseInt(out int res)
len += start;
bool neg = false;
- if (m_data[start] == (byte)'-')
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start)) == (byte)'-')
{
neg = true;
++start;
}
- else if (m_data[start] == (byte)'+')
+ else if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start)) == (byte)'+')
++start;
int b;
@@ -1594,7 +1483,7 @@ public bool TryParseInt(out int res)
{
while (start < len)
{
- b = m_data[start];
+ b = Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(m_data), start));
b -= (byte)'0';
if (b < 0 || b > 9)
break;
@@ -1625,12 +1514,12 @@ public static bool TryParseInt(osUTF8Slice t, out int res)
len += start;
bool neg = false;
- if (data[start] == (byte)'-')
+ if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(data), start)) == (byte)'-')
{
neg = true;
++start;
}
- else if (data[start] == (byte)'+')
+ else if (Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(data), start)) == (byte)'+')
++start;
int b;
@@ -1638,7 +1527,7 @@ public static bool TryParseInt(osUTF8Slice t, out int res)
{
while (start < len)
{
- b = data[start];
+ b = Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(data), start));
b -= (byte)'0';
if (b < 0 || b > 9)
break;
@@ -1684,43 +1573,113 @@ public unsafe static bool TryParseUUID(osUTF8Slice inp, out UUID result)
if (val[13] != '-' || val[18] != '-' || val[23] != '-')
return false;
+ if (Sse42.IsSupported)
+ {
+ Vector128 input = Unsafe.As>(ref Unsafe.AsRef(val));
+ Vector128 upper = Ssse3.Shuffle(input, Vector128.Create(0, 2, 4, 6, 9, 11, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lower = Ssse3.Shuffle(input, Vector128.Create(1, 3, 5, 7, 10, 12, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 16 + 3));
+ Vector128 upperhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 2, 5, 7, 9, 11, 13, 15));
+ Vector128 lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1, 3, 6, 8, 10, 12, 14, 0xff));
+ upper = Sse2.Or(upper, upperhalf);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ upper = Sse41.Insert(upper, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 16)), 7);
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 17)), 7);
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 35)), 15);
+
+ Vector128 charf = Vector128.Create((byte)'f');
+ Vector128 tmpcmp = Sse2.Subtract(charf, lower);
+ int cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+
+ tmpcmp = Sse2.Subtract(charf, upper);
+ cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+
+ Vector128 charTolower = Vector128.Create((byte)0x20);
+ Vector128 lowerLetters = Sse2.Or(lower, charTolower);
+ Vector128 upperLetters = Sse2.Or(upper, charTolower);
+
+ Vector128 letterTohex = Vector128.Create((byte)('a' - '0' - 10));
+ lowerLetters = Sse2.Subtract(lowerLetters, letterTohex);
+ upperLetters = Sse2.Subtract(upperLetters, letterTohex);
+
+ Vector128 char9 = Vector128.Create((byte)'9');
+ Vector128 above9lower = (Sse2.CompareGreaterThan(lower.AsSByte(), char9.AsSByte())).AsByte();
+
+ Vector128 ten = Vector128.Create((byte)('0' + 10));
+ tmpcmp = Sse2.Subtract(lowerLetters, ten);
+ tmpcmp = Sse2.And(tmpcmp, above9lower);
+ cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+ Vector128 above9upper = (Sse2.CompareGreaterThan(upper.AsSByte(), char9.AsSByte())).AsByte();
+
+ tmpcmp = Sse2.Subtract(upperLetters, ten);
+ tmpcmp = Sse2.And(tmpcmp, above9upper);
+ cmp = Sse2.MoveMask(tmpcmp);
+ if (cmp != 0)
+ throw new Exception("bad");
+
+ lower = Sse41.BlendVariable(lower, lowerLetters, above9lower);
+ upper = Sse41.BlendVariable(upper, upperLetters, above9upper);
+ Vector128 charzero = Vector128.Create((byte)'0');
+ lower = Sse2.Subtract(lower, charzero);
+ cmp = Sse2.MoveMask(lower);
+ if (cmp != 0)
+ throw new Exception("bad");
+ upper = Sse2.Subtract(upper, charzero);
+ cmp = Sse2.MoveMask(upper);
+ if (cmp != 0)
+ throw new Exception("bad");
+ upper = Sse2.ShiftLeftLogical(upper.AsUInt16(), 4).AsByte();
+ lower = Sse2.Or(lower, upper);
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref Unsafe.AsRef(in result)) = lower;
+ return true;
+ }
+
if (BitConverter.IsLittleEndian)
{
- result.bytea3 = (byte)Utils.HexToByte(val, 0);
- result.bytea2 = (byte)Utils.HexToByte(val, 2);
- result.bytea1 = (byte)Utils.HexToByte(val, 4);
- result.bytea0 = (byte)Utils.HexToByte(val, 6);
+ result.bytea3 = Utils.HexToByte(val, 0);
+ result.bytea2 = Utils.HexToByte(val, 2);
+ result.bytea1 = Utils.HexToByte(val, 4);
+ result.bytea0 = Utils.HexToByte(val, 6);
- result.byteb1 = (byte)Utils.HexToByte(val, 9);
- result.byteb0 = (byte)Utils.HexToByte(val, 11);
+ result.byteb1 = Utils.HexToByte(val, 9);
+ result.byteb0 = Utils.HexToByte(val, 11);
- result.bytec1 = (byte)Utils.HexToByte(val, 14);
- result.bytec0 = (byte)Utils.HexToByte(val, 16);
+ result.bytec1 = Utils.HexToByte(val, 14);
+ result.bytec0 = Utils.HexToByte(val, 16);
}
else
{
- result.bytea0 = (byte)Utils.HexToByte(val, 0);
- result.bytea1 = (byte)Utils.HexToByte(val, 2);
- result.bytea2 = (byte)Utils.HexToByte(val, 4);
- result.bytea3 = (byte)Utils.HexToByte(val, 6);
+ result.bytea0 = Utils.HexToByte(val, 0);
+ result.bytea1 = Utils.HexToByte(val, 2);
+ result.bytea2 = Utils.HexToByte(val, 4);
+ result.bytea3 = Utils.HexToByte(val, 6);
- result.byteb0 = (byte)Utils.HexToByte(val, 9);
- result.byteb1 = (byte)Utils.HexToByte(val, 11);
+ result.byteb0 = Utils.HexToByte(val, 9);
+ result.byteb1 = Utils.HexToByte(val, 11);
- result.bytec0 = (byte)Utils.HexToByte(val, 14);
- result.bytec1 = (byte)Utils.HexToByte(val, 16);
+ result.bytec0 = Utils.HexToByte(val, 14);
+ result.bytec1 = Utils.HexToByte(val, 16);
}
- result.d = (byte)Utils.HexToByte(val, 19);
- result.e = (byte)Utils.HexToByte(val, 21);
+ result.d = Utils.HexToByte(val, 19);
+ result.e = Utils.HexToByte(val, 21);
- result.f = (byte)Utils.HexToByte(val, 24);
- result.g = (byte)Utils.HexToByte(val, 26);
- result.h = (byte)Utils.HexToByte(val, 28);
- result.i = (byte)Utils.HexToByte(val, 30);
- result.j = (byte)Utils.HexToByte(val, 32);
- result.k = (byte)Utils.HexToByte(val, 34);
+ result.f = Utils.HexToByte(val, 24);
+ result.g = Utils.HexToByte(val, 26);
+ result.h = Utils.HexToByte(val, 28);
+ result.i = Utils.HexToByte(val, 30);
+ result.j = Utils.HexToByte(val, 32);
+ result.k = Utils.HexToByte(val, 34);
return true;
}
else
diff --git a/OpenMetaverse.Types/OpenMetaverse.Types.csproj b/OpenMetaverse.Types/OpenMetaverse.Types.csproj
index cd2892d1..8356b85c 100644
--- a/OpenMetaverse.Types/OpenMetaverse.Types.csproj
+++ b/OpenMetaverse.Types/OpenMetaverse.Types.csproj
@@ -1,7 +1,7 @@
Local
- net48;netstandard2.0
+ net6.0
OpenMetaverse
1591,1574,0419,0618
True
@@ -13,4 +13,4 @@
-
\ No newline at end of file
+
diff --git a/OpenMetaverse.Types/Quaternion.cs b/OpenMetaverse.Types/Quaternion.cs
index be4d5475..2a462e81 100644
--- a/OpenMetaverse.Types/Quaternion.cs
+++ b/OpenMetaverse.Types/Quaternion.cs
@@ -28,6 +28,9 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Globalization;
+using System.Text;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.Intrinsics;
namespace OpenMetaverse
{
@@ -44,6 +47,13 @@ public struct Quaternion : IEquatable
/// W value
public float W;
+ public enum MainAxis : int
+ {
+ X = 0,
+ Y = 1,
+ Z = 2
+ }
+
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -78,7 +88,7 @@ public Quaternion(float x, float y, float z)
Z = z;
float xyzsum = 1f - (X * X) - (Y * Y) - (Z * Z);
- W = (xyzsum > 1e-6f) ? (float)Math.Sqrt(xyzsum) : 0;
+ W = (xyzsum > 1e-6f) ? MathF.Sqrt(xyzsum) : 0;
}
///
@@ -100,46 +110,103 @@ public Quaternion(byte[] byteArray, int pos, bool normalized)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Quaternion(Quaternion q)
{
- X = q.X;
- Y = q.Y;
- Z = q.Z;
- W = q.W;
+ this = q;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Quaternion(Vector128 q) : this()
+ {
+ Unsafe.As>(ref Unsafe.AsRef(this)) = q;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Quaternion(MainAxis BaseAxis, float angle)
+ {
+ switch (BaseAxis)
+ {
+ case MainAxis.X:
+ W = MathF.Cos(0.5f * angle);
+ X = MathF.Sqrt(1.0f - W * W);
+ Y = 0;
+ Z = 0;
+ break;
+ case MainAxis.Y:
+ W = MathF.Cos(0.5f * angle);
+ Y = MathF.Sqrt(1.0f - W * W);
+ X = 0;
+ Z = 0;
+ break;
+ case MainAxis.Z:
+ W = MathF.Cos(0.5f * angle);
+ Z = MathF.Sqrt(1.0f - W * W);
+ X = 0;
+ Y = 0;
+ break;
+ default: //error
+ X = 0;
+ Y = 0;
+ Z = 0;
+ W = 1;
+ break;
+ }
}
#endregion Constructors
#region Public Methods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool ApproxEquals(Quaternion quat)
+ public readonly bool ApproxEquals(Quaternion quat)
{
// assume normalized
- return Math.Abs(quat.X - X) < 1e-6f &&
- Math.Abs(quat.Y - Y) < 1e-6f &&
- Math.Abs(quat.Z - Z) < 1e-6f;
+ return MathF.Abs(quat.W - W) < 1e-6f &&
+ MathF.Abs(quat.Z - Z) < 1e-6f &&
+ MathF.Abs(quat.X - X) < 1e-6f;
}
+ /* not faster
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly bool ApproxEquals2(in Quaternion quat)
+ {
+ if (Sse.IsSupported)
+ {
+ Vector128 tol = Vector128.Create(1e-6f);
+
+ Vector128 a = Unsafe.As>(ref Unsafe.AsRef(this));
+ Vector128 c = Sse.CompareEqual(tol, tol);
+
+ Vector128 b = Unsafe.As>(ref Unsafe.AsRef(quat));
+ c = Sse2.ShiftRightLogical(c.AsInt32(), 1).AsSingle();
+
+ a = Sse.Subtract(a, b);
+ a = Sse.And(a, c);
+ a = Sse.CompareLessThan(a, tol);
+ int res = Sse.MoveMask(a);
+ return res == 0x0f;
+ }
+ // assume normalized
+ return MathF.Abs(quat.X - X) < 1e-6f &&
+ MathF.Abs(quat.Y - Y) < 1e-6f &&
+ MathF.Abs(quat.Z - Z) < 1e-6f;
+ }
+ */
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool ApproxEquals(Quaternion quat, float tolerance)
+ public readonly bool ApproxEquals(Quaternion quat, float tolerance)
{
// assume normalized
- return Math.Abs(quat.X - X) < tolerance &&
- Math.Abs(quat.Y - Y) < tolerance &&
- Math.Abs(quat.Z - Z) < tolerance;
+ return MathF.Abs(quat.W - W) < tolerance &&
+ MathF.Abs(quat.Z - Z) < tolerance &&
+ MathF.Abs(quat.X - X) < tolerance;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsIdentity()
+ public readonly bool IsIdentity()
{
// assume normalized
- if(W > (1.0f - 1e-6f))
- return true;
- if (W < -(1.0f - 1e-6f))
- return true;
- return false;
+ return MathF.Abs(W) > (1.0f - 1e-6f);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsIdentityOrZero()
+ public readonly bool IsIdentityOrZero()
{
// assume normalized
if (X != 0)
@@ -152,27 +219,60 @@ public bool IsIdentityOrZero()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float Length()
+ public readonly unsafe float Length()
{
- return (float)Math.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W));
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref Unsafe.AsRef(this));
+ q = Sse41.DotProduct(q, q, 0xf1);
+ return MathF.Sqrt(q.ToScalar());
+ }
+ else
+ return MathF.Sqrt((X * X) + (Y * Y) + (Z * Z) + (W * W));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float LengthSquared()
+ public readonly unsafe float LengthSquared()
{
- return (X * X) + (Y * Y) + (Z * Z) + (W * W);
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref Unsafe.AsRef(this));
+ q = Sse41.DotProduct(q, q, 0xf1);
+ return q.ToScalar();
+ }
+ else
+ return (X * X) + (Y * Y) + (Z * Z) + (W * W);
}
///
/// Normalizes the quaternion
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Normalize()
+ public unsafe void Normalize()
{
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref Unsafe.AsRef(this));
+ Vector128 d = Sse41.DotProduct(q, q, 0xff);
+ float m = d.ToScalar();
+ if (m > 1e-6f)
+ {
+ d = Sse.Sqrt(d);
+ q = Sse.Divide(q, d);
+ //d = Sse.ReciprocalSqrt(d);
+ //q = Sse.Multiply(q, d);
+ Unsafe.As>(ref this) = q;
+ return;
+ }
+ q = Vector128.Create(0f, 0f, 0f, 1f);
+ Unsafe.As>(ref this) = q;
+ return;
+ }
+
float mag = LengthSquared();
if (mag > 1e-6f)
{
- float oomag = 1f / (float)Math.Sqrt(mag);
+ float oomag = 1f / MathF.Sqrt(mag);
X *= oomag;
Y *= oomag;
Z *= oomag;
@@ -202,10 +302,10 @@ public void Invert()
if (len > 1e-6f)
{
len = -1.0f / len;
- X = X * len;
- Y = Y * len;
- Z = Z * len;
- W = -W * len;
+ X *= len;
+ Y *= len;
+ Z *= len;
+ W *= -len;
}
else
{
@@ -217,33 +317,54 @@ public void Invert()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float Dot(Quaternion q2)
- {
- return (X * q2.X) + (Y * q2.Y) + (Z * q2.Z) + (W * q2.W);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float Dot(ref Quaternion q2)
+ public readonly float Dot(Quaternion q2)
{
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref Unsafe.AsRef(this));
+ Vector128 d = Unsafe.As>(ref q2);
+ d = Sse41.DotProduct(q, d, 0xf1);
+ return d.ToScalar();
+ }
return (X * q2.X) + (Y * q2.Y) + (Z * q2.Z) + (W * q2.W);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Add(Quaternion quaternion2)
+ public void Add(in Quaternion quaternion2)
{
- X += quaternion2.X;
- Y += quaternion2.Y;
- Z += quaternion2.Z;
- W += quaternion2.W;
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref Unsafe.AsRef(this));
+ Vector128 d = Unsafe.As>(ref Unsafe.AsRef(quaternion2));
+ d = Sse.Add(q, d);
+ Unsafe.As>(ref Unsafe.AsRef(this)) = d;
+ }
+ else
+ {
+ X += quaternion2.X;
+ Y += quaternion2.Y;
+ Z += quaternion2.Z;
+ W += quaternion2.W;
+ }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Sub(Quaternion quaternion2)
+ public void Sub(in Quaternion quaternion2)
{
- X -= quaternion2.X;
- Y -= quaternion2.Y;
- Z -= quaternion2.Z;
- W -= quaternion2.W;
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref Unsafe.AsRef(this));
+ Vector128 d = Unsafe.As>(ref Unsafe.AsRef(quaternion2));
+ d = Sse.Subtract(q, d);
+ Unsafe.As>(ref Unsafe.AsRef(this)) = d;
+ }
+ else
+ {
+ X -= quaternion2.X;
+ Y -= quaternion2.Y;
+ Z -= quaternion2.Z;
+ W -= quaternion2.W;
+ }
}
///
@@ -262,7 +383,7 @@ public void FromBytes(byte[] byteArray, int pos, bool normalized)
if (normalized)
{
float xyzsum = 1f - (X * X) - (Y * Y) - (Z * Z);
- W = (xyzsum > 1e-6f) ? (float)Math.Sqrt(xyzsum) : 0f;
+ W = (xyzsum > 1e-6f) ? MathF.Sqrt(xyzsum) : 0f;
}
else
{
@@ -275,16 +396,16 @@ public void FromBytes(byte[] byteArray, int pos, bool normalized)
///
/// A 12 byte array containing normalized X, Y, and Z floating
/// point values in order using little endian byte ordering
- public byte[] GetBytes()
+ public readonly byte[] GetBytes()
{
byte[] bytes = new byte[12];
float norm = LengthSquared();
if (norm > 1e-6f || W < 0.9999f)
{
if (W < 0f)
- norm = -1f / (float)Math.Sqrt(norm);
+ norm = -1f / MathF.Sqrt(norm);
else
- norm = 1f / (float)Math.Sqrt(norm);
+ norm = 1f / MathF.Sqrt(norm);
Utils.FloatToBytesSafepos(norm * X, bytes, 0);
Utils.FloatToBytesSafepos(norm * Y, bytes, 4);
Utils.FloatToBytesSafepos(norm * Z, bytes, 8);
@@ -304,24 +425,159 @@ public byte[] GetBytes()
/// Destination byte array
/// Position in the destination array to start
/// writing. Must be at least 12 bytes before the end of the array
- public void ToBytes(byte[] dest, int pos)
+ public readonly unsafe void ToBytes(byte[] dest, int pos)
{
float norm = LengthSquared();
if (norm > 1e-6f || norm < 0.9999f)
{
if (W < 0f)
- norm = -1f / (float)Math.Sqrt(norm);
+ norm = -1f / MathF.Sqrt(norm);
else
- norm = 1f / (float)Math.Sqrt(norm);
- Utils.FloatToBytesSafepos(norm * X, dest, pos);
- Utils.FloatToBytesSafepos(norm * Y, dest, pos + 4);
- Utils.FloatToBytesSafepos(norm * Z, dest, pos + 8);
+ norm = 1f / MathF.Sqrt(norm);
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ {
+ *(float*)(d + pos) = norm * X;
+ *(float*)(d + pos + 4) = norm * Y;
+ *(float*)(d + pos + 8) = norm * Z;
+ }
+ }
+ else
+ {
+ Utils.FloatToBytesSafepos(norm * X, dest, pos);
+ Utils.FloatToBytesSafepos(norm * Y, dest, pos + 4);
+ Utils.FloatToBytesSafepos(norm * Z, dest, pos + 8);
+ }
}
else
{
- Utils.FloatToBytesSafepos(0, dest, pos);
- Utils.FloatToBytesSafepos(0, dest, pos + 4);
- Utils.FloatToBytesSafepos(0, dest, pos + 8);
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ {
+ *(long*)(d + pos) = 0;
+ *(int*)(d + pos + 8) = 0;
+ }
+ }
+ else
+ {
+ Utils.FloatToBytesSafepos(0, dest, pos);
+ Utils.FloatToBytesSafepos(0, dest, pos + 4);
+ Utils.FloatToBytesSafepos(0, dest, pos + 8);
+ }
+ }
+ }
+
+ public readonly unsafe void ToBytes(byte* dest)
+ {
+ float norm = LengthSquared();
+ if (norm > 1e-6f || norm < 0.9999f)
+ {
+ if (W < 0f)
+ norm = -1f / MathF.Sqrt(norm);
+ else
+ norm = 1f / MathF.Sqrt(norm);
+ if (Utils.CanDirectCopyLE)
+ {
+ *(float*)(dest) = norm * X;
+ *(float*)(dest + 4) = norm * Y;
+ *(float*)(dest + 8) = norm * Z;
+ }
+ else
+ {
+ Utils.FloatToBytes(norm * X, dest);
+ Utils.FloatToBytes(norm * Y, dest + 4);
+ Utils.FloatToBytes(norm * Z, dest + 8);
+ }
+ }
+ else
+ {
+ if (Utils.CanDirectCopyLE)
+ {
+ *(long*)dest = 0;
+ *(int*)(dest + 8) = 0;
+ }
+ else
+ {
+ Utils.FloatToBytes(0, dest);
+ Utils.FloatToBytes(0, dest + 4);
+ Utils.FloatToBytes(0, dest + 8);
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ToShortsBytes(byte[] dest, int pos)
+ {
+ ushort sx = Utils.FloatToUnitUInt16(X);
+ ushort sy = Utils.FloatToUnitUInt16(Y);
+ ushort sz = Utils.FloatToUnitUInt16(Z);
+ ushort sw = Utils.FloatToUnitUInt16(W);
+
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ {
+ *(ushort*)(d + pos) = sx;
+ *(ushort*)(d + pos + 2) = sy;
+ *(ushort*)(d + pos + 4) = sz;
+ *(ushort*)(d + pos + 6) = sw;
+ }
+ }
+ else
+ {
+ Utils.UInt16ToBytes(sx, dest, pos);
+ Utils.UInt16ToBytes(sy, dest, pos + 2);
+ Utils.UInt16ToBytes(sz, dest, pos + 4);
+ Utils.UInt16ToBytes(sw, dest, pos + 6);
+ }
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ToShortsBytes(byte* dest, int pos)
+ {
+ ushort sx = Utils.FloatToUnitUInt16(X);
+ ushort sy = Utils.FloatToUnitUInt16(Y);
+ ushort sz = Utils.FloatToUnitUInt16(Z);
+ ushort sw = Utils.FloatToUnitUInt16(W);
+
+ if (Utils.CanDirectCopyLE)
+ {
+ *(ushort*)(dest + pos) = sx;
+ *(ushort*)(dest + pos + 2) = sy;
+ *(ushort*)(dest + pos + 4) = sz;
+ *(ushort*)(dest + pos + 6) = sw;
+ }
+ else
+ {
+ Utils.UInt16ToBytes(sx, dest, pos);
+ Utils.UInt16ToBytes(sy, dest, pos + 2);
+ Utils.UInt16ToBytes(sz, dest, pos + 4);
+ Utils.UInt16ToBytes(sw, dest, pos + 6);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ToShortsBytes(byte* dest)
+ {
+ ushort sx = Utils.FloatToUnitUInt16(X);
+ ushort sy = Utils.FloatToUnitUInt16(Y);
+ ushort sz = Utils.FloatToUnitUInt16(Z);
+ ushort sw = Utils.FloatToUnitUInt16(W);
+
+ if (Utils.CanDirectCopyLE)
+ {
+ *(ushort*)(dest) = sx;
+ *(ushort*)(dest + 2) = sy;
+ *(ushort*)(dest + 4) = sz;
+ *(ushort*)(dest + 6) = sw;
+ }
+ else
+ {
+ Utils.UInt16ToBytes(sx, dest);
+ Utils.UInt16ToBytes(sy, dest + 2);
+ Utils.UInt16ToBytes(sz, dest + 4);
+ Utils.UInt16ToBytes(sw, dest + 6);
}
}
@@ -331,8 +587,10 @@ public void ToBytes(byte[] dest, int pos)
/// X euler angle
/// Y euler angle
/// Z euler angle
- public void GetEulerAngles(out float roll, out float pitch, out float yaw)
+ public readonly void GetEulerAngles(out float roll, out float pitch, out float yaw)
{
+ const float halfpi = MathF.PI / 2f;
+
roll = 0f;
pitch = 0f;
yaw = 0f;
@@ -345,7 +603,7 @@ public void GetEulerAngles(out float roll, out float pitch, out float yaw)
float tZ = Z * Z;
float tW = W * W;
float m = tX + tY + tZ + tW;
- if (Math.Abs(m) < 0.0001f)
+ if (MathF.Abs(m) < 0.0001f)
return;
float n = 2 * (Y * W + X * Z);
@@ -353,21 +611,21 @@ public void GetEulerAngles(out float roll, out float pitch, out float yaw)
if (p > 0f)
{
- roll = (float)Math.Atan2(2.0f * (X * W - Y * Z), (-tX - tY + tZ + tW));
- pitch = (float)Math.Atan2(n, Math.Sqrt(p));
- yaw = (float)Math.Atan2(2.0f * (Z * W - X * Y), tX - tY - tZ + tW);
+ roll = MathF.Atan2(2.0f * (X * W - Y * Z), (-tX - tY + tZ + tW));
+ pitch = MathF.Atan2(n, MathF.Sqrt(p));
+ yaw = MathF.Atan2(2.0f * (Z * W - X * Y), tX - tY - tZ + tW);
}
else if (n > 0f)
{
roll = 0f;
- pitch = (float)(Math.PI / 2d);
+ pitch = halfpi;
yaw = (float)Math.Atan2((Z * W + X * Y), 0.5f - tX - tY);
}
else
{
roll = 0f;
- pitch = -(float)(Math.PI / 2d);
- yaw = (float)Math.Atan2((Z * W + X * Y), 0.5f - tX - tZ);
+ pitch = -halfpi;
+ yaw = MathF.Atan2((Z * W + X * Y), 0.5f - tX - tZ);
}
}
@@ -376,9 +634,9 @@ public void GetEulerAngles(out float roll, out float pitch, out float yaw)
///
/// Unit vector describing the axis
/// Angle around the axis, in radians
- public void GetAxisAngle(out Vector3 axis, out float angle)
+ public readonly void GetAxisAngle(out Vector3 axis, out float angle)
{
- Normalize();
+ //Normalize();
float ww = W * W;
if (ww > 0.9999f)
{
@@ -392,19 +650,19 @@ public void GetAxisAngle(out Vector3 axis, out float angle)
axis = new Vector3(-X, -Y, -Z);
else
axis = new Vector3(X, Y, Z);
- angle = (float)Math.PI;
+ angle = MathF.PI;
return;
}
- float sin = (float)Math.Sqrt(1.0f - ww);
+ float sin = MathF.Sqrt(1.0f - ww);
float invSin = 1.0f / sin;
if (W < 0)
invSin = -invSin;
axis = new Vector3(X, Y, Z) * invSin;
- angle = 2.0f * (float)Math.Acos(W);
- if (angle > Math.PI)
- angle = 2.0f * (float)Math.PI - angle;
+ angle = 2.0f * MathF.Acos(W);
+ if (angle > MathF.PI)
+ angle = 2.0f * MathF.PI - angle;
}
#endregion Public Methods
@@ -412,8 +670,16 @@ public void GetAxisAngle(out Vector3 axis, out float angle)
#region Static Methods
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Quaternion Add(Quaternion quaternion1, Quaternion quaternion2)
+ public static Quaternion Add(in Quaternion quaternion1, in Quaternion quaternion2)
{
+ if (Sse.IsSupported)
+ {
+ Vector128 a = Unsafe.As>(ref Unsafe.AsRef(quaternion1));
+ Vector128 b = Unsafe.As>(ref Unsafe.AsRef(quaternion2));
+ a = Sse.Add(a, b);
+ return new Quaternion(a);
+ }
+
return new Quaternion(
quaternion1.X + quaternion2.X,
quaternion1.Y + quaternion2.Y,
@@ -425,9 +691,16 @@ public static Quaternion Add(Quaternion quaternion1, Quaternion quaternion2)
/// Returns the conjugate (spatial inverse) of a quaternion
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Quaternion Conjugate(Quaternion quaternion)
+ public static Quaternion Conjugate(in Quaternion quaternion)
{
- return new Quaternion( -quaternion.X, -quaternion.Y, -quaternion.Z, quaternion.W);
+ if (Sse.IsSupported)
+ {
+ Vector128 d = Unsafe.As>(ref Unsafe.AsRef(quaternion));
+ Vector128 Mask = Vector128.Create(0x80000000, 0x80000000, 0x80000000, 0).AsSingle();
+ d = Sse.Xor(d, Mask);
+ return new Quaternion(d);
+ }
+ return new Quaternion(-quaternion.X, -quaternion.Y, -quaternion.Z, quaternion.W);
}
///
@@ -437,7 +710,7 @@ public static Quaternion Conjugate(Quaternion quaternion)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Quaternion CreateFromAxisAngle(float axisX, float axisY, float axisZ, float angle)
{
- Vector3 axis = new Vector3(axisX, axisY, axisZ);
+ Vector3 axis = new(axisX, axisY, axisZ);
return CreateFromAxisAngle(axis, angle);
}
@@ -453,8 +726,8 @@ public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
axis.Normalize();
angle *= 0.5f;
- float c = (float)Math.Cos(angle);
- float s = (float)Math.Sin(angle);
+ float c = MathF.Cos(angle);
+ float s = MathF.Sin(angle);
return new Quaternion(axis.X * s, axis.Y * s, axis.Z * s, c);
}
@@ -463,8 +736,8 @@ public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
public static Quaternion CreateRotationX(float angle)
{
angle *= 0.5f;
- float c = (float)Math.Cos(angle);
- float s = (float)Math.Sin(angle);
+ float c = MathF.Cos(angle);
+ float s = MathF.Sin(angle);
return new Quaternion(s, 0, 0, c);
}
@@ -473,8 +746,8 @@ public static Quaternion CreateRotationX(float angle)
public static Quaternion CreateRotationY(float angle)
{
angle *= 0.5f;
- float c = (float)Math.Cos(angle);
- float s = (float)Math.Sin(angle);
+ float c = MathF.Cos(angle);
+ float s = MathF.Sin(angle);
return new Quaternion(0, s, 0, c);
}
@@ -483,8 +756,8 @@ public static Quaternion CreateRotationY(float angle)
public static Quaternion CreateRotationZ(float angle)
{
angle *= 0.5f;
- float c = (float)Math.Cos(angle);
- float s = (float)Math.Sin(angle);
+ float c = MathF.Cos(angle);
+ float s = MathF.Sin(angle);
return new Quaternion(0, 0, s, c);
}
@@ -516,22 +789,22 @@ public static Quaternion CreateFromEulers(float roll, float pitch, float yaw)
throw new ArgumentException("Euler angles must be in radians");
roll *= 0.5f;
- double atCos = Math.Cos(roll);
- double atSin = Math.Sin(roll);
+ float atCos = MathF.Cos(roll);
+ float atSin = MathF.Sin(roll);
pitch *= 0.5f;
- double leftCos = Math.Cos(pitch);
- double leftSin = Math.Sin(pitch);
+ float leftCos = MathF.Cos(pitch);
+ float leftSin = MathF.Sin(pitch);
yaw *= 0.5f;
- double upCos = Math.Cos(yaw);
- double upSin = Math.Sin(yaw);
+ float upCos = MathF.Cos(yaw);
+ float upSin = MathF.Sin(yaw);
- double atLeftCos = atCos * leftCos;
- double atLeftSin = atSin * leftSin;
+ float atLeftCos = atCos * leftCos;
+ float atLeftSin = atSin * leftSin;
return new Quaternion(
- (float)(atSin * leftCos * upCos + atCos * leftSin * upSin),
- (float)(atCos * leftSin * upCos - atSin * leftCos * upSin),
- (float)(atLeftCos * upSin + atLeftSin * upCos),
- (float)(atLeftCos * upCos - atLeftSin * upSin)
+ atSin * leftCos * upCos + atCos * leftSin * upSin,
+ atCos * leftSin * upCos - atSin * leftCos * upSin,
+ atLeftCos * upSin + atLeftSin * upCos,
+ atLeftCos * upCos - atLeftSin * upSin
);
}
@@ -541,7 +814,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix3x3 matrix)
float n2;
if (num >= 0f)
{
- num = (float)Math.Sqrt((num + 1f));
+ num = MathF.Sqrt((num + 1f));
n2 = 0.5f / num;
return new Quaternion(
(matrix.M23 - matrix.M32) * n2,
@@ -551,7 +824,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix3x3 matrix)
}
if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
{
- num = (float)Math.Sqrt((((1f + matrix.M11) - matrix.M22) - matrix.M33));
+ num = MathF.Sqrt((((1f + matrix.M11) - matrix.M22) - matrix.M33));
n2 = 0.5f / num;
return new Quaternion(
0.5f * num,
@@ -561,7 +834,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix3x3 matrix)
}
if (matrix.M22 > matrix.M33)
{
- num = (float)Math.Sqrt((((1f + matrix.M22) - matrix.M11) - matrix.M33));
+ num = MathF.Sqrt((((1f + matrix.M22) - matrix.M11) - matrix.M33));
n2 = 0.5f / num;
return new Quaternion(
(matrix.M21 + matrix.M12) * n2,
@@ -570,7 +843,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix3x3 matrix)
(matrix.M31 - matrix.M13) * n2);
}
- num = (float)Math.Sqrt((((1f + matrix.M33) - matrix.M11) - matrix.M22));
+ num = MathF.Sqrt((((1f + matrix.M33) - matrix.M11) - matrix.M22));
n2 = 0.5f / num;
return new Quaternion(
(matrix.M31 + matrix.M13) * n2,
@@ -585,7 +858,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4 matrix)
float n2;
if (num >= 0f)
{
- num = (float)Math.Sqrt((num + 1f));
+ num = MathF.Sqrt((num + 1f));
n2 = 0.5f / num;
return new Quaternion(
(matrix.M23 - matrix.M32) * n2,
@@ -595,7 +868,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4 matrix)
}
if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
{
- num = (float)Math.Sqrt((((1f + matrix.M11) - matrix.M22) - matrix.M33));
+ num = MathF.Sqrt((((1f + matrix.M11) - matrix.M22) - matrix.M33));
n2 = 0.5f / num;
return new Quaternion(
0.5f * num,
@@ -605,7 +878,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4 matrix)
}
if (matrix.M22 > matrix.M33)
{
- num = (float)Math.Sqrt((((1f + matrix.M22) - matrix.M11) - matrix.M33));
+ num = MathF.Sqrt((((1f + matrix.M22) - matrix.M11) - matrix.M33));
n2 = 0.5f / num;
return new Quaternion(
(matrix.M21 + matrix.M12) * n2,
@@ -614,7 +887,7 @@ public static Quaternion CreateFromRotationMatrix(Matrix4 matrix)
(matrix.M31 - matrix.M13) * n2);
}
- num = (float)Math.Sqrt((((1f + matrix.M33) - matrix.M11) - matrix.M22));
+ num = MathF.Sqrt((((1f + matrix.M33) - matrix.M11) - matrix.M22));
n2 = 0.5f / num;
return new Quaternion(
(matrix.M31 + matrix.M13) * n2,
@@ -632,6 +905,13 @@ public static Quaternion Divide(Quaternion q1, Quaternion q2)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Dot(Quaternion q1, Quaternion q2)
{
+ if (Sse41.IsSupported)
+ {
+ Vector128 q = Unsafe.As>(ref q1);
+ Vector128 d = Unsafe.As>(ref q2);
+ d = Sse41.DotProduct(q, d, 0xf1);
+ return d.ToScalar();
+ }
return (q1.X * q2.X) + (q1.Y * q2.Y) + (q1.Z * q2.Z) + (q1.W * q2.W);
}
@@ -657,7 +937,7 @@ public static Quaternion Inverse(Quaternion quaternion)
///
/// Spherical linear interpolation between two quaternions
///
- public static Quaternion Slerp(Quaternion q1, Quaternion q2, float amount)
+ public static Quaternion Slerp(Quaternion q1, in Quaternion q2, float amount)
{
float angle = Dot(q1, q2);
@@ -675,10 +955,10 @@ public static Quaternion Slerp(Quaternion q1, Quaternion q2, float amount)
if ((1f - angle) >= 0.05f)
{
// slerp
- float theta = (float)Math.Acos(angle);
- float invsintheta = 1f / (float)Math.Sin(theta);
- scale = (float)Math.Sin(theta * (1f - amount)) * invsintheta;
- invscale = (float)Math.Sin(theta * amount) * invsintheta;
+ float theta = MathF.Acos(angle);
+ float invsintheta = 1f / MathF.Sin(theta);
+ scale = MathF.Sin(theta * (1f - amount)) * invsintheta;
+ invscale = MathF.Sin(theta * amount) * invsintheta;
}
else
{
@@ -689,13 +969,14 @@ public static Quaternion Slerp(Quaternion q1, Quaternion q2, float amount)
}
else
{
- q2.X = -q1.Y;
- q2.Y = q1.X;
- q2.Z = -q1.W;
- q2.W = q1.Z;
-
- scale = (float)Math.Sin(Utils.PI * (0.5f - amount));
- invscale = (float)Math.Sin(Utils.PI * amount);
+ scale = MathF.Sin(Utils.PI * (0.5f - amount));
+ invscale = MathF.Sin(Utils.PI * amount);
+ return new Quaternion(
+ q1.X * scale - q1.Y * invscale,
+ q1.Y * scale + q1.X * invscale,
+ q1.Z * scale - q1.W * invscale,
+ q1.W * scale + q1.Z * invscale
+ );
}
return new Quaternion(
@@ -753,7 +1034,7 @@ public static Quaternion Normalize(Quaternion q)
float mag = q.LengthSquared();
if (mag > 1e-6f)
{
- float oomag = 1f / (float)Math.Sqrt(mag);
+ float oomag = 1f / MathF.Sqrt(mag);
return new Quaternion(
q.X * oomag,
q.Y * oomag,
@@ -763,50 +1044,202 @@ public static Quaternion Normalize(Quaternion q)
return Quaternion.Identity;
}
- public static Quaternion Parse(string val)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+
+ public unsafe static Quaternion Parse(string val)
+ {
+ return Parse(val.AsSpan());
+ }
+
+ public static Quaternion Parse(ReadOnlySpan sp)
{
- char[] splitChar = { ',' };
- string[] split = val.Replace("<", String.Empty).Replace(">", String.Empty).Split(splitChar);
- if (split.Length == 3)
+ if (sp.Length < 7)
+ throw new FormatException("Invalid Quaternion");
+
+ int start = 0;
+ int comma = 0;
+ char c;
+ do
{
- return new Quaternion(
- float.Parse(split[0].Trim(), Utils.EnUsCulture),
- float.Parse(split[1].Trim(), Utils.EnUsCulture),
- float.Parse(split[2].Trim(), Utils.EnUsCulture));
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
}
- else
+ while (++comma < sp.Length);
+
+ if (c == '<')
{
- return new Quaternion(
- float.Parse(split[0].Trim(), Utils.EnUsCulture),
- float.Parse(split[1].Trim(), Utils.EnUsCulture),
- float.Parse(split[2].Trim(), Utils.EnUsCulture),
- float.Parse(split[3].Trim(), Utils.EnUsCulture));
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
}
+ if (comma > sp.Length - 5)
+ throw new FormatException("Invalid Quaternion");
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ throw new FormatException("Invalid Quaternion");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 3)
+ throw new FormatException("Invalid Quaternion");
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
+ throw new FormatException("Invalid Quaternion");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '>')
+ break;
+ }
+ if (comma >= sp.Length)
+ throw new FormatException("Invalid Quaternion");
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float z))
+ throw new FormatException("Invalid Quaternion");
+
+ if (c == '>')
+ return new Quaternion(x, y, z);
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ' ' || c == '>')
+ break;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float w))
+ throw new FormatException("Invalid Quaternion");
+
+ return new Quaternion(x, y, z, w);
}
- public static bool TryParse(string val, out Quaternion result)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool TryParse(string val, out Quaternion result)
+ {
+ return TryParse(val.AsSpan(), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan sp, out Quaternion result)
{
- try
+ if (sp.Length < 7)
+ {
+ result = Identity;
+ return false;
+ }
+
+ int start = 0;
+ int comma = 0;
+ char c;
+
+ do
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ }
+ if (comma > sp.Length - 5)
+ {
+ result = Identity;
+ return false;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ {
+ result = Identity;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 3)
+ {
+ result = Identity;
+ return false;
+ }
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
{
- result = Parse(val);
+ result = Identity;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == '>' || c == ',')
+ break;
+ }
+ if (comma >= sp.Length)
+ {
+ result = Identity;
+ return false;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float z))
+ {
+ result = Identity;
+ return false;
+ }
+
+ if (c == '>')
+ {
+ result = new Quaternion(x, y, z);
return true;
}
- catch (Exception)
+
+ comma++;
+ start = comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ' ' || c == '>')
+ break;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float w))
{
- result = new Quaternion();
+ result = Identity;
return false;
}
+
+ result = new Quaternion(x, y, z, w);
+ return true;
}
#endregion Static Methods
#region Overrides
- public override bool Equals(object obj)
+ public readonly override bool Equals(object obj)
{
- if(!(obj is Quaternion))
+ if(obj is not Quaternion other)
return false;
- Quaternion other = (Quaternion)obj;
+
if (X != other.X)
return false;
if (Y != other.Y)
@@ -819,7 +1252,7 @@ public override bool Equals(object obj)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Quaternion other)
+ public readonly bool Equals(Quaternion other)
{
if (X != other.X)
return false;
@@ -833,7 +1266,7 @@ public bool Equals(Quaternion other)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool NotEqual(Quaternion other)
+ public readonly bool NotEqual(Quaternion other)
{
if (X != other.X)
return true;
@@ -847,7 +1280,7 @@ public bool NotEqual(Quaternion other)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode()
+ public readonly override int GetHashCode()
{
int hash = X.GetHashCode();
hash = Utils.CombineHash(hash, Y.GetHashCode());
@@ -856,9 +1289,19 @@ public override int GetHashCode()
return hash;
}
- public override string ToString()
+ public readonly override string ToString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}, {2}, {3}>", X, Y, Z, W);
+ StringBuilder sb = new();
+ sb.Append('<');
+ sb.Append(X.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Y.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Z.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(W.ToString(Utils.EnUsCulture));
+ sb.Append('>');
+ return sb.ToString();
}
///
@@ -866,12 +1309,20 @@ public override string ToString()
/// decimal digits and separated by spaces only
///
/// Raw string representation of the quaternion
- public string ToRawString()
+ public readonly string ToRawString()
{
- CultureInfo enUs = new CultureInfo("en-us");
+ CultureInfo enUs = new("en-us");
enUs.NumberFormat.NumberDecimalDigits = 3;
- return String.Format(enUs, "{0} {1} {2} {3}", X, Y, Z, W);
+ StringBuilder sb = new();
+ sb.Append(X.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Y.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Z.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(W.ToString(enUs));
+ return sb.ToString();
}
#endregion Overrides
@@ -954,6 +1405,6 @@ public string ToRawString()
#endregion Operators
/// A quaternion with a value of 0,0,0,1
- public readonly static Quaternion Identity = new Quaternion(0f, 0f, 0f, 1f);
+ public readonly static Quaternion Identity = new(0f, 0f, 0f, 1f);
}
}
diff --git a/OpenMetaverse.Types/UUID.cs b/OpenMetaverse.Types/UUID.cs
index cb0ba250..88813a49 100644
--- a/OpenMetaverse.Types/UUID.cs
+++ b/OpenMetaverse.Types/UUID.cs
@@ -29,6 +29,8 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.Intrinsics;
namespace OpenMetaverse
{
@@ -41,8 +43,6 @@ namespace OpenMetaverse
[Serializable()]
public struct UUID : IComparable,IComparable, IEquatable, IEqualityComparer
{
- // still a big piece of *** because how stupid .net structs are.
- // .net5 unsafe may remove the need for this union
[XmlIgnore] [NonSerialized()] [FieldOffset(0)] public int a;
[XmlIgnore] [NonSerialized()] [FieldOffset(4)] public short b;
[XmlIgnore] [NonSerialized()] [FieldOffset(6)] public short c;
@@ -71,45 +71,39 @@ public struct UUID : IComparable,IComparable, IEquatable, IEqualityC
[XmlIgnore] [NonSerialized()] [FieldOffset(8)] public int intc;
[XmlIgnore] [NonSerialized()] [FieldOffset(12)] public int intd;
- [XmlIgnore] [NonSerialized()] [FieldOffset(0)] public ulong ulonga;
+ [XmlIgnore] [NonSerialized()][FieldOffset(0)] public ulong ulonga;
[XmlIgnore] [NonSerialized()] [FieldOffset(8)] public ulong ulongb;
[FieldOffset(0)] public Guid Guid;
#region Constructors
-
+ /*
+ public Guid Guid
+ {
+ get
+ {
+ return Unsafe.As(ref this);
+ }
+ set
+ {
+ Unsafe.As(ref this) = value;
+ }
+ }
+ */
///
/// Constructor that takes a string UUID representation
///
/// A string representation of a UUID, case
/// insensitive and can either be hyphenated or non-hyphenated
/// UUID("11f8aa9c-b071-4242-836b-13b7abe0d489")
- /*
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe UUID(string val)
+ public UUID(string sval) : this(sval.AsSpan())
{
- if (!string.IsNullOrEmpty(val))
- {
- try
- {
- if (Guid.TryParse(val, out Guid gg))
- {
- this = *(UUID*)≫
- return;
- }
- }
- catch { }
- }
- this = new UUID();
}
- */
- public unsafe UUID(string sval)
+ public unsafe UUID(ReadOnlySpan sval)
{
this = new UUID();
- if (sval == null)
- throw new FormatException("Invalid UUID");
-
int len = sval.Length;
if (len < 32)
throw new FormatException("Invalid UUID");
@@ -132,63 +126,130 @@ public unsafe UUID(string sval)
if (len < 36)
throw new Exception();
- while (--len > 35)
+ if (val[13] != '-' || val[18] != '-' || val[23] != '-')
+ throw new Exception();
+
+ if (Sse42.IsSupported)
{
- if (val[len] != ' ')
+ Vector128 input = Unsafe.As>(ref Unsafe.AsRef(val));
+ Vector128 upper = Ssse3.Shuffle(input, Vector128.Create(0, 4, 8, 12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lower = Ssse3.Shuffle(input, Vector128.Create(2, 6, 10, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 18));
+ Vector128 uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0, 4, 10, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 2, 6, 12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 34)), 7);
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 38));
+ uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 4, 10, 14, 0xff, 0xff, 0xff, 0xff));
+ lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 6, 12, 0xff, 0xff, 0xff, 0xff, 0xff));
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 54)), 11);
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 56));
+ uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 4, 8, 12));
+ lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 6, 10, 14));
+
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ Vector128 charTolower = Vector128.Create((byte)0x20);
+ Vector128 upperLetters = Sse2.Or(upper, charTolower);
+ Vector128 lowerLetters = Sse2.Or(lower, charTolower);
+
+ Vector128 letterTohex = Vector128.Create((byte)('a' - '0' - 10));
+ upperLetters = Sse2.Subtract(upperLetters, letterTohex);
+ lowerLetters = Sse2.Subtract(lowerLetters, letterTohex);
+
+ Vector128 char9 = Vector128.Create((byte)'9');
+ Vector128 above9upper = (Sse2.CompareGreaterThan(upper.AsSByte(), char9.AsSByte())).AsByte();
+ Vector128 above9lower = (Sse2.CompareGreaterThan(lower.AsSByte(), char9.AsSByte())).AsByte();
+
+ Vector128 ten = Vector128.Create((byte)('0' + 10));
+ Vector128 tmpcmpA = Sse2.Subtract(upperLetters, ten);
+ Vector128 tmpcmpB = Sse2.Subtract(lowerLetters, ten);
+
+ Vector128 fifteen = Vector128.Create((byte)('0' + 15));
+ Vector128 tmpcmpC = Sse2.Subtract(fifteen, upperLetters);
+ Vector128 tmpcmpD = Sse2.Subtract(fifteen, lowerLetters);
+
+ tmpcmpA = Sse2.Or(tmpcmpC, tmpcmpA);
+ tmpcmpB = Sse2.Or(tmpcmpD, tmpcmpB);
+
+ tmpcmpA = Sse2.And(tmpcmpA, above9upper);
+ tmpcmpB = Sse2.And(tmpcmpB, above9lower);
+
+ tmpcmpA = Sse2.Or(tmpcmpB, tmpcmpA);
+ int cmp = Sse2.MoveMask(tmpcmpA);
+ if (cmp != 0)
throw new Exception();
- }
- if (val[13] != '-' || val[18] != '-' || val[23] != '-')
- throw new Exception();
+ upper = Sse41.BlendVariable(upper, upperLetters, above9upper);
+ lower = Sse41.BlendVariable(lower, lowerLetters, above9lower);
+
+ Vector128 charzero = Vector128.Create((byte)'0');
+ upper = Sse2.Subtract(upper, charzero);
+ lower = Sse2.Subtract(lower, charzero);
+
+ tmpcmpA = Sse2.Or(lower, upper);
+ cmp = Sse2.MoveMask(tmpcmpA);
+ if (cmp != 0)
+ throw new Exception();
+
+ upper = Sse2.ShiftLeftLogical(upper.AsUInt16(), 4).AsByte();
+ lower = Sse2.Or(lower, upper);
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref Unsafe.AsRef(in this)) = lower;
+ return;
+ }
if (BitConverter.IsLittleEndian)
{
- bytea3 = (byte)Utils.HexToByte(val, 0);
- bytea2 = (byte)Utils.HexToByte(val, 2);
- bytea1 = (byte)Utils.HexToByte(val, 4);
- bytea0 = (byte)Utils.HexToByte(val, 6);
+ bytea3 = Utils.HexToByte(val, 0);
+ bytea2 = Utils.HexToByte(val, 2);
+ bytea1 = Utils.HexToByte(val, 4);
+ bytea0 = Utils.HexToByte(val, 6);
- byteb1 = (byte)Utils.HexToByte(val, 9);
- byteb0 = (byte)Utils.HexToByte(val, 11);
+ byteb1 = Utils.HexToByte(val, 9);
+ byteb0 = Utils.HexToByte(val, 11);
- bytec1 = (byte)Utils.HexToByte(val, 14);
- bytec0 = (byte)Utils.HexToByte(val, 16);
+ bytec1 = Utils.HexToByte(val, 14);
+ bytec0 = Utils.HexToByte(val, 16);
}
else
{
- bytea0 = (byte)Utils.HexToByte(val, 0);
- bytea1 = (byte)Utils.HexToByte(val, 2);
- bytea2 = (byte)Utils.HexToByte(val, 4);
- bytea3 = (byte)Utils.HexToByte(val, 6);
+ bytea0 = Utils.HexToByte(val, 0);
+ bytea1 = Utils.HexToByte(val, 2);
+ bytea2 = Utils.HexToByte(val, 4);
+ bytea3 = Utils.HexToByte(val, 6);
- byteb0 = (byte)Utils.HexToByte(val, 9);
- byteb1 = (byte)Utils.HexToByte(val, 11);
+ byteb0 = Utils.HexToByte(val, 9);
+ byteb1 = Utils.HexToByte(val, 11);
- bytec0 = (byte)Utils.HexToByte(val, 14);
- bytec1 = (byte)Utils.HexToByte(val, 16);
+ bytec0 = Utils.HexToByte(val, 14);
+ bytec1 = Utils.HexToByte(val, 16);
}
-
- d = (byte)Utils.HexToByte(val, 19);
- e = (byte)Utils.HexToByte(val, 21);
+ d = Utils.HexToByte(val, 19);
+ e = Utils.HexToByte(val, 21);
- f = (byte)Utils.HexToByte(val, 24);
- g = (byte)Utils.HexToByte(val, 26);
- h = (byte)Utils.HexToByte(val, 28);
- i = (byte)Utils.HexToByte(val, 30);
- j = (byte)Utils.HexToByte(val, 32);
- k = (byte)Utils.HexToByte(val, 34);
+ f = Utils.HexToByte(val, 24);
+ g = Utils.HexToByte(val, 26);
+ h = Utils.HexToByte(val, 28);
+ i = Utils.HexToByte(val, 30);
+ j = Utils.HexToByte(val, 32);
+ k = Utils.HexToByte(val, 34);
return;
}
else
{
- while (--len > 31)
- {
- if (val[len] != ' ')
- throw new Exception();
- }
-
if (BitConverter.IsLittleEndian)
{
bytea3 = Utils.HexToByte(val, 0);
@@ -260,6 +321,15 @@ public unsafe UUID(ulong _la, ulong _lb) : this()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe UUID(byte[] source, int pos) : this()
{
+ if(Ssse3.IsSupported)
+ {
+ Vector128 rawval = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(source), pos));
+ if (BitConverter.IsLittleEndian)
+ rawval = Ssse3.Shuffle(rawval, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref this) = rawval;
+ return;
+ }
+
fixed (byte* ptr = &source[pos])
{
if (BitConverter.IsLittleEndian)
@@ -332,13 +402,12 @@ public UUID(UUID val)
///
/// IComparable.CompareTo implementation
///
- public int CompareTo(object val)
+ public readonly int CompareTo(object val)
{
if (val == null)
return 1;
UUID id = (UUID)val;
-
if (id.a != a)
return (uint)id.a > (uint)a ? -1 : 1;
if (id.b != b)
@@ -365,7 +434,7 @@ public int CompareTo(object val)
return 0;
}
- public int CompareTo(UUID id)
+ public readonly int CompareTo(UUID id)
{
if (id.a != a)
return (uint)id.a > (uint)a ? -1 : 1;
@@ -401,6 +470,15 @@ public int CompareTo(UUID id)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void FromBytes(byte[] source, int pos)
{
+ if (Ssse3.IsSupported)
+ {
+ Vector128 rawval = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(source), pos));
+ if (BitConverter.IsLittleEndian)
+ rawval = Ssse3.Shuffle(rawval, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref this) = rawval;
+ return;
+ }
+
fixed (byte* ptr = &source[pos])
{
if (BitConverter.IsLittleEndian)
@@ -437,36 +515,10 @@ public unsafe void FromBytes(byte[] source, int pos)
///
/// A 16 byte array containing this UUID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe byte[] GetBytes()
+ public readonly unsafe byte[] GetBytes()
{
byte[] dest = new byte[16];
- fixed (byte* ptr = &dest[0])
- {
- if (BitConverter.IsLittleEndian)
- {
- *ptr = bytea3;
- *(ptr + 1) = bytea2;
- *(ptr + 2) = bytea1;
- *(ptr + 3) = bytea0;
- *(ptr + 4) = byteb1;
- *(ptr + 5) = byteb0;
- *(ptr + 6) = bytec1;
- *(ptr + 7) = bytec0;
- *(ulong*)(ptr + 8) = ulongb;
- }
- else
- {
- *(ulong*)(ptr) = ulonga;
- *(ptr + 8) = d;
- *(ptr + 9) = e;
- *(ptr + 10) = f;
- *(ptr + 11) = g;
- *(ptr + 12) = h;
- *(ptr + 13) = i;
- *(ptr + 14) = j;
- *(ptr + 15) = k;
- }
- }
+ ToBytes(dest, 0);
return dest;
}
@@ -477,8 +529,16 @@ public unsafe byte[] GetBytes()
/// Position in the destination array to start
/// writing. Must be at least 16 bytes before the end of the array
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe void ToBytes(byte[] dest, int pos)
+ public readonly unsafe void ToBytes(byte[] dest, int pos)
{
+ if (Ssse3.IsSupported)
+ {
+ Vector128 val = Unsafe.As>(ref Unsafe.AsRef(in this));
+ if (BitConverter.IsLittleEndian)
+ val = Ssse3.Shuffle(val, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = val;
+ return;
+ }
fixed (byte* ptr = &dest[pos])
{
if (BitConverter.IsLittleEndian)
@@ -508,12 +568,41 @@ public unsafe void ToBytes(byte[] dest, int pos)
}
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ToBytes(byte* ptr)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ *ptr = bytea3;
+ *(ptr + 1) = bytea2;
+ *(ptr + 2) = bytea1;
+ *(ptr + 3) = bytea0;
+ *(ptr + 4) = byteb1;
+ *(ptr + 5) = byteb0;
+ *(ptr + 6) = bytec1;
+ *(ptr + 7) = bytec0;
+ *(ulong*)(ptr + 8) = ulongb;
+ }
+ else
+ {
+ *(ulong*)(ptr) = ulonga;
+ *(ptr + 8) = d;
+ *(ptr + 9) = e;
+ *(ptr + 10) = f;
+ *(ptr + 11) = g;
+ *(ptr + 12) = h;
+ *(ptr + 13) = i;
+ *(ptr + 14) = j;
+ *(ptr + 15) = k;
+ }
+ }
+
///
/// Calculate an LLCRC (cyclic redundancy check) for this UUID
///
/// The CRC checksum for this UUID
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public uint CRC()
+ public readonly uint CRC()
{
return (uint)a + (uint)intb + (uint)intc + (uint)intd;
}
@@ -522,7 +611,8 @@ public uint CRC()
/// Create a 64-bit integer representation from the second half of this UUID
///
/// An integer created from the last eight bytes of this UUID
- public ulong GetULong()
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly ulong GetULong()
{
if (BitConverter.IsLittleEndian)
return ulongb;
@@ -547,20 +637,17 @@ public ulong GetULong()
/// A string representation of a UUID, case
/// insensitive and can either be hyphenated or non-hyphenated
/// UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489")
- /*
- public static UUID Parse(string val)
- {
- Guid gg = Guid.Parse(val);
- return new UUID(gg);
- }
- */
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static UUID Parse(string sval)
{
- UUID result = new UUID();
- if (sval == null)
- throw new FormatException("Invalid UUID");
+ return Parse(sval.AsSpan());
+ }
+ public unsafe static UUID Parse(ReadOnlySpan sval)
+ {
+ UUID result = new();
int len = sval.Length;
if (len < 32)
throw new FormatException("Invalid UUID");
@@ -581,62 +668,131 @@ public unsafe static UUID Parse(string sval)
{
if (len < 36)
throw new Exception();
- while (--len > 35)
- {
- if (val[len] != ' ')
- throw new Exception();
- }
if (val[13] != '-' || val[18] != '-' || val[23] != '-')
throw new Exception();
+ if (Sse42.IsSupported)
+ {
+ Vector128 input = Unsafe.As>(ref Unsafe.AsRef(val));
+ Vector128 upper = Ssse3.Shuffle(input, Vector128.Create(0, 4, 8, 12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lower = Ssse3.Shuffle(input, Vector128.Create(2, 6, 10, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 18));
+ Vector128 uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0, 4, 10, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 2, 6, 12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 34)), 7);
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 38));
+ uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 4, 10, 14, 0xff, 0xff, 0xff, 0xff));
+ lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 6, 12, 0xff, 0xff, 0xff, 0xff, 0xff));
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 54)), 11);
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 56));
+ uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 4, 8, 12));
+ lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 6, 10, 14));
+
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ Vector128 charTolower = Vector128.Create((byte)0x20);
+ Vector128 upperLetters = Sse2.Or(upper, charTolower);
+ Vector128 lowerLetters = Sse2.Or(lower, charTolower);
+
+ Vector128 letterTohex = Vector128.Create((byte)('a' - '0' - 10));
+ upperLetters = Sse2.Subtract(upperLetters, letterTohex);
+ lowerLetters = Sse2.Subtract(lowerLetters, letterTohex);
+
+ Vector128 char9 = Vector128.Create((byte)'9');
+ Vector128 above9upper = (Sse2.CompareGreaterThan(upper.AsSByte(), char9.AsSByte())).AsByte();
+ Vector128 above9lower = (Sse2.CompareGreaterThan(lower.AsSByte(), char9.AsSByte())).AsByte();
+
+ Vector128 ten = Vector128.Create((byte)('0' + 10));
+ Vector128 tmpcmpA = Sse2.Subtract(upperLetters, ten);
+ Vector128 tmpcmpB = Sse2.Subtract(lowerLetters, ten);
+
+ Vector128 fifteen = Vector128.Create((byte)('0' + 15));
+ Vector128 tmpcmpC = Sse2.Subtract(fifteen, upperLetters);
+ Vector128 tmpcmpD = Sse2.Subtract(fifteen, lowerLetters);
+
+ tmpcmpA = Sse2.Or(tmpcmpC, tmpcmpA);
+ tmpcmpB = Sse2.Or(tmpcmpD, tmpcmpB);
+
+ tmpcmpA = Sse2.And(tmpcmpA, above9upper);
+ tmpcmpB = Sse2.And(tmpcmpB, above9lower);
+
+ tmpcmpA = Sse2.Or(tmpcmpB, tmpcmpA);
+ int cmp = Sse2.MoveMask(tmpcmpA);
+ if (cmp != 0)
+ throw new Exception();
+
+ upper = Sse41.BlendVariable(upper, upperLetters, above9upper);
+ lower = Sse41.BlendVariable(lower, lowerLetters, above9lower);
+
+ Vector128 charzero = Vector128.Create((byte)'0');
+ upper = Sse2.Subtract(upper, charzero);
+ lower = Sse2.Subtract(lower, charzero);
+
+ tmpcmpA = Sse2.Or(lower, upper);
+ cmp = Sse2.MoveMask(tmpcmpA);
+ if (cmp != 0)
+ throw new Exception();
+
+ upper = Sse2.ShiftLeftLogical(upper.AsUInt16(), 4).AsByte();
+ lower = Sse2.Or(lower, upper);
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref Unsafe.AsRef(in result)) = lower;
+ return result;
+ }
+
if (BitConverter.IsLittleEndian)
{
- result.bytea3 = (byte)Utils.HexToByte(val, 0);
- result.bytea2 = (byte)Utils.HexToByte(val, 2);
- result.bytea1 = (byte)Utils.HexToByte(val, 4);
- result.bytea0 = (byte)Utils.HexToByte(val, 6);
+ result.bytea3 = Utils.HexToByte(val, 0);
+ result.bytea2 = Utils.HexToByte(val, 2);
+ result.bytea1 = Utils.HexToByte(val, 4);
+ result.bytea0 = Utils.HexToByte(val, 6);
- result.byteb1 = (byte)Utils.HexToByte(val, 9);
- result.byteb0 = (byte)Utils.HexToByte(val, 11);
+ result.byteb1 = Utils.HexToByte(val, 9);
+ result.byteb0 = Utils.HexToByte(val, 11);
- result.bytec1 = (byte)Utils.HexToByte(val, 14);
- result.bytec0 = (byte)Utils.HexToByte(val, 16);
+ result.bytec1 = Utils.HexToByte(val, 14);
+ result.bytec0 = Utils.HexToByte(val, 16);
}
else
{
- result.bytea0 = (byte)Utils.HexToByte(val, 0);
- result.bytea1 = (byte)Utils.HexToByte(val, 2);
- result.bytea2 = (byte)Utils.HexToByte(val, 4);
- result.bytea3 = (byte)Utils.HexToByte(val, 6);
+ result.bytea0 = Utils.HexToByte(val, 0);
+ result.bytea1 = Utils.HexToByte(val, 2);
+ result.bytea2 = Utils.HexToByte(val, 4);
+ result.bytea3 = Utils.HexToByte(val, 6);
- result.byteb0 = (byte)Utils.HexToByte(val, 9);
- result.byteb1 = (byte)Utils.HexToByte(val, 11);
+ result.byteb0 = Utils.HexToByte(val, 9);
+ result.byteb1 = Utils.HexToByte(val, 11);
- result.bytec0 = (byte)Utils.HexToByte(val, 14);
- result.bytec1 = (byte)Utils.HexToByte(val, 16);
+ result.bytec0 = Utils.HexToByte(val, 14);
+ result.bytec1 = Utils.HexToByte(val, 16);
}
- result.d = (byte)Utils.HexToByte(val, 19);
- result.e = (byte)Utils.HexToByte(val, 21);
+ result.d = Utils.HexToByte(val, 19);
+ result.e = Utils.HexToByte(val, 21);
- result.f = (byte)Utils.HexToByte(val, 24);
- result.g = (byte)Utils.HexToByte(val, 26);
- result.h = (byte)Utils.HexToByte(val, 28);
- result.i = (byte)Utils.HexToByte(val, 30);
- result.j = (byte)Utils.HexToByte(val, 32);
- result.k = (byte)Utils.HexToByte(val, 34);
+ result.f = Utils.HexToByte(val, 24);
+ result.g = Utils.HexToByte(val, 26);
+ result.h = Utils.HexToByte(val, 28);
+ result.i = Utils.HexToByte(val, 30);
+ result.j = Utils.HexToByte(val, 32);
+ result.k = Utils.HexToByte(val, 34);
return result;
}
else
{
- while (--len > 31)
- {
- if (val[len] != ' ')
- throw new Exception();
- }
-
if (BitConverter.IsLittleEndian)
{
result.bytea3 = Utils.HexToByte(val, 0);
@@ -692,11 +848,15 @@ public unsafe static UUID Parse(string sval)
/// True if the string was successfully parse, otherwise false
/// UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static bool TryParse(string sval, out UUID result)
+ {
+ return TryParse(sval.AsSpan(), out result);
+ }
+
+ public unsafe static bool TryParse(ReadOnlySpan sval, out UUID result)
{
result = new UUID();
- if (sval is null)
- return false;
int len = sval.Length;
if (len < 32)
@@ -720,6 +880,7 @@ public unsafe static bool TryParse(string sval, out UUID result)
{
if (len < 36)
return false;
+
while (--len > 35)
{
if (val[len] != ' ')
@@ -729,43 +890,123 @@ public unsafe static bool TryParse(string sval, out UUID result)
if (val[13] != '-' || val[18] != '-' || val[23] != '-')
return false;
+ if (Sse42.IsSupported)
+ {
+ Vector128 input = Unsafe.As>(ref Unsafe.AsRef(val));
+ Vector128 upper = Ssse3.Shuffle(input, Vector128.Create(0, 4, 8, 12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lower = Ssse3.Shuffle(input, Vector128.Create(2, 6, 10, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 18));
+ Vector128 uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0, 4, 10, 14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ Vector128 lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 2, 6, 12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 34)), 7);
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 38));
+ uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 4, 10, 14, 0xff, 0xff, 0xff, 0xff));
+ lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 6, 12, 0xff, 0xff, 0xff, 0xff, 0xff));
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ lower = Sse41.Insert(lower, Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 54)), 11);
+
+ input = Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(val), 56));
+ uppertmp = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 4, 8, 12));
+ lowerhalf = Ssse3.Shuffle(input, Vector128.Create(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2, 6, 10, 14));
+
+ upper = Sse2.Or(upper, uppertmp);
+ lower = Sse2.Or(lower, lowerhalf);
+
+ Vector128 charTolower = Vector128.Create((byte)0x20);
+ Vector128 upperLetters = Sse2.Or(upper, charTolower);
+ Vector128 lowerLetters = Sse2.Or(lower, charTolower);
+
+ Vector128 letterTohex = Vector128.Create((byte)('a' - '0' - 10));
+ upperLetters = Sse2.Subtract(upperLetters, letterTohex);
+ lowerLetters = Sse2.Subtract(lowerLetters, letterTohex);
+
+ Vector128 char9 = Vector128.Create((byte)'9');
+ Vector128 above9upper = (Sse2.CompareGreaterThan(upper.AsSByte(), char9.AsSByte())).AsByte();
+ Vector128 above9lower = (Sse2.CompareGreaterThan(lower.AsSByte(), char9.AsSByte())).AsByte();
+
+ Vector128 ten = Vector128.Create((byte)('0' + 10));
+ Vector128 tmpcmpA = Sse2.Subtract(upperLetters, ten);
+ Vector128 tmpcmpB = Sse2.Subtract(lowerLetters, ten);
+
+ Vector128 fifteen = Vector128.Create((byte)('0' + 15));
+ Vector128 tmpcmpC = Sse2.Subtract(fifteen, upperLetters);
+ Vector128 tmpcmpD = Sse2.Subtract(fifteen, lowerLetters);
+
+ tmpcmpA = Sse2.Or(tmpcmpC, tmpcmpA);
+ tmpcmpB = Sse2.Or(tmpcmpD, tmpcmpB);
+
+ tmpcmpA = Sse2.And(tmpcmpA, above9upper);
+ tmpcmpB = Sse2.And(tmpcmpB, above9lower);
+
+ tmpcmpA = Sse2.Or(tmpcmpB, tmpcmpA);
+ int cmp = Sse2.MoveMask(tmpcmpA);
+ if (cmp != 0)
+ return false;
+
+ upper = Sse41.BlendVariable(upper, upperLetters, above9upper);
+ lower = Sse41.BlendVariable(lower, lowerLetters, above9lower);
+
+ Vector128 charzero = Vector128.Create((byte)'0');
+ upper = Sse2.Subtract(upper, charzero);
+ lower = Sse2.Subtract(lower, charzero);
+
+ tmpcmpA = Sse2.Or(lower, upper);
+ cmp = Sse2.MoveMask(tmpcmpA);
+ if (cmp != 0)
+ return false;
+
+ upper = Sse2.ShiftLeftLogical(upper.AsUInt16(), 4).AsByte();
+ lower = Sse2.Or(lower, upper);
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Unsafe.As>(ref Unsafe.AsRef(in result)) = lower;
+ return true;
+ }
+
if (BitConverter.IsLittleEndian)
{
- result.bytea3 = (byte)Utils.HexToByte(val, 0);
- result.bytea2 = (byte)Utils.HexToByte(val, 2);
- result.bytea1 = (byte)Utils.HexToByte(val, 4);
- result.bytea0 = (byte)Utils.HexToByte(val, 6);
+ result.bytea3 = Utils.HexToByte(val, 0);
+ result.bytea2 = Utils.HexToByte(val, 2);
+ result.bytea1 = Utils.HexToByte(val, 4);
+ result.bytea0 = Utils.HexToByte(val, 6);
- result.byteb1 = (byte)Utils.HexToByte(val, 9);
- result.byteb0 = (byte)Utils.HexToByte(val, 11);
+ result.byteb1 = Utils.HexToByte(val, 9);
+ result.byteb0 = Utils.HexToByte(val, 11);
- result.bytec1 = (byte)Utils.HexToByte(val, 14);
- result.bytec0 = (byte)Utils.HexToByte(val, 16);
+ result.bytec1 = Utils.HexToByte(val, 14);
+ result.bytec0 = Utils.HexToByte(val, 16);
}
else
{
- result.bytea0 = (byte)Utils.HexToByte(val, 0);
- result.bytea1 = (byte)Utils.HexToByte(val, 2);
- result.bytea2 = (byte)Utils.HexToByte(val, 4);
- result.bytea3 = (byte)Utils.HexToByte(val, 6);
+ result.bytea0 = Utils.HexToByte(val, 0);
+ result.bytea1 = Utils.HexToByte(val, 2);
+ result.bytea2 = Utils.HexToByte(val, 4);
+ result.bytea3 = Utils.HexToByte(val, 6);
- result.byteb0 = (byte)Utils.HexToByte(val, 9);
- result.byteb1 = (byte)Utils.HexToByte(val, 11);
+ result.byteb0 = Utils.HexToByte(val, 9);
+ result.byteb1 = Utils.HexToByte(val, 11);
- result.bytec0 = (byte)Utils.HexToByte(val, 14);
- result.bytec1 = (byte)Utils.HexToByte(val, 16);
+ result.bytec0 = Utils.HexToByte(val, 14);
+ result.bytec1 = Utils.HexToByte(val, 16);
}
- result.d = (byte)Utils.HexToByte(val, 19);
- result.e = (byte)Utils.HexToByte(val, 21);
+ result.d = Utils.HexToByte(val, 19);
+ result.e = Utils.HexToByte(val, 21);
- result.f = (byte)Utils.HexToByte(val, 24);
- result.g = (byte)Utils.HexToByte(val, 26);
- result.h = (byte)Utils.HexToByte(val, 28);
- result.i = (byte)Utils.HexToByte(val, 30);
- result.j = (byte)Utils.HexToByte(val, 32);
- result.k = (byte)Utils.HexToByte(val, 34);
+ result.f = Utils.HexToByte(val, 24);
+ result.g = Utils.HexToByte(val, 26);
+ result.h = Utils.HexToByte(val, 28);
+ result.i = Utils.HexToByte(val, 30);
+ result.j = Utils.HexToByte(val, 32);
+ result.k = Utils.HexToByte(val, 34);
return true;
}
else
@@ -857,7 +1098,7 @@ public unsafe static UUID Random()
///
/// An integer composed of all the UUID bytes XORed together
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode()
+ public readonly override int GetHashCode()
{
int h = Utils.CombineHash(intd, intc);
h = Utils.CombineHash(h, intb);
@@ -865,9 +1106,9 @@ public override int GetHashCode()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int GetHashCode(UUID u)
+ public readonly int GetHashCode(UUID u)
{
- return u.a ^ u.intb ^ u.intc ^ u.intd;
+ return u.GetHashCode();
}
///
@@ -876,12 +1117,11 @@ public int GetHashCode(UUID u)
/// An object to compare to this UUID
/// True if the object is a UUID and both UUIDs are equal
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override bool Equals(object o)
+ public readonly override bool Equals(object o)
{
- if (!(o is UUID))
+ if (o is not UUID uuid)
return false;
- UUID uuid = (UUID)o;
if (ulonga != uuid.ulonga)
return false;
if (ulongb != uuid.ulongb)
@@ -895,7 +1135,7 @@ public override bool Equals(object o)
/// UUID to compare to
/// True if the UUIDs are equal, otherwise false
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(UUID uuid)
+ public readonly bool Equals(UUID uuid)
{
if (ulonga != uuid.ulonga)
return false;
@@ -905,7 +1145,7 @@ public bool Equals(UUID uuid)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(UUID a, UUID b)
+ public readonly bool Equals(UUID a, UUID b)
{
if (a.ulonga != b.ulonga)
return false;
@@ -915,7 +1155,7 @@ public bool Equals(UUID a, UUID b)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsZero()
+ public readonly bool IsZero()
{
if (ulonga != 0)
return false;
@@ -925,7 +1165,7 @@ public bool IsZero()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool NotEqual(UUID uuid)
+ public readonly bool NotEqual(in UUID uuid)
{
if (ulonga != uuid.ulonga)
return true;
@@ -935,7 +1175,7 @@ public bool NotEqual(UUID uuid)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsNotZero()
+ public readonly bool IsNotZero()
{
if (ulonga != 0)
return true;
@@ -952,9 +1192,9 @@ public bool IsNotZero()
/// 11f8aa9c-b071-4242-836b-13b7abe0d489
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override string ToString()
+ public readonly override string ToString()
{
- return Utils.UUIDToDashString(ref this);
+ return Utils.UUIDToDashString(this);
}
#endregion Overrides
@@ -968,7 +1208,7 @@ public override string ToString()
/// Second UUID for comparison
/// True if the UUIDs are byte for byte equal, otherwise false
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(UUID lhs, UUID rhs)
+ public static bool operator ==(in UUID lhs, in UUID rhs)
{
if (lhs.ulonga != rhs.ulonga)
return false;
@@ -984,7 +1224,7 @@ public override string ToString()
/// Second UUID for comparison
/// True if the UUIDs are not equal, otherwise true
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(UUID lhs, UUID rhs)
+ public static bool operator !=(in UUID lhs, in UUID rhs)
{
if (lhs.ulonga != rhs.ulonga)
return true;
@@ -1001,10 +1241,11 @@ public override string ToString()
/// A UUID that is a XOR combination of the two input UUIDs
public static UUID operator ^(UUID lhs, UUID rhs)
{
- UUID ret = new UUID();
- ret.ulonga = lhs.ulonga ^ rhs.ulonga;
- ret.ulongb = lhs.ulongb ^ rhs.ulongb;
- return ret;
+ return new()
+ {
+ ulonga = lhs.ulonga ^ rhs.ulonga,
+ ulongb = lhs.ulongb ^ rhs.ulongb
+ };
}
///
@@ -1021,7 +1262,7 @@ public static explicit operator UUID(string val)
#endregion Operators
/// An UUID with a value of all zeroes
- public static readonly UUID Zero = new UUID();
+ public static readonly UUID Zero = new();
/// A cache of UUID.Zero as a string to optimize a common path
public static readonly string ZeroString = "00000000-0000-0000-0000-000000000000";
diff --git a/OpenMetaverse.Types/Utils.cs b/OpenMetaverse.Types/Utils.cs
index c7b489ca..aedf190a 100644
--- a/OpenMetaverse.Types/Utils.cs
+++ b/OpenMetaverse.Types/Utils.cs
@@ -34,45 +34,17 @@ namespace OpenMetaverse
{
public static partial class Utils
{
- ///
- /// Operating system
- ///
- public enum Platform
- {
- /// Unknown
- Unknown,
- /// Microsoft Windows
- Windows,
- /// Microsoft Windows CE
- WindowsCE,
- /// Linux
- Linux,
- /// Apple OSX
- OSX
- }
-
- ///
- /// Runtime platform
- ///
- public enum Runtime
- {
- /// .NET runtime
- Windows,
- /// Mono runtime: http://www.mono-project.com/
- Mono
- }
-
- public const float E = (float)Math.E;
+ public const float E = MathF.E;
public const float LOG10E = 0.4342945f;
public const float LOG2E = 1.442695f;
- public const float PI = (float)Math.PI;
- public const float TWO_PI = (float)(Math.PI * 2.0d);
- public const float PI_OVER_TWO = (float)(Math.PI / 2.0d);
- public const float PI_OVER_FOUR = (float)(Math.PI / 4.0d);
+ public const float PI = MathF.PI;
+ public const float TWO_PI = MathF.PI * 2.0f;
+ public const float PI_OVER_TWO = MathF.PI / 2.0f;
+ public const float PI_OVER_FOUR = MathF.PI / 4.0f;
/// Used for converting degrees to radians
- public const float DEG_TO_RAD = (float)(Math.PI / 180.0d);
+ public const float DEG_TO_RAD = MathF.PI / 180.0f;
/// Used for converting radians to degrees
- public const float RAD_TO_DEG = (float)(180.0d / Math.PI);
+ public const float RAD_TO_DEG = 180.0f / MathF.PI;
/// Provide a single instance of the CultureInfo class to
/// help parsing in situations where the grid assumes an en-us
@@ -88,15 +60,15 @@ public enum Runtime
/// Provide a single instance of the MD5 class to avoid making
/// duplicate copies and handle thread safety
private static readonly System.Security.Cryptography.MD5 MD5Builder =
- new System.Security.Cryptography.MD5CryptoServiceProvider();
+ System.Security.Cryptography.MD5.Create();
/// Provide a single instance of the SHA-1 class to avoid
/// making duplicate copies and handle thread safety
private static readonly System.Security.Cryptography.SHA1 SHA1Builder =
- new System.Security.Cryptography.SHA1CryptoServiceProvider();
+ System.Security.Cryptography.SHA1.Create();
private static readonly System.Security.Cryptography.SHA256 SHA256Builder =
- new System.Security.Cryptography.SHA256Managed();
+ System.Security.Cryptography.SHA256.Create();
/// Provide a single instance of a random number generator
/// to avoid making duplicate copies and handle thread safety
@@ -114,16 +86,7 @@ public enum Runtime
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Clamp(float value, float min, float max)
{
- // First we check to see if we're greater than the max
- if (value >= max)
- return max;
-
- // Then we check to see if we're less than the min.
- if (value < min)
- return min;
-
- // There's no check to see if min > max.
- return value;
+ return (value < max) ? (value > min ? value : min) : max;
}
///
@@ -136,16 +99,7 @@ public static float Clamp(float value, float min, float max)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Clamp(double value, double min, double max)
{
- // First we check to see if we're greater than the max
- if (value >= max)
- return max;
-
- // Then we check to see if we're less than the min.
- if (value < min)
- return min;
-
- // There's no check to see if min > max.
- return value;
+ return (value < max) ? (value > min ? value : min) : max;
}
///
@@ -158,16 +112,7 @@ public static double Clamp(double value, double min, double max)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Clamp(int value, int min, int max)
{
- // First we check to see if we're greater than the max
- if (value >= max)
- return max;
-
- // Then we check to see if we're less than the min.
- if (value < min)
- return min;
-
- // There's no check to see if min > max.
- return value;
+ return (value < max) ? (value > min ? value : min) : max;
}
///
@@ -213,40 +158,38 @@ public static float Distance(float value1, float value2)
public static float Hermite(float value1, float tangent1, float value2, float tangent2, float amount)
{
+ if (amount <= 0f)
+ return value1;
+ if (amount >= 1f)
+ return value2;
+
// All transformed to double not to lose precission
// Otherwise, for high numbers of param:amount the result is NaN instead of Infinity
- double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
- double sCubed = s * s * s;
+ double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount;
double sSquared = s * s;
-
- if (amount == 0f)
- result = value1;
- else if (amount == 1f)
- result = value2;
- else
- result = (2d * v1 - 2d * v2 + t2 + t1) * sCubed +
+ double sCubed = sSquared * s;
+
+ return (float)((2d * v1 - 2d * v2 + t2 + t1) * sCubed +
(3d * v2 - 3d * v1 - 2d * t1 - t2) * sSquared +
- t1 * s + v1;
- return (float)result;
+ t1 * s + v1);
}
public static double Hermite(double value1, double tangent1, double value2, double tangent2, double amount)
{
+ if (amount <= 0d)
+ return value1;
+ if (amount >= 1f)
+ return value2;
+
// All transformed to double not to lose precission
// Otherwise, for high numbers of param:amount the result is NaN instead of Infinity
- double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount, result;
- double sCubed = s * s * s;
+ double v1 = value1, v2 = value2, t1 = tangent1, t2 = tangent2, s = amount;
double sSquared = s * s;
+ double sCubed = sSquared * s;
- if (amount == 0d)
- result = value1;
- else if (amount == 1f)
- result = value2;
- else
- result = (2d * v1 - 2d * v2 + t2 + t1) * sCubed +
+ return (2d * v1 - 2d * v2 + t2 + t1) * sCubed +
(3d * v2 - 3d * v1 - 2d * t1 - t2) * sSquared +
t1 * s + v1;
- return result;
}
public static float Lerp(float value1, float value2, float amount)
@@ -261,20 +204,12 @@ public static double Lerp(double value1, double value2, double amount)
public static float SmoothStep(float value1, float value2, float amount)
{
- // It is expected that 0 < amount < 1
- // If amount < 0, return value1
- // If amount > 1, return value2
- float result = Utils.Clamp(amount, 0f, 1f);
- return Utils.Hermite(value1, 0f, value2, 0f, result);
+ return Utils.Hermite(value1, 0f, value2, 0f, amount);
}
public static double SmoothStep(double value1, double value2, double amount)
{
- // It is expected that 0 < amount < 1
- // If amount < 0, return value1
- // If amount > 1, return value2
- double result = Utils.Clamp(amount, 0f, 1f);
- return Utils.Hermite(value1, 0f, value2, 0f, result);
+ return Utils.Hermite(value1, 0f, value2, 0f, amount);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -414,52 +349,5 @@ public static double RandomDouble()
}
#endregion Math
-
- #region Platform
-
- ///
- /// Get the current running platform
- ///
- /// Enumeration of the current platform we are running on
- public static Platform GetRunningPlatform()
- {
- const string OSX_CHECK_FILE = "/Library/Extensions.kextcache";
-
- if (Environment.OSVersion.Platform == PlatformID.WinCE)
- {
- return Platform.WindowsCE;
- }
- else
- {
- int plat = (int)Environment.OSVersion.Platform;
-
- if ((plat != 4) && (plat != 128))
- {
- return Platform.Windows;
- }
- else
- {
- if (System.IO.File.Exists(OSX_CHECK_FILE))
- return Platform.OSX;
- else
- return Platform.Linux;
- }
- }
- }
-
- ///
- /// Get the current running runtime
- ///
- /// Enumeration of the current runtime we are running on
- public static Runtime GetRunningRuntime()
- {
- Type t = Type.GetType("Mono.Runtime");
- if (t != null)
- return Runtime.Mono;
- else
- return Runtime.Windows;
- }
-
- #endregion Platform
}
}
diff --git a/OpenMetaverse.Types/UtilsConversions.cs b/OpenMetaverse.Types/UtilsConversions.cs
index 46f81f15..16068ef7 100644
--- a/OpenMetaverse.Types/UtilsConversions.cs
+++ b/OpenMetaverse.Types/UtilsConversions.cs
@@ -32,6 +32,9 @@
using System.Reflection;
using System.IO;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.Intrinsics;
namespace OpenMetaverse
{
@@ -39,7 +42,19 @@ public static partial class Utils
{
// public static readonly bool NoAlignment = CheckNeedAlignment();
public static readonly bool CanDirectCopyLE = CheckNeedAlignment();
-// public static readonly bool CanDirectCopyBE = CheckDirectCopyBE();
+ //public static readonly bool CanDirectCopyBE = CheckDirectCopyBE();
+
+ [StructLayout(LayoutKind.Sequential, Size = 16, Pack = 1)]
+ public struct Bytes16 { }
+
+ [StructLayout(LayoutKind.Sequential, Size = 12, Pack = 1)]
+ public struct Bytes12 { }
+
+ [StructLayout(LayoutKind.Sequential, Size = 8, Pack = 1)]
+ public struct Bytes8 { }
+
+ [StructLayout(LayoutKind.Sequential, Size = 6, Pack = 1)]
+ public struct Bytes6 { }
public unsafe static bool CheckNeedAlignment()
{
@@ -157,7 +172,7 @@ static bool CheckDirectCopyBE()
string.Empty, // 54
string.Empty, // 55
"settings", // 56
- string.Empty, // 57
+ "material" // 57
};
private static readonly string[] _FolderTypeNames = new string[]
@@ -188,7 +203,7 @@ static bool CheckDirectCopyBE()
"favorite", // 23
string.Empty, // 24
"settings", // 25
- "ensemble", // 26
+ "material", // 26
"ensemble", // 27
"ensemble", // 28
"ensemble", // 29
@@ -247,7 +262,7 @@ static bool CheckDirectCopyBE()
string.Empty, // 23
string.Empty, // 24
"settings", // 25
- string.Empty, // 26
+ "material", // 26
};
private static readonly string[] _SaleTypeNames = new string[]
@@ -322,17 +337,16 @@ static bool CheckDirectCopyBE()
#endregion String Arrays
- #region BytesTo
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ApproxEqual(float a, float b, float tolerance, float reltolerance = float.Epsilon)
{
- float dif = Math.Abs(a - b);
+ float dif = MathF.Abs(a - b);
if (dif <= tolerance)
return true;
- a = Math.Abs(a);
- b = Math.Abs(b);
+ a = MathF.Abs(a);
+ b = MathF.Abs(b);
if (b > a)
a = b;
return dif <= a * reltolerance;
@@ -341,24 +355,24 @@ public static bool ApproxEqual(float a, float b, float tolerance, float reltoler
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ApproxZero(float a, float tolerance)
{
- return Math.Abs(a) <= tolerance;
+ return MathF.Abs(a) <= tolerance;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ApproxZero(float a)
{
- return Math.Abs(a) <= 1e-6;
+ return MathF.Abs(a) <= 1e-6;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ApproxEqual(float a, float b)
{
- float dif = Math.Abs(a - b);
+ float dif = MathF.Abs(a - b);
if (dif <= 1e-6f)
return true;
- a = Math.Abs(a);
- b = Math.Abs(b);
+ a = MathF.Abs(a);
+ b = MathF.Abs(b);
if (b > a)
a = b;
return dif <= a * float.Epsilon;
@@ -384,13 +398,14 @@ public static unsafe short BytesToInt16(byte[] bytes)
//if (bytes.Length < 2 ) return 0;
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- return *(short*)p;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
else
return (short)(bytes[0] | (bytes[1] << 8));
}
+ #region BytesTo
+
///
/// Convert the first two bytes starting at the given position in
/// little endian ordering to a signed short integer
@@ -405,8 +420,7 @@ public static unsafe short BytesToInt16(byte[] bytes, int pos)
//if (bytes.Length < pos + 2) return 0;
if (CanDirectCopyLE)
{
- fixed (byte* p = &bytes[pos])
- return *(short*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return (short)(bytes[pos] | (bytes[pos + 1] << 8));
@@ -437,9 +451,8 @@ public unsafe static int BytesToInt(byte[] bytes, int pos)
{
if (CanDirectCopyLE)
{
- if (bytes.Length < pos + 4) return 0;
- fixed (byte* p = &bytes[pos])
- return *(int*)p;
+ //if (bytes.Length < pos + 4) return 0;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
return bytes[pos] |
@@ -453,7 +466,7 @@ public unsafe static int BytesToInt(byte* bytes)
{
if (CanDirectCopyLE)
{
- return *(int*)bytes;
+ return *(int*)bytes;
}
return *bytes |
@@ -467,8 +480,7 @@ public unsafe static int BytesToIntSafepos(byte[] bytes, int pos)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = &bytes[pos])
- return *(int*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
return bytes[pos] |
@@ -489,8 +501,7 @@ public unsafe static int BytesToInt(byte[] bytes)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- return *(int*)p;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
else
return bytes[0] |
@@ -529,8 +540,7 @@ public unsafe static long BytesToInt64(byte[] bytes)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- return *(long*)p;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
else
return
@@ -591,8 +601,7 @@ public unsafe static long BytesToInt64(byte[] bytes, int pos)
if (CanDirectCopyLE)
{
if (bytes.Length < pos + 8) return 0;
- fixed (byte* p = &bytes[pos])
- return *(long*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return
@@ -611,8 +620,7 @@ public unsafe static long BytesToInt64Safepos(byte[] bytes, int pos)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = &bytes[pos])
- return *(long*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return
@@ -640,8 +648,7 @@ public static unsafe ushort BytesToUInt16(byte[] bytes, int pos)
//if (bytes.Length < pos + 2) return 0;
if (CanDirectCopyLE)
{
- fixed (byte* p = &bytes[pos])
- return *(ushort*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return (ushort)(bytes[pos] + (bytes[pos + 1] << 8));
@@ -669,8 +676,7 @@ public static unsafe ushort BytesToUInt16(byte[] bytes)
//if (bytes.Length < 2) return 0;
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- return *(ushort*)p;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
else
return (ushort)(bytes[0] + (bytes[1] << 8));
@@ -690,8 +696,7 @@ public unsafe static uint BytesToUInt(byte[] bytes, int pos)
if (CanDirectCopyLE)
{
if (bytes.Length < pos + 4) return 0;
- fixed (byte* p = &bytes[pos])
- return *(uint*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return (uint)(
@@ -706,8 +711,7 @@ public unsafe static uint BytesToUIntSafepos(byte[] bytes, int pos)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = &bytes[pos])
- return *(uint*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return (uint)(
@@ -729,8 +733,7 @@ public unsafe static uint BytesToUInt(byte[] bytes)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- return *(uint*)p;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
else
return (uint)(
@@ -765,11 +768,10 @@ public unsafe static uint BytesToUInt(byte* bytes)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static ulong BytesToUInt64(byte[] bytes, int pos)
{
+ if (bytes.Length < pos + 8) return 0;
if (CanDirectCopyLE)
{
- if (bytes.Length < pos + 8) return 0;
- fixed (byte* p = &bytes[pos])
- return *(ulong*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return (ulong)(
@@ -788,8 +790,7 @@ public unsafe static ulong BytesToUInt64Safepos(byte[] bytes, int pos)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = &bytes[pos])
- return *(ulong*)p;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
else
return (ulong)(
@@ -815,8 +816,7 @@ public unsafe static ulong BytesToUInt64(byte[] bytes)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- return *(ulong*)p;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
else
return (ulong)(
@@ -861,8 +861,7 @@ public unsafe static ulong BytesToUInt64(byte* bytes)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static float BytesToFloat(byte[] bytes)
{
- int tmp = BytesToInt(bytes);
- return *(float*)&tmp;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -875,22 +874,19 @@ public unsafe static float BytesToFloat(byte* bytes)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static float BytesToFloat(byte[] bytes, int pos)
{
- int tmp = BytesToInt(bytes, pos);
- return *(float*)&tmp;
+ return Unsafe.As(ref bytes[pos]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static float BytesToFloatSafepos(byte[] bytes, int pos)
{
- int tmp = BytesToIntSafepos(bytes, pos);
- return *(float*)&tmp;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static double BytesToDouble(byte[] bytes)
{
- long tmp = BytesToInt64(bytes);
- return *(double*)&tmp;
+ return Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -910,26 +906,24 @@ public unsafe static double BytesToDouble(byte* bytes)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static double BytesToDouble(byte[] bytes, int pos)
{
- long tmp = BytesToInt64(bytes, pos);
- return *(double*)&tmp;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static double BytesToDoubleSafepos(byte[] bytes, int pos)
{
- long tmp = BytesToInt64Safepos(bytes, pos);
- return *(double*)&tmp;
+ return Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(bytes), pos));
}
#endregion BytesTo
-
#region ToBytes
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] Int16ToBytes(short value)
{
byte[] bytes = new byte[2];
- bytes[0] = (byte)(value);
- bytes[1] = (byte)((value >> 8));
+ bytes[0] = (byte)value;
+ bytes[1] = (byte)(value >> 8);
return bytes;
}
@@ -943,52 +937,69 @@ public static void Int16ToBytes(Stream ms, short value)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Int16ToBytes(short value, byte[] dest, int pos)
{
- dest[pos] = (byte)(value);
- dest[pos + 1] = (byte)((value >> 8));
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Int16ToBytes(short value, byte* dest)
{
- *dest = (byte)(value);
- dest[1] = (byte)((value >> 8));
+ *(short*)dest = value;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe void Int16ToBytes(short value, byte* dest, int pos)
+ {
+
+ *(short*)dest[pos] = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] UInt16ToBytes(ushort value)
{
byte[] bytes = new byte[2];
- bytes[0] = (byte)(value);
- bytes[1] = (byte)((value >> 8));
+ bytes[0] = (byte)value;
+ bytes[1] = (byte)(value >> 8);
return bytes;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UInt16ToBytes(ushort value, byte[] dest, int pos)
{
- dest[pos] = (byte)(value);
- dest[pos + 1] = (byte)((value >> 8));
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
+
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe void UInt16ToBytes(ushort value, byte* dest, int pos)
+ {
+ *(ushort*)dest[pos] = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void UInt16ToBytes(ushort value, byte* dest)
{
- *dest = (byte)(value);
- dest[1] = (byte)((value >> 8));
+ *(ushort*)dest = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UInt16ToBytesBig(ushort value, byte[] dest, int pos)
{
- dest[pos] = (byte)((value >> 8));
- dest[pos + 1] = (byte)(value);
+ dest[pos] = (byte)(value >> 8);
+ dest[pos + 1] = (byte)value;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void UInt16ToBytesBig(ushort value, byte* dest, int pos)
+ {
+ dest[pos] = (byte)(value >> 8);
+ dest[pos + 1] = (byte)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void UInt16ToBytesBig(ushort value, byte* dest)
{
- *dest = (byte)((value >> 8));
- dest[1] = (byte)(value);
+ *dest = (byte)(value >> 8);
+ dest[1] = (byte)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1011,6 +1022,7 @@ public unsafe static byte[] IntToBytes(int value)
byte[] bytes = new byte[4];
if (CanDirectCopyLE)
{
+ //Unsafe.As(ref bytes[0]) = value;
fixed (byte* p = bytes)
*(int*)p = value;
}
@@ -1027,11 +1039,25 @@ public unsafe static byte[] IntToBytes(int value)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void IntToBytes(int value, byte[] dest, int pos)
{
+ if (dest.Length < pos + 4) return;
if (CanDirectCopyLE)
{
- if (dest.Length < pos + 4) return;
- fixed (byte* p = &dest[pos])
- *(int*)p = value;
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
+ }
+ else
+ {
+ dest[pos] = (byte)(value);
+ dest[pos + 1] = (byte)((value >> 8));
+ dest[pos + 2] = (byte)((value >> 16));
+ dest[pos + 3] = (byte)((value >> 24));
+ }
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void IntToBytes(int value, byte* dest, int pos)
+ {
+ if (CanDirectCopyLE)
+ {
+ *(int*)dest[pos] = value;
}
else
{
@@ -1063,8 +1089,7 @@ public unsafe static void IntToBytesSafepos(int value, byte[] dest, int pos)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = &dest[pos])
- *(int*)p = value;
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
}
else
{
@@ -1103,6 +1128,15 @@ public static void IntToBytesBig(int value, byte[] bytes, int pos)
bytes[pos + 3] = (byte)value;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void IntToBytesBig(int value, byte* bytes, int pos)
+ {
+ bytes[pos] = (byte)(value >> 24);
+ bytes[pos + 1] = (byte)(value >> 16);
+ bytes[pos + 2] = (byte)(value >> 8);
+ bytes[pos + 3] = (byte)value;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void IntToBytesBig(int value, byte* bytes)
{
@@ -1118,12 +1152,24 @@ public unsafe static byte[] UIntToBytes(uint value)
return IntToBytes((int)value);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void UIntToBytes(uint value, byte* dest)
+ {
+ IntToBytes((int)value, dest);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void UIntToBytes(uint value, byte[] dest, int pos)
{
IntToBytes((int)value, dest, pos);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void UIntToBytes(uint value, byte* dest, int pos)
+ {
+ IntToBytes((int)value, dest, pos);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void UIntToBytesSafepos(uint value, byte[] dest, int pos)
{
@@ -1147,8 +1193,7 @@ public unsafe static byte[] Int64ToBytes(long value)
byte[] bytes = new byte[8];
if (CanDirectCopyLE)
{
- fixed (byte* p = bytes)
- *(long*)p = value;
+ Unsafe.As(ref MemoryMarshal.GetArrayDataReference(bytes)) = value;
}
else
{
@@ -1169,9 +1214,29 @@ public unsafe static void Int64ToBytes(long value, byte[] dest, int pos)
{
if (CanDirectCopyLE)
{
+ //Unsafe.As(ref dest[pos]) = value;
if (dest.Length < pos + 8) return;
- fixed (byte* p = &dest[pos])
- *(long*)p = value;
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
+ }
+ else
+ {
+ dest[pos] = (byte)value;
+ dest[pos + 1] = (byte)(value >> 8);
+ dest[pos + 2] = (byte)(value >> 16);
+ dest[pos + 3] = (byte)(value >> 24);
+ dest[pos + 4] = (byte)(value >> 32);
+ dest[pos + 5] = (byte)(value >> 40);
+ dest[pos + 6] = (byte)(value >> 48);
+ dest[pos + 7] = (byte)(value >> 56);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void Int64ToBytes(long value, byte* dest, int pos)
+ {
+ if (CanDirectCopyLE)
+ {
+ *(long*)dest[pos] = value;
}
else
{
@@ -1211,8 +1276,7 @@ public unsafe static void Int64ToBytesSafepos(long value, byte[] dest, int pos)
{
if (CanDirectCopyLE)
{
- fixed (byte* p = &dest[pos])
- *(long*)p = value;
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
}
else
{
@@ -1240,7 +1304,6 @@ public static void Int64ToBytes(Stream ms, long value)
ms.WriteByte((byte)(value >> 56));
}
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] Int64ToBytesBig(long value)
{
@@ -1269,6 +1332,19 @@ public static void Int64ToBytesBig(long value, byte[] dest, int pos)
dest[pos + 7] = (byte)value;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void Int64ToBytesBig(long value, byte* dest, int pos)
+ {
+ dest[pos] = (byte)(value >> 56);
+ dest[pos + 1] = (byte)(value >> 48);
+ dest[pos + 2] = (byte)(value >> 40);
+ dest[pos + 3] = (byte)(value >> 32);
+ dest[pos + 4] = (byte)(value >> 24);
+ dest[pos + 5] = (byte)(value >> 16);
+ dest[pos + 6] = (byte)(value >> 8);
+ dest[pos + 7] = (byte)value;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Int64ToBytesBig(long value, byte* dest)
{
@@ -1300,12 +1376,24 @@ public static byte[] UInt64ToBytesBig(ulong value)
return Int64ToBytesBig((long)value);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void UInt64ToBytes(ulong value, byte* dest)
+ {
+ Int64ToBytes((long)value, dest);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void UInt64ToBytes(ulong value, byte[] dest, int pos)
{
Int64ToBytes((long)value, dest, pos);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void UInt64ToBytes(ulong value, byte* dest, int pos)
+ {
+ Int64ToBytes((long)value, dest, pos);
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void UInt64ToBytesSafepos(ulong value, byte[] dest, int pos)
{
@@ -1340,6 +1428,13 @@ public unsafe static void FloatToBytes(Stream ms, float value)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void FloatToBytes(float value, byte[] dest, int pos)
{
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void FloatToBytes(float value, byte* dest, int pos)
+ {
+ //Unsafe.As(ref dest[pos]) = value;
IntToBytes(*(int*)&value, dest, pos);
}
@@ -1352,7 +1447,7 @@ public unsafe static void FloatToBytes(float value, byte* dest)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void FloatToBytesSafepos(float value, byte[] dest, int pos)
{
- IntToBytesSafepos(*(int*)&value, dest, pos);
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1375,6 +1470,12 @@ public unsafe static byte[] DoubleToBytesBig(double value)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void DoubleToBytes(double value, byte[] dest, int pos)
+ {
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void DoubleToBytes(double value, byte* dest, int pos)
{
Int64ToBytes(*(long*)&value, dest, pos);
}
@@ -1388,7 +1489,7 @@ public unsafe static void DoubleToBytes(double value, byte* dest)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static void DoubleToBytesSafepos(double value, byte[] dest, int pos)
{
- Int64ToBytesSafepos(*(long*)&value, dest, pos);
+ Unsafe.As(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(dest), pos)) = value;
}
#endregion ToBytes
@@ -1423,7 +1524,7 @@ public static string BytesToString(byte[] bytes)
public static string BytesToString(byte[] bytes, int index, int count)
{
- if (bytes.Length <= index + count)
+ if (bytes.Length < index + count)
return string.Empty;
if (bytes[index + count - 1] == 0x00)
return Encoding.UTF8.GetString(bytes, index, count - 1);
@@ -1715,14 +1816,15 @@ public static unsafe bool osUTF8TryGetbytes(string srcstr, ref int srcstart, byt
return ret;
}
- public static int osUTF8GetBytesCount(string str, out int maxsource)
+ public static int osUTF8GetBytesCount(string sstr, out int maxsource)
{
maxsource = 0;
char c;
char lastc = (char)0;
int nbytes = 0;
int i = 0;
- while(i < str.Length)
+ var str = sstr.AsSpan();
+ while (i < str.Length)
{
c = str[i++];
@@ -1766,16 +1868,17 @@ public static int osUTF8GetBytesCount(string str, out int maxsource)
return nbytes;
}
- public static int osUTF8GetBytesCount(string str, int maxnbytes, out int maxsourcelen)
+ public static int osUTF8GetBytesCount(string sstr, int maxnbytes, out int maxsourcelen)
{
maxsourcelen = 0;
int max2 = maxnbytes - 2;
int max3 = maxnbytes - 3;
int max4 = maxnbytes - 4;
- char c = ' ';
+ char c;
int nbytes = 0;
int i = 0;
+ var str = sstr.AsSpan();
while(i < str.Length && nbytes < maxnbytes)
{
c = str[i++];
@@ -1824,6 +1927,7 @@ public static int osUTF8GetBytesCount(string str, int maxnbytes, out int maxsour
///
/// Character to test
/// true if hex digit, false if not
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexDigit(Char c)
{
@@ -1846,7 +1950,7 @@ public static bool IsHexDigit(Char c)
return false;
}
-
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int HexNibbleWithChk(Char c)
{
const int numA = 65;
@@ -1868,7 +1972,7 @@ public static int HexNibbleWithChk(Char c)
return -1;
}
-
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int HexNibbleWithChk(byte c)
{
const int numA = 65;
@@ -1891,6 +1995,7 @@ public static int HexNibbleWithChk(byte c)
return -1;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int HexNibble(Char c)
{
@@ -1917,6 +2022,7 @@ public static int HexNibble(Char c)
throw new FormatException("invalid hex char");
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int HexNibble(byte c)
{
const byte numA = (byte)'A';
@@ -1988,7 +2094,7 @@ public unsafe static byte HexToByte(byte* data, int pos)
return (byte)(HexNibble(data[pos]) << 4 | HexNibble(data[pos + 1]));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe static byte HexToByte(char* hex, int pos)
{
return (byte)(HexNibble(hex[pos]) << 4 | HexNibble(hex[pos + 1]));
@@ -2063,6 +2169,30 @@ public static byte FloatToByte(float val, float lower, float upper)
return (byte)(255 * val);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte FloatZeroOneToByte(float val)
+ {
+ if (val <= 0)
+ return 0;
+ if (val >= 1.0f)
+ return 255;
+
+ return (byte)(255 * val);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort FloatZeroOneToushort(float val)
+ {
+ if (val <= 0)
+ return 0;
+
+ if (val >= 1.0f)
+ return 0xffff;
+
+ return (ushort)(val * 0xffff);
+ }
+
+
///
/// Convert a byte to a float value given a minimum and maximum range
///
@@ -2130,6 +2260,7 @@ public static ushort FloatToUInt16(float value, float lower, float upper)
return (ushort)(value * 0xffff);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort FloatToUInt16(float value, float range)
{
value += range;
@@ -2143,53 +2274,39 @@ public static ushort FloatToUInt16(float value, float range)
return (ushort)(value * 32767.5);
}
- public static void FloatToUInt16Bytes(float value, float range, byte[] dest, int pos)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort FloatToUnitUInt16(float value)
{
- value += range;
- if (value <= 0)
- {
- dest[pos] = 0;
- dest[pos + 1] = 0;
- return;
- }
+ if (value <= -1.0)
+ return 0;
- value /= range;
- if (value >= 2.0f)
- {
- dest[pos] = 0xff;
- dest[pos + 1] = 0xff;
- return;
- }
+ if (value >= 1.0f)
+ return 0xffff;
- ushort s = (ushort)(value * 32767.5);
- dest[pos] = (byte)s;
- dest[pos + 1] = (byte)(s >> 8);
+ return (ushort)(value * 32767.5 + 32767);
}
- public static byte[] FloatToUInt16Bytes(float value, float range)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void FloatToUInt16Bytes(float value, float range, byte[] dest, int pos)
{
- byte[] dest = new byte[2];
+ UInt16ToBytes(FloatToUInt16(value, range), dest, pos);
+ }
- value += range;
- if (value <= 0)
- {
- dest[0] = 0;
- dest[1] = 0;
- return dest;
- }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void FloatToUInt16Bytes(float value, float range, byte* dest, int pos)
+ {
+ UInt16ToBytes(FloatToUInt16(value, range), dest, pos);
+ }
- value /= range;
- if (value >= 2.0f)
- {
- dest[0] = 0xff;
- dest[1] = 0xff;
- return dest;
- }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static void FloatToUInt16Bytes(float value, float range, byte* dest)
+ {
+ UInt16ToBytes(FloatToUInt16(value, range), dest);
+ }
- ushort s = (ushort)(value * 32767.5);
- dest[0] = (byte)s;
- dest[1] = (byte)(s >> 8);
- return dest;
+ public unsafe static byte[] FloatToUInt16Bytes(float value, float range)
+ {
+ return UInt16ToBytes(FloatToUInt16(value, range));
}
#endregion Packed Values
@@ -2393,7 +2510,7 @@ public static byte[] CopyBytes(byte[] bytes)
return null;
byte[] newBytes = new byte[bytes.Length];
- Buffer.BlockCopy(bytes, 0, newBytes, 0, bytes.Length);
+ Array.Copy(bytes, newBytes, bytes.Length);
return newBytes;
}
@@ -2492,9 +2609,7 @@ public static uint DateTimeToUnixTime(DateTime time)
/// Second value
public static void Swap(ref T lhs, ref T rhs)
{
- T temp = lhs;
- lhs = rhs;
- rhs = temp;
+ (rhs, lhs) = (lhs, rhs);
}
///
@@ -2882,8 +2997,51 @@ public static byte HighNibbleToHexByteChar(byte b)
return (byte)(b > 9 ? b + 0x57 : b + ASCIIzero);
}
- public static unsafe void UUIDToByteDashString(ref UUID u, byte* dst)
+ public static unsafe void UUIDToByteDashString(UUID u, byte* dst)
{
+ if (Sse41.IsSupported)
+ {
+ Vector128 lower = Unsafe.As>(ref Unsafe.AsRef(in u));
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Vector128 upper = (Sse2.ShiftRightLogical(lower.AsInt32(), 4)).AsByte();
+
+ Vector128 mask0f = Vector128.Create((byte)0x0f);
+ lower = Sse2.And(mask0f, lower);
+ upper = Sse2.And(mask0f, upper);
+
+ Vector128 pastNine = Vector128.Create((sbyte)10);
+ Vector128 lowerMask = Sse2.CompareLessThan(lower.AsSByte(), pastNine).AsByte();
+ Vector128 upperMask = Sse2.CompareLessThan(upper.AsSByte(), pastNine).AsByte();
+
+ Vector128 first = Vector128.Create((byte)'0');
+ Vector128 second = Vector128.Create((byte)('a' - 10));
+ Vector128 addlower = Sse41.BlendVariable(second, first, lowerMask);
+ Vector128 addupper = Sse41.BlendVariable(second, first, upperMask);
+
+ lower = Sse2.Add(lower, addlower);
+ upper = Sse2.Add(upper, addupper);
+
+ Vector128 mask1 = Ssse3.Shuffle(lower, Vector128.Create(0xff, 0, 0xff, 1, 0xff, 2, 0xff, 3, 0xff, 0xff, 4, 0xff, 5, 0xff, 0xff, 6));
+ Vector128 mask2 = Ssse3.Shuffle(upper, Vector128.Create(0, 0xff, 1, 0xff, 2, 0xff, 3, 0xff, 0xff, 4, 0xff, 5, 0xff, 0xff, 6, 0xff));
+ Vector128 mask3 = Ssse3.Shuffle(lower, Vector128.Create(0xff, 7, 0xff, 0xff, 8, 0xff, 9, 0xff, 0xff, 10, 0xff, 11, 0xff, 12, 0xff, 13));
+ Vector128 mask4 = Ssse3.Shuffle(upper, Vector128.Create(7, 0xff, 0xff, 8, 0xff, 9, 0xff, 0xff, 10, 0xff, 11, 0xff, 12, 0xff, 13, 0xff));
+ Vector128 hypens = Vector128.Create(0, 0, (byte)'-', 0, 0, 0, 0, (byte)'-', 0, 0, 0, 0, 0, 0, 0, 0);
+ Vector128 hypens2 = Vector128.Create(0, 0, 0, 0, 0, 0, 0, 0, (byte)'-', 0, 0, 0, 0, (byte)'-', 0, 0);
+ Vector128 upperSorted = Sse2.Or(Sse2.Or(mask1, mask2), hypens2);
+ Vector128 lowerSorted = Sse2.Or(Sse2.Or(mask3, mask4), hypens);
+
+ Unsafe.As>(ref Unsafe.AsRef(dst)) = upperSorted;
+ Unsafe.As>(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(dst), 16)) = lowerSorted;
+
+ int v1 = Sse2.Extract(upper.AsUInt16(), 7);
+ int v2 = Sse2.Extract(lower.AsUInt16(), 7);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(dst), 32)) = (byte)(v1 & 0xff);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(dst), 33)) = (byte)(v2 & 0xff);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(dst), 34)) = (byte)((v1 >> 8) & 0xff);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.AsRef(dst), 35)) = (byte)((v2 >> 8) & 0xff);
+ return;
+ }
byte b;
if (BitConverter.IsLittleEndian)
{
@@ -2992,17 +3150,7 @@ public static unsafe osUTF8 UUIDToosUTF8(UUID v)
{
osUTF8 ret = new osUTF8(36);
fixed (byte* d = ret.m_data)
- UUIDToByteDashString(ref v, d);
- ret.m_len = 36;
- return ret;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe osUTF8 UUIDToosUTF8(ref UUID v)
- {
- osUTF8 ret = new osUTF8(36);
- fixed (byte* d = ret.m_data)
- UUIDToByteDashString(ref v, d);
+ UUIDToByteDashString(v, d);
ret.m_len = 36;
return ret;
}
@@ -3028,116 +3176,169 @@ public static char charHighNibbleToHexChar(byte b)
return (char)(b > 9 ? b + 0x57 : b + ASCIIzero);
}
- public static string UUIDToDashString(ref UUID u)
+ public static string UUIDToDashString(UUID u)
{
- char[] dst = new char[36];
- byte b;
- if (BitConverter.IsLittleEndian)
- {
- //a
- b = u.bytea3;
- dst[0] = charHighNibbleToHexChar(b);
- dst[1] = charLowNibbleToHexChar(b);
- b = u.bytea2;
- dst[2] = charHighNibbleToHexChar(b);
- dst[3] = charLowNibbleToHexChar(b);
- b = u.bytea1;
- dst[4] = charHighNibbleToHexChar(b);
- dst[5] = charLowNibbleToHexChar(b);
- b = u.bytea0;
- dst[6] = charHighNibbleToHexChar(b);
- dst[7] = charLowNibbleToHexChar(b);
-
- dst[8] = '-';
-
- //b
- b = u.byteb1;
- dst[9] = charHighNibbleToHexChar(b);
- dst[10] = charLowNibbleToHexChar(b);
- b = u.byteb0;
- dst[11] = charHighNibbleToHexChar(b);
- dst[12] = charLowNibbleToHexChar(b);
-
- dst[13] = '-';
-
- //c
- b = u.bytec1;
- dst[14] = charHighNibbleToHexChar(b);
- dst[15] = charLowNibbleToHexChar(b);
- b = u.bytec0;
- dst[16] = charHighNibbleToHexChar(b);
- dst[17] = charLowNibbleToHexChar(b);
- }
- else
+ return string.Create(36, u, (dst, u) =>
{
- //a
- b = u.bytea0;
- dst[0] = charHighNibbleToHexChar(b);
- dst[1] = charLowNibbleToHexChar(b);
- b = u.bytea1;
- dst[2] = charHighNibbleToHexChar(b);
- dst[3] = charLowNibbleToHexChar(b);
- b = u.bytea2;
- dst[4] = charHighNibbleToHexChar(b);
- dst[5] = charLowNibbleToHexChar(b);
- b = u.bytea3;
- dst[6] = charHighNibbleToHexChar(b);
- dst[7] = charLowNibbleToHexChar(b);
-
- dst[8] = '-';
-
- //b
- b = u.byteb0;
- dst[9] = charHighNibbleToHexChar(b);
- dst[10] = charLowNibbleToHexChar(b);
- b = u.byteb1;
- dst[11] = charHighNibbleToHexChar(b);
- dst[12] = charLowNibbleToHexChar(b);
-
- dst[13] = '-';
-
- //c
- b = u.bytec0;
- dst[14] = charHighNibbleToHexChar(b);
- dst[15] = charLowNibbleToHexChar(b);
- b = u.bytec1;
- dst[16] = charHighNibbleToHexChar(b);
- dst[17] = charLowNibbleToHexChar(b);
- }
-
-
- dst[18] = '-';
-
- b = u.d; //d
- dst[19] = charHighNibbleToHexChar(b);
- dst[20] = charLowNibbleToHexChar(b);
- b = u.e; //e
- dst[21] = charHighNibbleToHexChar(b);
- dst[22] = charLowNibbleToHexChar(b);
-
- dst[23] = '-';
+ if (Sse41.IsSupported)
+ {
+ Vector128 lower = Unsafe.As>(ref Unsafe.AsRef(in u));
+ if (BitConverter.IsLittleEndian)
+ lower = Ssse3.Shuffle(lower, Vector128.Create((byte)0x03, 0x02, 0x01, 0x00, 0x05, 0x04, 0x07, 0x06, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F));
+ Vector128 upper = (Sse2.ShiftRightLogical(lower.AsInt32(), 4)).AsByte();
+
+ Vector128 mask0f = Vector128.Create((byte)0x0f);
+ lower = Sse2.And(mask0f, lower);
+ upper = Sse2.And(mask0f, upper);
+
+ Vector128 pastNine = Vector128.Create((sbyte)10);
+ Vector128 lowerMask = Sse2.CompareLessThan(lower.AsSByte(), pastNine).AsByte();
+ Vector128 upperMask = Sse2.CompareLessThan(upper.AsSByte(), pastNine).AsByte();
+
+ Vector128 first = Vector128.Create((byte)'0');
+ Vector128 second = Vector128.Create((byte)('a' - 10));
+ Vector128 addlower = Sse41.BlendVariable(second, first, lowerMask);
+ Vector128 addupper = Sse41.BlendVariable(second, first, upperMask);
+
+ lower = Sse2.Add(lower, addlower);
+ upper = Sse2.Add(upper, addupper);
+
+ Vector128 mask1 = Ssse3.Shuffle(lower, Vector128.Create(0xff, 0, 0xff, 1, 0xff, 2, 0xff, 3, 0xff, 0xff, 4, 0xff, 5, 0xff, 0xff, 6));
+ Vector128 mask2 = Ssse3.Shuffle(upper, Vector128.Create(0, 0xff, 1, 0xff, 2, 0xff, 3, 0xff, 0xff, 4, 0xff, 5, 0xff, 0xff, 6, 0xff));
+ Vector128 mask3 = Ssse3.Shuffle(lower, Vector128.Create(0xff, 7, 0xff, 0xff, 8, 0xff, 9, 0xff, 0xff, 10, 0xff, 11, 0xff, 12, 0xff, 13));
+ Vector128 mask4 = Ssse3.Shuffle(upper, Vector128.Create(7, 0xff, 0xff, 8, 0xff, 9, 0xff, 0xff, 10, 0xff, 11, 0xff, 12, 0xff, 13, 0xff));
+ Vector128 hypens = Vector128.Create(0, 0, (byte)'-', 0, 0, 0, 0, (byte)'-', 0, 0, 0, 0, 0, 0, 0, 0);
+ Vector128 hypens2 = Vector128.Create(0, 0, 0, 0, 0, 0, 0, 0, (byte)'-', 0, 0, 0, 0, (byte)'-', 0, 0);
+ Vector128 upperSorted = Sse2.Or(Sse2.Or(mask1, mask2), hypens2);
+ Vector128 lowerSorted = Sse2.Or(Sse2.Or(mask3, mask4), hypens);
+
+ Vector128 charsMask0 = Vector128.Create(0, 0xff, 1, 0xff, 2, 0xff, 3, 0xff, 4, 0xff, 5, 0xff, 6, 0xff, 7, 0xff);
+ Vector128 chars0 = Ssse3.Shuffle(upperSorted, charsMask0);
+ Unsafe.As>(ref MemoryMarshal.GetReference(dst)) = chars0;
+
+ Vector128 charsMask1 = Vector128.Create(8, 0xff, 9, 0xff, 10, 0xff, 11, 0xff, 12, 0xff, 13, 0xff, 14, 0xff, 15, 0xff);
+ Vector128 chars1 = Ssse3.Shuffle(upperSorted, charsMask1);
+ Unsafe.As>(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 16)) = chars1;
+
+ chars0 = Ssse3.Shuffle(lowerSorted, charsMask0);
+ Unsafe.As>(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 32)) = chars0;
+
+ chars1 = Ssse3.Shuffle(lowerSorted, charsMask1);
+ Unsafe.As>(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 48)) = chars1;
+
+ int v1 = Sse2.Extract(upper.AsUInt16(), 7);
+ int v2 = Sse2.Extract(lower.AsUInt16(), 7);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 64)) = (byte)(v1 & 0xff);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 66)) = (byte)(v2 & 0xff);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 68)) = (byte)((v1 >> 8) & 0xff);
+ Unsafe.As(ref Unsafe.AddByteOffset(ref MemoryMarshal.GetReference(dst), 70)) = (byte)((v2 >> 8) & 0xff);
+ return;
+ }
+ byte b;
+ if (BitConverter.IsLittleEndian)
+ {
+ //a
+ b = u.bytea3;
+ dst[0] = charHighNibbleToHexChar(b);
+ dst[1] = charLowNibbleToHexChar(b);
+ b = u.bytea2;
+ dst[2] = charHighNibbleToHexChar(b);
+ dst[3] = charLowNibbleToHexChar(b);
+ b = u.bytea1;
+ dst[4] = charHighNibbleToHexChar(b);
+ dst[5] = charLowNibbleToHexChar(b);
+ b = u.bytea0;
+ dst[6] = charHighNibbleToHexChar(b);
+ dst[7] = charLowNibbleToHexChar(b);
+
+ dst[8] = '-';
+
+ //b
+ b = u.byteb1;
+ dst[9] = charHighNibbleToHexChar(b);
+ dst[10] = charLowNibbleToHexChar(b);
+ b = u.byteb0;
+ dst[11] = charHighNibbleToHexChar(b);
+ dst[12] = charLowNibbleToHexChar(b);
+
+ dst[13] = '-';
+
+ //c
+ b = u.bytec1;
+ dst[14] = charHighNibbleToHexChar(b);
+ dst[15] = charLowNibbleToHexChar(b);
+ b = u.bytec0;
+ dst[16] = charHighNibbleToHexChar(b);
+ dst[17] = charLowNibbleToHexChar(b);
+ }
+ else
+ {
+ //a
+ b = u.bytea0;
+ dst[0] = charHighNibbleToHexChar(b);
+ dst[1] = charLowNibbleToHexChar(b);
+ b = u.bytea1;
+ dst[2] = charHighNibbleToHexChar(b);
+ dst[3] = charLowNibbleToHexChar(b);
+ b = u.bytea2;
+ dst[4] = charHighNibbleToHexChar(b);
+ dst[5] = charLowNibbleToHexChar(b);
+ b = u.bytea3;
+ dst[6] = charHighNibbleToHexChar(b);
+ dst[7] = charLowNibbleToHexChar(b);
+
+ dst[8] = '-';
+
+ //b
+ b = u.byteb0;
+ dst[9] = charHighNibbleToHexChar(b);
+ dst[10] = charLowNibbleToHexChar(b);
+ b = u.byteb1;
+ dst[11] = charHighNibbleToHexChar(b);
+ dst[12] = charLowNibbleToHexChar(b);
+
+ dst[13] = '-';
+
+ //c
+ b = u.bytec0;
+ dst[14] = charHighNibbleToHexChar(b);
+ dst[15] = charLowNibbleToHexChar(b);
+ b = u.bytec1;
+ dst[16] = charHighNibbleToHexChar(b);
+ dst[17] = charLowNibbleToHexChar(b);
+ }
- b = u.f; //f
- dst[24] = charHighNibbleToHexChar(b);
- dst[25] = charLowNibbleToHexChar(b);
- b = u.g; //g
- dst[26] = charHighNibbleToHexChar(b);
- dst[27] = charLowNibbleToHexChar(b);
- b = u.h; //h
- dst[28] = charHighNibbleToHexChar(b);
- dst[29] = charLowNibbleToHexChar(b);
- b = u.i; //i
- dst[30] = charHighNibbleToHexChar(b);
- dst[31] = charLowNibbleToHexChar(b);
- b = u.j; //j
- dst[32] = charHighNibbleToHexChar(b);
- dst[33] = charLowNibbleToHexChar(b);
- b = u.k; //k
- dst[34] = charHighNibbleToHexChar(b);
- dst[35] = charLowNibbleToHexChar(b);
- return new string(dst);
+ dst[18] = '-';
+
+ b = u.d; //d
+ dst[19] = charHighNibbleToHexChar(b);
+ dst[20] = charLowNibbleToHexChar(b);
+ b = u.e; //e
+ dst[21] = charHighNibbleToHexChar(b);
+ dst[22] = charLowNibbleToHexChar(b);
+
+ dst[23] = '-';
+
+ b = u.f; //f
+ dst[24] = charHighNibbleToHexChar(b);
+ dst[25] = charLowNibbleToHexChar(b);
+ b = u.g; //g
+ dst[26] = charHighNibbleToHexChar(b);
+ dst[27] = charLowNibbleToHexChar(b);
+ b = u.h; //h
+ dst[28] = charHighNibbleToHexChar(b);
+ dst[29] = charLowNibbleToHexChar(b);
+ b = u.i; //i
+ dst[30] = charHighNibbleToHexChar(b);
+ dst[31] = charLowNibbleToHexChar(b);
+ b = u.j; //j
+ dst[32] = charHighNibbleToHexChar(b);
+ dst[33] = charLowNibbleToHexChar(b);
+ b = u.k; //k
+ dst[34] = charHighNibbleToHexChar(b);
+ dst[35] = charLowNibbleToHexChar(b);
+ });
}
-
#endregion Miscellaneous
}
}
diff --git a/OpenMetaverse.Types/Vector2.cs b/OpenMetaverse.Types/Vector2.cs
index 76f6ef4e..26f52c90 100644
--- a/OpenMetaverse.Types/Vector2.cs
+++ b/OpenMetaverse.Types/Vector2.cs
@@ -28,6 +28,7 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Text;
namespace OpenMetaverse
{
@@ -156,6 +157,16 @@ public bool IsZero()
return true;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsNotZero()
+ {
+ if (X != 0)
+ return true;
+ if (Y != 0)
+ return true;
+ return false;
+ }
+
///
/// Test if this vector is composed of all finite numbers
///
@@ -183,7 +194,7 @@ public float Dot(Vector3 value2)
///
/// Byte array containing two four-byte floats
/// Beginning position in the byte array
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte[] byteArray, int pos)
{
X = Utils.BytesToFloatSafepos(byteArray, pos);
@@ -194,7 +205,7 @@ public void FromBytes(byte[] byteArray, int pos)
/// Returns the raw bytes for this vector
///
/// An eight-byte array containing X and Y
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte[] GetBytes()
{
byte[] dest = new byte[8];
@@ -209,32 +220,52 @@ public byte[] GetBytes()
/// Destination byte array
/// Position in the destination array to start
/// writing. Must be at least 8 bytes before the end of the array
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
- public void ToBytes(byte[] dest, int pos)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe void ToBytes(byte[] dest, int pos)
{
- Utils.FloatToBytesSafepos(X, dest, pos);
- Utils.FloatToBytesSafepos(Y, dest, pos + 4);
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ *(Vector2*)(d + pos) = this;
+ }
+ else
+ {
+ Utils.FloatToBytesSafepos(X, dest, pos);
+ Utils.FloatToBytesSafepos(Y, dest, pos + 4);
+ }
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe void ToBytes(byte* dest)
+ {
+ if (Utils.CanDirectCopyLE)
+ *(Vector2*)(dest) = this;
+ else
+ {
+ Utils.FloatToBytes(X, dest);
+ Utils.FloatToBytes(Y, dest + 4);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Length()
{
- return (float)Math.Sqrt(X * X + Y * Y);
+ return MathF.Sqrt(X * X + Y * Y);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public float LengthSquared()
{
return X * X + Y * Y;
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Normalize()
{
float factor = LengthSquared();
if (factor > 1e-6)
{
- factor = 1f / (float)Math.Sqrt(factor);
+ factor = 1f / MathF.Sqrt(factor);
X *= factor;
Y *= factor;
}
@@ -249,7 +280,7 @@ public void Normalize()
#region Static Methods
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Add(Vector2 value1, Vector2 value2)
{
return new Vector2(value1.X + value2.X, value1.Y + value2.Y);
@@ -263,7 +294,7 @@ public static Vector2 Clamp(Vector3 value1, float min, float max)
Utils.Clamp(value1.Y, min, max));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
{
return new Vector2(
@@ -271,13 +302,13 @@ public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
Utils.Clamp(value1.Y, min.Y, max.Y));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Distance(Vector2 value1, Vector2 value2)
{
- return (float)Math.Sqrt(DistanceSquared(value1, value2));
+ return MathF.Sqrt(DistanceSquared(value1, value2));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DistanceSquared(Vector2 value1, Vector2 value2)
{
return
@@ -285,20 +316,20 @@ public static float DistanceSquared(Vector2 value1, Vector2 value2)
(value1.Y - value2.Y) * (value1.Y - value2.Y);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Divide(Vector2 value1, Vector2 value2)
{
return new Vector2(value1.X / value2.X, value1.Y / value2.Y);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Divide(Vector2 value1, float divider)
{
float factor = 1 / divider;
return new Vector2(value1.X * factor, value1.Y * factor);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Dot(Vector2 value1, Vector2 value2)
{
return (value1.X * value2.X) + (value1.Y * value2.Y);
@@ -311,47 +342,47 @@ public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
Utils.Lerp(value1.Y, value2.Y, amount));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Max(Vector2 value1, Vector2 value2)
{
return new Vector2(
- Math.Max(value1.X, value2.X),
- Math.Max(value1.Y, value2.Y));
+ MathF.Max(value1.X, value2.X),
+ MathF.Max(value1.Y, value2.Y));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Min(Vector2 value1, Vector2 value2)
{
return new Vector2(
- Math.Min(value1.X, value2.X),
- Math.Min(value1.Y, value2.Y));
+ MathF.Min(value1.X, value2.X),
+ MathF.Min(value1.Y, value2.Y));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Multiply(Vector2 value1, Vector2 value2)
{
return new Vector2(value1.X * value2.X, value1.Y * value2.Y);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Multiply(Vector2 value1, float scaleFactor)
{
return new Vector2(value1.X * scaleFactor, value1.Y * scaleFactor);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Negate(Vector2 value)
{
return new Vector2(-value.X, -value.Y);
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Normalize(Vector2 value)
{
float factor = value.LengthSquared();
if (factor > 1e-6)
{
- factor = 1f / (float)Math.Sqrt(factor);
+ factor = 1f / MathF.Sqrt(factor);
return new Vector2(value.X * factor, value.Y * factor);
}
return new Vector2();
@@ -362,29 +393,117 @@ public static Vector2 Normalize(Vector2 value)
///
/// A string representation of a 2D vector, enclosed
/// in arrow brackets and separated by commas
- public static Vector2 Parse(string val)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector2 Parse(string val)
{
- char[] splitChar = { ',' };
- string[] split = val.Replace("<", String.Empty).Replace(">", String.Empty).Split(splitChar);
- return new Vector2(
- float.Parse(split[0].Trim(), Utils.EnUsCulture),
- float.Parse(split[1].Trim(), Utils.EnUsCulture));
+ return Parse(val.AsSpan());
+ }
+
+ public static Vector2 Parse(ReadOnlySpan sp)
+ {
+ if (sp.Length < 3)
+ throw new FormatException("Invalid Vector2");
+
+ int start = 0;
+ int comma = 0;
+ char c;
+
+ do
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ }
+ if (comma > sp.Length - 1)
+ throw new FormatException("Invalid Vector2");
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ throw new FormatException("Invalid Vector2");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == '>')
+ break;
+ }
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
+ throw new FormatException("Invalid Vector2");
+
+ return new Vector2(x, y);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryParse(string val, out Vector2 result)
{
- try
+ return TryParse(val.AsSpan(), out result);
+ }
+ public static bool TryParse(ReadOnlySpan sp, out Vector2 result)
+ {
+ if (sp.Length < 3)
{
- result = Parse(val);
- return true;
+ result = Zero;
+ return false;
}
- catch (Exception)
+
+ int start = 0;
+ int comma = 0;
+ char c;
+ do
{
- result = new Vector2();
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ }
+ if (comma > sp.Length - 1)
+ {
+ result = Zero;
return false;
}
- }
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ {
+ result = Zero;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ' ' || c == '>')
+ break;
+ }
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
+ {
+ result = Zero;
+ return false;
+ }
+
+ result = new Vector2(x, y);
+ return true;
+ }
///
/// Interpolates between two vectors using a cubic equation
///
@@ -395,7 +514,7 @@ public static Vector2 SmoothStep(Vector2 value1, Vector2 value2, float amount)
Utils.SmoothStep(value1.Y, value2.Y, amount));
}
- [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Subtract(Vector2 value1, Vector2 value2)
{
return new Vector2(value1.X - value2.X, value1.Y - value2.Y);
@@ -466,7 +585,13 @@ public override int GetHashCode()
/// A string representation of the vector
public override string ToString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}>", X, Y);
+ StringBuilder sb = new();
+ sb.Append('<');
+ sb.Append(X.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Y.ToString(Utils.EnUsCulture));
+ sb.Append('>');
+ return sb.ToString();
}
///
@@ -479,7 +604,12 @@ public string ToRawString()
CultureInfo enUs = new CultureInfo("en-us");
enUs.NumberFormat.NumberDecimalDigits = 3;
- return String.Format(enUs, "{0} {1}", X, Y);
+ StringBuilder sb = new();
+ sb.Append(X.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Y.ToString(enUs));
+ sb.Append(' ');
+ return sb.ToString();
}
#endregion Overrides
diff --git a/OpenMetaverse.Types/Vector3.cs b/OpenMetaverse.Types/Vector3.cs
index d9fa9d00..162ced45 100644
--- a/OpenMetaverse.Types/Vector3.cs
+++ b/OpenMetaverse.Types/Vector3.cs
@@ -25,9 +25,13 @@
*/
using System;
+using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using System.Globalization;
+using System.Runtime.Intrinsics.X86;
+using System.Runtime.Intrinsics;
+using System.Text;
+using System.Collections;
namespace OpenMetaverse
{
@@ -38,13 +42,13 @@ namespace OpenMetaverse
[StructLayout(LayoutKind.Sequential)]
public struct Vector3 : IComparable, IEquatable
{
- /// X value
+ /// x value
public float X;
/// Y value
public float Y;
/// Z value
public float Z;
-
+
#region Constructors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -149,19 +153,30 @@ public void Sub(Vector3 v)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clamp(float min, float max)
{
- X = Utils.Clamp(X, min, max);
- Y = Utils.Clamp(Y, min, max);
- Z = Utils.Clamp(Z, min, max);
+ if (X > max)
+ X = max;
+ else if (X < min)
+ X = min;
+
+ if (Y > max)
+ Y = max;
+ else if (Y < min)
+ Y = min;
+
+ if (Z > max)
+ Z = max;
+ else if (Z < min)
+ Z = min;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float Length()
+ public readonly float Length()
{
- return (float)Math.Sqrt(X * X + Y * Y + Z * Z);
+ return MathF.Sqrt(X * X + Y * Y + Z * Z);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float LengthSquared()
+ public readonly float LengthSquared()
{
return (X * X + Y * Y + Z * Z);
}
@@ -172,7 +187,7 @@ public void Normalize()
float factor = X * X + Y * Y + Z * Z;
if (factor > 1e-6f)
{
- factor = 1f / (float)Math.Sqrt(factor);
+ factor = 1f / MathF.Sqrt(factor);
X *= factor;
Y *= factor;
Z *= factor;
@@ -186,7 +201,7 @@ public void Normalize()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool ApproxEquals(Vector3 vec)
+ public readonly bool ApproxEquals(Vector3 vec)
{
return Utils.ApproxEqual(X, vec.X) &&
Utils.ApproxEqual(Y, vec.Y) &&
@@ -203,7 +218,7 @@ public bool ApproxEquals(Vector3 vec)
/// True if the magnitude of difference between the two vectors
/// is less than the given tolerance, otherwise false
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool ApproxEquals(Vector3 vec, float tolerance)
+ public readonly bool ApproxEquals(Vector3 vec, float tolerance)
{
return Utils.ApproxEqual(X, vec.X, tolerance) &&
Utils.ApproxEqual(Y, vec.Y, tolerance) &&
@@ -212,7 +227,7 @@ public bool ApproxEquals(Vector3 vec, float tolerance)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool ApproxZero()
+ public readonly bool ApproxZero()
{
if (!Utils.ApproxZero(X))
return false;
@@ -224,7 +239,7 @@ public bool ApproxZero()
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool ApproxZero(float tolerance)
+ public readonly bool ApproxZero(float tolerance)
{
if (!Utils.ApproxZero(X, tolerance))
return false;
@@ -236,7 +251,7 @@ public bool ApproxZero(float tolerance)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsZero()
+ public readonly bool IsZero()
{
if (X != 0)
return false;
@@ -247,26 +262,41 @@ public bool IsZero()
return true;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly bool IsNotZero()
+ {
+ if (X != 0)
+ return true;
+ if (Y != 0)
+ return true;
+ if (Z != 0)
+ return true;
+ return false;
+ }
+
///
/// IComparable.CompareTo implementation
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int CompareTo(Vector3 vector)
+ public readonly int CompareTo(Vector3 vector)
{
return LengthSquared().CompareTo(vector.LengthSquared());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public float Dot(Vector3 value2)
+ public readonly float Dot(Vector3 value2)
{
return (X * value2.X) + (Y * value2.Y) + (Z * value2.Z);
}
-
+ public readonly float AbsDot(Vector3 value2)
+ {
+ return MathF.Abs(X * value2.X) + MathF.Abs(Y * value2.Y) + MathF.Abs(Z * value2.Z);
+ }
///
/// Test if this vector is composed of all finite numbers
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsFinite()
+ public readonly bool IsFinite()
{
return (Utils.IsFinite(X) && Utils.IsFinite(Y) && Utils.IsFinite(Z));
}
@@ -276,12 +306,16 @@ public bool IsFinite()
///
/// Byte array containing a 12 byte vector
/// Beginning position in the byte array
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void FromBytes(byte[] byteArray)
+ {
+ this = Unsafe.ReadUnaligned(ref MemoryMarshal.GetArrayDataReference(byteArray));
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte[] byteArray, int pos)
{
- X = Utils.BytesToFloatSafepos(byteArray, pos);
- Y = Utils.BytesToFloatSafepos(byteArray, pos + 4);
- Z = Utils.BytesToFloatSafepos(byteArray, pos + 8);
+ this = Unsafe.ReadUnaligned(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(byteArray), pos));
}
///
@@ -289,12 +323,10 @@ public void FromBytes(byte[] byteArray, int pos)
///
/// A 12 byte array containing X, Y, and Z
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public byte[] GetBytes()
+ public readonly byte[] GetBytes()
{
byte[] dest = new byte[12];
- Utils.FloatToBytesSafepos(X, dest, 0);
- Utils.FloatToBytesSafepos(Y, dest, 4);
- Utils.FloatToBytesSafepos(Z, dest, 8);
+ Unsafe.WriteUnaligned(ref MemoryMarshal.GetArrayDataReference(dest), this);
return dest;
}
@@ -305,13 +337,274 @@ public byte[] GetBytes()
/// Position in the destination array to start
/// writing. Must be at least 12 bytes before the end of the array
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBytes(byte[] dest, int pos)
+ public readonly unsafe void ToBytes(byte[] dest, int pos)
{
- Utils.FloatToBytesSafepos(X, dest, pos);
- Utils.FloatToBytesSafepos(Y, dest, pos + 4);
- Utils.FloatToBytesSafepos(Z, dest, pos + 8);
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ *(Vector3*)(d + pos) = this;
+ }
+ else
+ {
+ Utils.FloatToBytesSafepos(X, dest, pos);
+ Utils.FloatToBytesSafepos(Y, dest, pos + 4);
+ Utils.FloatToBytesSafepos(Z, dest, pos + 8);
+ }
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ToBytes(byte* dest)
+ {
+ if (Utils.CanDirectCopyLE)
+ *(Vector3*)dest = this;
+ else
+ {
+ Utils.FloatToBytes(X, dest);
+ Utils.FloatToBytes(Y, dest + 4);
+ Utils.FloatToBytes(Z, dest + 8);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ClampedToShortsBytes(float range, byte[] dest, int pos)
+ {
+ float a, b;
+
+ a = MathF.Abs(X);
+ b = MathF.Abs(Y);
+ if (b > a)
+ a = b;
+ b = MathF.Abs(Z);
+ if (b > a)
+ a = b;
+
+ ushort sx, sy, sz;
+ if (a > range)
+ {
+ a = range / a;
+ sx = Utils.FloatToUInt16(X * a, range);
+ sy = Utils.FloatToUInt16(Y * a, range);
+ sz = Utils.FloatToUInt16(Z * a, range);
+ }
+ else
+ {
+ sx = Utils.FloatToUInt16(X, range);
+ sy = Utils.FloatToUInt16(Y, range);
+ sz = Utils.FloatToUInt16(Z, range);
+ }
+
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ {
+ *(ushort*)(d + pos) = sx;
+ *(ushort*)(d + pos + 2) = sy;
+ *(ushort*)(d + pos + 4) = sz;
+ }
+ }
+ else
+ {
+ Utils.UInt16ToBytes(sx, dest, pos);
+ Utils.UInt16ToBytes(sy, dest, pos + 2);
+ Utils.UInt16ToBytes(sz, dest, pos + 4);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ClampedToShortsBytes(float range, byte* dest, int pos)
+ {
+ float a, b;
+
+ a = MathF.Abs(X);
+ b = MathF.Abs(Y);
+ if (b > a)
+ a = b;
+ b = MathF.Abs(Z);
+ if (b > a)
+ a = b;
+
+ ushort sx, sy, sz;
+ if (a > range)
+ {
+ a = range / a;
+ sx = Utils.FloatToUInt16(X * a, range);
+ sy = Utils.FloatToUInt16(Y * a, range);
+ sz = Utils.FloatToUInt16(Z * a, range);
+ }
+ else
+ {
+ sx = Utils.FloatToUInt16(X, range);
+ sy = Utils.FloatToUInt16(Y, range);
+ sz = Utils.FloatToUInt16(Z, range);
+ }
+
+ if (Utils.CanDirectCopyLE)
+ {
+ *(ushort*)(dest + pos) = sx;
+ *(ushort*)(dest + pos + 2) = sy;
+ *(ushort*)(dest + pos + 4) = sz;
+ }
+ else
+ {
+ Utils.UInt16ToBytes(sx, dest, pos);
+ Utils.UInt16ToBytes(sy, dest, pos + 2);
+ Utils.UInt16ToBytes(sz, dest, pos + 4);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly unsafe void ClampedToShortsBytes(float range, byte* dest)
+ {
+ float a, b;
+
+ a = MathF.Abs(X);
+ b = MathF.Abs(Y);
+ if (b > a)
+ a = b;
+ b = MathF.Abs(Z);
+ if (b > a)
+ a = b;
+
+ ushort sx, sy, sc;
+ if (a > range)
+ {
+ a = range / a;
+ sx = Utils.FloatToUInt16(X * a, range);
+ sy = Utils.FloatToUInt16(Y * a, range);
+ sc = Utils.FloatToUInt16(Z * a, range);
+ }
+ else
+ {
+ sx = Utils.FloatToUInt16(X, range);
+ sy = Utils.FloatToUInt16(Y, range);
+ sc = Utils.FloatToUInt16(Z, range);
+ }
+
+ if (Utils.CanDirectCopyLE)
+ {
+ *(ushort*)(dest) = sx;
+ *(ushort*)(dest + 2) = sy;
+ *(ushort*)(dest + 4) = sc;
+ }
+ else
+ {
+ Utils.UInt16ToBytes(sx, dest);
+ Utils.UInt16ToBytes(sy, dest + 2);
+ Utils.UInt16ToBytes(sc, dest + 4);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Rotate(Quaternion rot)
+ {
+ float x2 = rot.X + rot.X;
+ float y2 = rot.Y + rot.Y;
+ float z2 = rot.Z + rot.Z;
+
+ float wx2 = rot.W * x2;
+ float wy2 = rot.W * y2;
+ float wz2 = rot.W * z2;
+ float xx2 = rot.X * x2;
+ float xy2 = rot.X * y2;
+ float xz2 = rot.X * z2;
+ float yy2 = rot.Y * y2;
+ float yz2 = rot.Y * z2;
+ float zz2 = rot.Z * z2;
+
+ x2 = X;
+ y2 = Y;
+ z2 = Z;
+
+ X = x2 * (1.0f - yy2 - zz2) + y2 * (xy2 - wz2) + z2 * (xz2 + wy2);
+ Y = x2 * (xy2 + wz2) + y2 * (1.0f - xx2 - zz2) + z2 * (yz2 - wx2);
+ Z = x2 * (xz2 - wy2) + y2 * (yz2 + wx2) + z2 * (1.0f - xx2 - yy2);
+ }
+
+ public void InverseRotate(Quaternion rot)
+ {
+ float x2 = rot.X + rot.X;
+ float y2 = rot.Y + rot.Y;
+ float z2 = rot.Z + rot.Z;
+
+ float wx2 = rot.W * x2;
+ float wy2 = rot.W * y2;
+ float wz2 = rot.W * z2;
+
+ float xx2 = rot.X * x2;
+ float xy2 = rot.X * y2;
+ float xz2 = rot.X * z2;
+ float yy2 = rot.Y * y2;
+ float yz2 = rot.Y * z2;
+ float zz2 = rot.Z * z2;
+
+ x2 = X;
+ y2 = Y;
+ z2 = Z;
+
+ X = x2 * (1.0f - yy2 - zz2) + y2 * (xy2 + wz2) + z2 * (xz2 - wy2);
+ Y = x2 * (xy2 - wz2) + y2 * (1.0f - xx2 - zz2) + z2 * (yz2 + wx2);
+ Z = x2 * (xz2 + wy2) + y2 * (yz2 - wx2) + z2 * (1.0f - xx2 - yy2);
+ }
+
+ //quaternion must be normalized <0,0,z,w>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void RotateByQZ(Quaternion rot)
+ {
+ float z2 = rot.Z + rot.Z;
+ float zz2 = 1.0f - rot.Z * z2;
+ float wz2 = rot.W * z2;
+
+ float ox = X;
+ float oy = Y;
+
+ X = ox * zz2 - oy * wz2;
+ Y = ox * wz2 + oy * zz2;
+ }
+
+ //quaternion must be normalized <0,0,z,w>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void InverseRotateByQZ(Quaternion rot)
+ {
+ float z2 = rot.Z + rot.Z;
+ float zz2 = 1.0f - rot.Z * z2;
+ float wz2 = rot.W * z2;
+
+ float ox = X;
+ float oy = Y;
+
+ X = ox * zz2 + oy * wz2;
+ Y = oy * zz2 - ox * wz2;
+ }
+
+ //shortQuaternion must be normalized
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void RotateByShortQZ(Vector2 shortQuaternion)
+ {
+ float z2 = shortQuaternion.X + shortQuaternion.X;
+ float zz2 = 1.0f - shortQuaternion.X * z2;
+ float wz2 = shortQuaternion.Y * z2;
+
+ float ox = X;
+ float oy = Y;
+
+ X = ox * zz2 - oy * wz2;
+ Y = ox * wz2 + oy * zz2;
+ }
+
+ //quaternion must be normalized <0,0,z,w>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void InverseRotateByShortQZ(Vector2 shortQuaternion)
+ {
+ float z2 = shortQuaternion.X + shortQuaternion.X;
+ float zz2 = 1.0f - shortQuaternion.X * z2;
+ float wz2 = shortQuaternion.Y * z2;
+
+ float ox = X;
+ float oy = Y;
+
+ X = ox * zz2 + oy * wz2;
+ Y = oy * zz2 - ox * wz2;
+ }
#endregion Public Methods
#region Static Methods
@@ -321,6 +614,12 @@ public static Vector3 Add(Vector3 value1, Vector3 value2)
return new Vector3(value1.X + value2.X, value1.Y + value2.Y, value1.Z + value2.Z);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 Abs(Vector3 value1)
+ {
+ return new Vector3(MathF.Abs(value1.X), MathF.Abs(value1.Y), MathF.Abs(value1.Z));
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Clamp(Vector3 value1, float min, float max)
{
@@ -348,6 +647,7 @@ public static Vector3 Cross(Vector3 value1, Vector3 value2)
value1.X * value2.Y - value2.X * value1.Y);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Distance(Vector3 value1, Vector3 value2)
{
return (float)Math.Sqrt(DistanceSquared(value1, value2));
@@ -382,6 +682,12 @@ public static float Dot(Vector3 value1, Vector3 value2)
return (value1.X * value2.X) + (value1.Y * value2.Y) + (value1.Z * value2.Z);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float AbsDot(Vector3 value1, Vector3 value2)
+ {
+ return MathF.Abs(value1.X * value2.X) + MathF.Abs(value1.Y * value2.Y) + MathF.Abs(value1.Z * value2.Z);
+ }
+
public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
{
return new Vector3(
@@ -438,7 +744,7 @@ public static Vector3 Normalize(Vector3 value)
float factor = value.LengthSquared();
if (factor > 1e-6f)
{
- factor = 1f / (float)Math.Sqrt(factor);
+ factor = 1f / MathF.Sqrt(factor);
return value * factor;
}
return new Vector3();
@@ -449,28 +755,150 @@ public static Vector3 Normalize(Vector3 value)
///
/// A string representation of a 3D vector, enclosed
/// in arrow brackets and separated by commas
- public static Vector3 Parse(string val)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector3 Parse(string val)
{
- char[] splitChar = { ',' };
- string[] split = val.Replace("<", String.Empty).Replace(">", String.Empty).Split(splitChar);
- return new Vector3(
- Single.Parse(split[0].Trim(), Utils.EnUsCulture),
- Single.Parse(split[1].Trim(), Utils.EnUsCulture),
- Single.Parse(split[2].Trim(), Utils.EnUsCulture));
+ return Parse(val.AsSpan());
}
+ public static Vector3 Parse(ReadOnlySpan sp)
+ {
+ if (sp.Length < 5)
+ throw new FormatException("Invalid Vector3");
+
+ int start = 0;
+ int comma = 0;
+ char c;
+
+ do
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ }
+
+ if (comma > sp.Length - 3)
+ throw new FormatException("Invalid Vector3");
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ throw new FormatException("Invalid Vector3");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 1)
+ throw new FormatException("Invalid Vector3");
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
+ throw new FormatException("Invalid Vector3");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ' ' || c == '>')
+ break;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float z))
+ throw new FormatException("Invalid Vector3");
+ return new Vector3(x, y, z);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryParse(string val, out Vector3 result)
{
- try
+ return TryParse(val.AsSpan(), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan sp, out Vector3 result)
+ {
+ if (sp.Length < 7)
{
- result = Parse(val);
- return true;
+ result = Zero;
+ return false;
+ }
+
+ int start = 0;
+ int comma = 0;
+ char c;
+ do
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (start > sp.Length - 6)
+ {
+ result = Zero;
+ return false;
+ }
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ {
+ result = Zero;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 3)
+ {
+ result = Zero;
+ return false;
}
- catch (Exception)
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
{
- result = Vector3.Zero;
+ result = Zero;
return false;
}
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ' ' || c == '>')
+ break;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float z))
+ {
+ result = Zero;
+ return false;
+ }
+
+ result = new Vector3(x, y, z);
+ return true;
}
///
@@ -480,16 +908,16 @@ public static bool TryParse(string val, out Vector3 result)
/// Normalized target vector
public static Quaternion RotationBetween(Vector3 a, Vector3 b)
{
- const double piOverfour = 0.25 * Math.PI;
- double magProduct = Math.Sqrt(a.LengthSquared() * b.LengthSquared());
- double angle;
+ const float piOverfour = 0.25f * MathF.PI;
+ float magProduct = MathF.Sqrt(a.LengthSquared() * b.LengthSquared());
+ float angle;
if(magProduct > 1e-6)
{
float dotProduct = Dot(a, b);
- if(dotProduct < 1e-6)
+ if(dotProduct < 1e-6f)
angle = piOverfour;
else
- angle = 0.5 * Math.Acos(dotProduct / magProduct);
+ angle = 0.5f * MathF.Acos(dotProduct / magProduct);
}
else
angle = piOverfour;
@@ -497,7 +925,7 @@ public static Quaternion RotationBetween(Vector3 a, Vector3 b)
Vector3 axis = Cross(a, b);
axis.Normalize();
- float s = (float)Math.Sin(angle);
+ float s = MathF.Sin(angle);
return new Quaternion(
axis.X * s,
axis.Y * s,
@@ -522,7 +950,52 @@ public static Vector3 Subtract(Vector3 value1, Vector3 value2)
{
return new Vector3(value1.X - value2.X, value1.Y - value2.Y, value1.Z - value2.Z);
}
+ /*
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static Vector3 SubtractS(Vector3 value1, Vector3 value2)
+ {
+ if (Sse2.IsSupported)
+ {
+ Vector128 ma = Sse2.LoadScalarVector128((double*)&value1.X).AsSingle();
+ ma = Sse2.Shuffle(ma, Sse2.LoadScalarVector128((float*)&value1.Z), 0x44);
+
+ Vector128 mb = Sse2.LoadScalarVector128((double*)&value2.X).AsSingle();
+ mb = Sse2.Shuffle(mb, Sse2.LoadScalarVector128((float*)&value2.Z), 0x44);
+
+ ma = Sse.Subtract(ma, mb);
+ Vector3 ret = new();
+ Sse2.StoreScalar((double*)&ret.X, ma.AsDouble());
+ Sse2.StoreScalar(&ret.Z, Sse2.Shuffle(ma.AsInt32(), 0x02).AsSingle());
+ return ret;
+ }
+ else
+ return Subtract(value1, value2);
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 AddS(Vector3 value1, Vector3 value2)
+ {
+ if (Sse2.IsSupported)
+ {
+ unsafe
+ {
+ Vector128 ma = Sse2.LoadScalarVector128((double*)&value1.X).AsSingle();
+ ma = Sse2.Shuffle(ma, Sse2.LoadScalarVector128(&value1.Z), 0x44);
+
+ Vector128 mb = Sse2.LoadScalarVector128((double*)&value2.X).AsSingle();
+ mb = Sse2.Shuffle(mb, Sse2.LoadScalarVector128(&value2.Z), 0x44);
+
+ ma = Sse.Add(ma, mb);
+ Vector3 ret = new();
+ Sse2.StoreScalar((double*)&ret.X, ma.AsDouble());
+ Sse2.StoreScalar(&ret.Z, Sse2.Shuffle(ma.AsInt32(), 0x02).AsSingle());
+ return ret;
+ }
+ }
+ else
+ return Subtract(value1, value2);
+ }
+ */
public static Vector3 Transform(Vector3 position, Matrix4 matrix)
{
return new Vector3(
@@ -541,6 +1014,12 @@ public static Vector3 TransformNormal(Vector3 position, Matrix4 matrix)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Transform(Vector3 vec, Quaternion rot)
+ {
+ return Rotate(vec, rot);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 Rotate(Vector3 vec, Quaternion rot)
{
float x2 = rot.X + rot.X;
float y2 = rot.Y + rot.Y;
@@ -566,16 +1045,147 @@ public static Vector3 Transform(Vector3 vec, Quaternion rot)
x2 * (xz2 - wy2) + y2 * (yz2 + wx2) + z2 * (1.0f - xx2 - yy2));
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 InverseRotate(Vector3 vec, Quaternion rot)
+ {
+ float x2 = rot.X + rot.X;
+ float y2 = rot.Y + rot.Y;
+ float z2 = rot.Z + rot.Z;
+
+ float wx2 = rot.W * x2;
+ float wy2 = rot.W * y2;
+ float wz2 = rot.W * z2;
+ float xx2 = rot.X * x2;
+ float xy2 = rot.X * y2;
+ float xz2 = rot.X * z2;
+ float yy2 = rot.Y * y2;
+ float yz2 = rot.Y * z2;
+ float zz2 = rot.Z * z2;
+
+ x2 = vec.X;
+ y2 = vec.Y;
+ z2 = vec.Z;
+
+ return new Vector3(
+ x2 * (1.0f - yy2 - zz2) + y2 * (xy2 + wz2) + z2 * (xz2 - wy2),
+ x2 * (xy2 - wz2) + y2 * (1.0f - xx2 - zz2) + z2 * (yz2 + wx2),
+ x2 * (xz2 + wy2) + y2 * (yz2 - wx2) + z2 * (1.0f - xx2 - yy2));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 UnitXRotated(Quaternion rot)
+ {
+ float y2 = rot.Y + rot.Y;
+ float z2 = rot.Z + rot.Z;
+
+ float wy2 = rot.W * y2;
+ float wz2 = rot.W * z2;
+ float xy2 = rot.X * y2;
+ float xz2 = rot.X * z2;
+ float yy2 = rot.Y * y2;
+ float zz2 = rot.Z * z2;
+
+ return new Vector3(1.0f - yy2 - zz2, xy2 + wz2, xz2 - wy2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 UnitYRotated(Quaternion rot)
+ {
+ float x2 = rot.X + rot.X;
+ float y2 = rot.Y + rot.Y;
+ float z2 = rot.Z + rot.Z;
+
+ float wx2 = rot.W * x2;
+ float wz2 = rot.W * z2;
+ float xx2 = rot.X * x2;
+ float xy2 = rot.X * y2;
+ float yz2 = rot.Y * z2;
+ float zz2 = rot.Z * z2;
+
+ return new Vector3(xy2 - wz2, 1.0f - xx2 - zz2, yz2 + wx2);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 UnitZRotated(Quaternion rot)
+ {
+ float x2 = rot.X + rot.X;
+ float y2 = rot.Y + rot.Y;
+ float z2 = rot.Z + rot.Z;
+
+ float wx2 = rot.W * x2;
+ float wy2 = rot.W * y2;
+ float xx2 = rot.X * x2;
+ float xz2 = rot.X * z2;
+ float yy2 = rot.Y * y2;
+ float yz2 = rot.Y * z2;
+
+ return new Vector3(xz2 + wy2, yz2 - wx2, 1.0f - xx2 - yy2);
+ }
+
+ //quaternion must be normalized <0,0,z,w>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 RotateByQZ(Vector3 vec, Quaternion rot)
+ {
+ float z2 = rot.Z + rot.Z;
+ float wz2 = rot.W * z2;
+ float zz2 = 1.0f - rot.Z * z2;
+
+ return new Vector3(
+ vec.X * zz2 - vec.Y * wz2,
+ vec.X * wz2 + vec.Y * zz2,
+ vec.Z);;
+ }
+
+ //quaternion must be normalized <0,0,z,w>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 InverseRotateByQZ(Vector3 vec, Quaternion rot)
+ {
+ float z2 = rot.Z + rot.Z;
+ float wz2 = rot.W * z2;
+ float zz2 = 1.0f - rot.Z * z2;
+
+ return new Vector3(
+ vec.X * zz2 + vec.Y * wz2,
+ vec.Y * zz2 - vec.X * wz2,
+ vec.Z);
+ }
+
+ //shortQuaternion must be normalized
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 RotateByShortQZ(Vector3 vec, Vector2 shortQuaternion)
+ {
+ float z2 = shortQuaternion.X + shortQuaternion.X;
+ float zz2 = 1.0f - shortQuaternion.X * z2;
+ float wz2 = shortQuaternion.Y * z2;
+
+ return new Vector3(
+ vec.X * zz2 - vec.Y * wz2,
+ vec.X * wz2 + vec.Y * zz2,
+ vec.Z); ;
+ }
+
+ //shortQuaternion must be normalized
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector3 InverseRotateByShortQZ(Vector3 vec, Vector2 shortQuaternion)
+ {
+ float z2 = shortQuaternion.X + shortQuaternion.X;
+ float zz2 = 1.0f - shortQuaternion.X * z2;
+ float wz2 = shortQuaternion.Y * z2;
+
+ return new Vector3(
+ vec.X * zz2 + vec.Y * wz2,
+ vec.Y * zz2 - vec.X * wz2,
+ vec.Z);
+ }
#endregion Static Methods
#region Overrides
- public override bool Equals(object obj)
+ public readonly override bool Equals(object obj)
{
- if (!(obj is Vector3))
+ if (obj is not Vector3 other)
return false;
- Vector3 other = (Vector3)obj;
if (X != other.X)
return false;
if (Y != other.Y)
@@ -586,7 +1196,7 @@ public override bool Equals(object obj)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Vector3 other)
+ public readonly bool Equals(Vector3 other)
{
if (X != other.X)
return false;
@@ -598,7 +1208,7 @@ public bool Equals(Vector3 other)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool NotEqual(Vector3 other)
+ public readonly bool NotEqual(Vector3 other)
{
if (X != other.X)
return true;
@@ -610,7 +1220,7 @@ public bool NotEqual(Vector3 other)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode()
+ public readonly override int GetHashCode()
{
int hash = X.GetHashCode();
hash = Utils.CombineHash(hash, Y.GetHashCode());
@@ -622,9 +1232,17 @@ public override int GetHashCode()
/// Get a formatted string representation of the vector
///
/// A string representation of the vector
- public override string ToString()
+ public readonly override string ToString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}, {2}>", X, Y, Z);
+ StringBuilder sb = new();
+ sb.Append('<');
+ sb.Append(X.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Y.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Z.ToString(Utils.EnUsCulture));
+ sb.Append('>');
+ return sb.ToString();
}
///
@@ -632,12 +1250,18 @@ public override string ToString()
/// decimal digits and separated by spaces only
///
/// Raw string representation of the vector
- public string ToRawString()
+ public readonly string ToRawString()
{
CultureInfo enUs = new CultureInfo("en-us");
enUs.NumberFormat.NumberDecimalDigits = 3;
- return String.Format(enUs, "{0} {1} {2}", X, Y, Z);
+ StringBuilder sb = new();
+ sb.Append(X.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Y.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Z.ToString(enUs));
+ return sb.ToString();
}
#endregion Overrides
@@ -768,16 +1392,16 @@ public static explicit operator Vector3(Vector3d value)
#endregion Operators
/// A vector with a value of 0,0,0
- public readonly static Vector3 Zero = new Vector3();
+ public readonly static Vector3 Zero = new();
/// A vector with a value of 1,1,1
- public readonly static Vector3 One = new Vector3(1f);
+ public readonly static Vector3 One = new(1f);
/// A unit vector facing forward (X axis), value 1,0,0
- public readonly static Vector3 UnitX = new Vector3(1f, 0f, 0f);
+ public readonly static Vector3 UnitX = new(1f, 0f, 0f);
/// A unit vector facing left (Y axis), value 0,1,0
- public readonly static Vector3 UnitY = new Vector3(0f, 1f, 0f);
+ public readonly static Vector3 UnitY = new(0f, 1f, 0f);
/// A unit vector facing up (Z axis), value 0,0,1
- public readonly static Vector3 UnitZ = new Vector3(0f, 0f, 1f);
- public readonly static Vector3 MinValue = new Vector3(float.MinValue, float.MinValue, float.MinValue);
- public readonly static Vector3 MaxValue = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
+ public readonly static Vector3 UnitZ = new(0f, 0f, 1f);
+ public readonly static Vector3 MinValue = new(float.MinValue, float.MinValue, float.MinValue);
+ public readonly static Vector3 MaxValue = new(float.MaxValue, float.MaxValue, float.MaxValue);
}
}
diff --git a/OpenMetaverse.Types/Vector3d.cs b/OpenMetaverse.Types/Vector3d.cs
index 50bd368e..96c63141 100644
--- a/OpenMetaverse.Types/Vector3d.cs
+++ b/OpenMetaverse.Types/Vector3d.cs
@@ -27,6 +27,8 @@
using System;
using System.Runtime.InteropServices;
using System.Globalization;
+using System.Text;
+using System.Runtime.CompilerServices;
namespace OpenMetaverse
{
@@ -308,28 +310,163 @@ public static Vector3d Normalize(Vector3d value)
///
/// A string representation of a 3D vector, enclosed
/// in arrow brackets and separated by commas
- public static Vector3d Parse(string val)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector3d Parse(string val)
{
- char[] splitChar = { ',' };
- string[] split = val.Replace("<", String.Empty).Replace(">", String.Empty).Split(splitChar);
- return new Vector3d(
- Double.Parse(split[0].Trim(), Utils.EnUsCulture),
- Double.Parse(split[1].Trim(), Utils.EnUsCulture),
- Double.Parse(split[2].Trim(), Utils.EnUsCulture));
+ return Parse(val.AsSpan());
}
- public static bool TryParse(string val, out Vector3d result)
+ public static unsafe Vector3d Parse(ReadOnlySpan sp)
{
- try
+ if (sp.Length < 7)
+ throw new FormatException("Invalid Vector3");
+
+ int start = 0;
+ fixed (char* p = sp)
{
- result = Parse(val);
- return true;
+ while (start < sp.Length)
+ {
+ if (p[start++] == '<')
+ break;
+ }
+ if (start > sp.Length - 6)
+ throw new FormatException("Invalid Vector3");
+
+ int comma1 = start + 1;
+ while (comma1 < sp.Length)
+ {
+ if (p[comma1] == ',')
+ break;
+ comma1++;
+ }
+ if (comma1 > sp.Length - 5)
+ throw new FormatException("Invalid Vector3");
+
+ if (!double.TryParse(sp[start..comma1], NumberStyles.Float, Utils.EnUsCulture, out double x))
+ throw new FormatException("Invalid Vector3");
+
+ comma1++;
+ start = comma1;
+ comma1++;
+ while (comma1 < sp.Length)
+ {
+ if (p[comma1] == ',')
+ break;
+ comma1++;
+ }
+ if (comma1 > sp.Length - 3)
+ throw new FormatException("Invalid Vector3");
+ if (!double.TryParse(sp[start..comma1], NumberStyles.Float, Utils.EnUsCulture, out double y))
+ throw new FormatException("Invalid Vector3");
+
+ comma1++;
+ start = comma1;
+ comma1++;
+ while (comma1 < sp.Length)
+ {
+ if (p[comma1] == '>')
+ break;
+ comma1++;
+ }
+ if (comma1 >= sp.Length)
+ throw new FormatException("Invalid Vector3");
+
+ if (!double.TryParse(sp[start..comma1], NumberStyles.Float, Utils.EnUsCulture, out double z))
+ throw new FormatException("Invalid Vector3");
+ return new Vector3d(x, y, z);
}
- catch (Exception)
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static bool TryParse(string val, out Vector3d result)
+ {
+ return TryParse(val.AsSpan(), out result);
+ }
+
+ public unsafe static bool TryParse(ReadOnlySpan sp, out Vector3d result)
+ {
+ if (sp.Length < 7)
{
- result = Vector3d.Zero;
+ result = Zero;
return false;
}
+
+ int start = 0;
+ fixed (char* p = sp)
+ {
+ while (start < sp.Length)
+ {
+ if (p[start++] == '<')
+ break;
+ }
+ if (start > sp.Length - 6)
+ {
+ result = Zero;
+ return false;
+ }
+
+ int comma1 = start + 1;
+ while (comma1 < sp.Length)
+ {
+ if (p[comma1] == ',')
+ break;
+ comma1++;
+ }
+ if (comma1 > sp.Length - 5)
+ {
+ result = Zero;
+ return false;
+ }
+
+ if (!double.TryParse(sp[start..comma1], NumberStyles.Float, Utils.EnUsCulture, out double x))
+ {
+ result = Zero;
+ return false;
+ }
+
+ comma1++;
+ start = comma1;
+ comma1++;
+ while (comma1 < sp.Length)
+ {
+ if (p[comma1] == ',')
+ break;
+ comma1++;
+ }
+ if (comma1 > sp.Length - 3)
+ {
+ result = Zero;
+ return false;
+ }
+ if (!double.TryParse(sp[start..comma1], NumberStyles.Float, Utils.EnUsCulture, out double y))
+ {
+ result = Zero;
+ return false;
+ }
+
+ comma1++;
+ start = comma1;
+ comma1++;
+ while (comma1 < sp.Length)
+ {
+ if (p[comma1] == '>')
+ break;
+ comma1++;
+ }
+ if (comma1 >= sp.Length)
+ {
+ result = Zero;
+ return false;
+ }
+
+ if (!double.TryParse(sp[start..comma1], NumberStyles.Float, Utils.EnUsCulture, out double z))
+ {
+ result = Zero;
+ return false;
+ }
+ result = new Vector3d(x, y, z);
+ return true;
+ }
}
///
@@ -376,7 +513,15 @@ public override int GetHashCode()
/// A string representation of the vector
public override string ToString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}, {2}>", X, Y, Z);
+ StringBuilder sb = new();
+ sb.Append('<');
+ sb.Append(X.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Y.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Z.ToString(Utils.EnUsCulture));
+ sb.Append('>');
+ return sb.ToString();
}
///
@@ -386,10 +531,16 @@ public override string ToString()
/// Raw string representation of the vector
public string ToRawString()
{
- CultureInfo enUs = new CultureInfo("en-us");
+ CultureInfo enUs = new("en-us");
enUs.NumberFormat.NumberDecimalDigits = 3;
- return String.Format(enUs, "{0} {1} {2}", X, Y, Z);
+ StringBuilder sb = new();
+ sb.Append(X.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Y.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Z.ToString(enUs));
+ return sb.ToString();
}
#endregion Overrides
diff --git a/OpenMetaverse.Types/Vector4.cs b/OpenMetaverse.Types/Vector4.cs
index 2aad0146..fe5a3210 100644
--- a/OpenMetaverse.Types/Vector4.cs
+++ b/OpenMetaverse.Types/Vector4.cs
@@ -28,6 +28,7 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Text;
namespace OpenMetaverse
{
@@ -93,10 +94,7 @@ public Vector4(byte[] byteArray, int pos)
public Vector4(Vector4 value)
{
- X = value.X;
- Y = value.Y;
- Z = value.Z;
- W = value.W;
+ this = value;
}
#endregion Constructors
@@ -132,11 +130,19 @@ public void Sub(Vector4 v)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clamp(float min, float max)
{
- X = Utils.Clamp(X, min, max);
- Y = Utils.Clamp(Y, min, max);
- Z = Utils.Clamp(Z, min, max);
- W = Utils.Clamp(W, min, max);
+ if (X < min) X = min;
+ else if (X > max) X = max;
+
+ if (Y < min) Y = min;
+ else if (Y > max) Y = max;
+
+ if (Z < min) Z = min;
+ else if (Z > max) Z = max;
+
+ if (W < min) W = min;
+ else if (W > max) W = max;
}
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Min(Vector4 v)
{
@@ -222,6 +228,20 @@ public bool IsZero()
return false;
return true;
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsNotZero()
+ {
+ if (X != 0)
+ return true;
+ if (Y != 0)
+ return true;
+ if (Z != 0)
+ return true;
+ if (W != 0)
+ return true;
+ return false;
+ }
///
/// IComparable.CompareTo implementation
///
@@ -276,12 +296,35 @@ public byte[] GetBytes()
/// Destination byte array
/// Position in the destination array to start
/// writing. Must be at least 16 bytes before the end of the array
- public void ToBytes(byte[] dest, int pos)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe void ToBytes(byte[] dest, int pos)
{
- Utils.FloatToBytesSafepos(X, dest, pos);
- Utils.FloatToBytesSafepos(Y, dest, pos + 4);
- Utils.FloatToBytesSafepos(Z, dest, pos + 8);
- Utils.FloatToBytesSafepos(W, dest, pos + 12);
+ if (Utils.CanDirectCopyLE)
+ {
+ fixed (byte* d = &dest[0])
+ *(Vector4*)(d + pos) = this;
+ }
+ else
+ {
+ Utils.FloatToBytesSafepos(X, dest, pos);
+ Utils.FloatToBytesSafepos(Y, dest, pos + 4);
+ Utils.FloatToBytesSafepos(Z, dest, pos + 8);
+ Utils.FloatToBytesSafepos(W, dest, pos + 12);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe void ToBytes(byte* dest)
+ {
+ if (Utils.CanDirectCopyLE)
+ *(Vector4*)dest = this;
+ else
+ {
+ Utils.FloatToBytes(X, dest);
+ Utils.FloatToBytes(Y, dest + 4);
+ Utils.FloatToBytes(Z, dest + 8);
+ Utils.FloatToBytes(W, dest + 12);
+ }
}
#endregion Public Methods
@@ -470,29 +513,172 @@ public static Vector4 Transform(Vector4 vector, Matrix4 matrix)
(vector.X * matrix.M14) + (vector.Y * matrix.M24) + (vector.Z * matrix.M34) + (vector.W * matrix.M44));
}
- public static Vector4 Parse(string val)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe static Vector4 Parse(string val)
{
- char[] splitChar = { ',' };
- string[] split = val.Replace("<", String.Empty).Replace(">", String.Empty).Split(splitChar);
- return new Vector4(
- float.Parse(split[0].Trim(), Utils.EnUsCulture),
- float.Parse(split[1].Trim(), Utils.EnUsCulture),
- float.Parse(split[2].Trim(), Utils.EnUsCulture),
- float.Parse(split[3].Trim(), Utils.EnUsCulture));
+ return Parse(val.AsSpan());
}
+ public static Vector4 Parse(ReadOnlySpan sp)
+ {
+ if (sp.Length < 7)
+ throw new FormatException("Invalid Vector4");
+
+ int start = 0;
+ int comma = 0;
+ char c;
+
+ do
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ }
+ if (comma > sp.Length - 5)
+ throw new FormatException("Invalid Vector4");
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ throw new FormatException("Invalid Vector4");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 3)
+ throw new FormatException("Invalid Vector4");
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
+ throw new FormatException("Invalid Vector4");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 1)
+ throw new FormatException("Invalid Vector4");
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float z))
+ throw new FormatException("Invalid Vector4");
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == '>')
+ break;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float w))
+ throw new FormatException("Invalid Vector4");
+ return new Vector4(x, y, z, w);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryParse(string val, out Vector4 result)
{
- try
+ return TryParse(val.AsSpan(), out result);
+ }
+
+ public static bool TryParse(ReadOnlySpan sp, out Vector4 result)
+ {
+ if (sp.Length < 7)
{
- result = Parse(val);
- return true;
+ result = Zero;
+ return false;
+ }
+ int start = 0;
+ int comma = 0;
+ char c;
+ do
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if (c == ',' || c == '<')
+ break;
+ }
+ while (++comma < sp.Length);
+
+ if (c == '<')
+ {
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ }
+ if (comma > sp.Length - 5)
+ {
+ result = Zero;
+ return false;
+ }
+
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float x))
+ {
+ result = Zero;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 5)
+ {
+ result = Zero;
+ return false;
+ }
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float y))
+ {
+ result = Zero;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ if (Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma) == ',')
+ break;
+ }
+ if (comma > sp.Length - 1)
+ {
+ result = Zero;
+ return false;
+ }
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float z))
+ {
+ result = Zero;
+ return false;
+ }
+
+ start = ++comma;
+ while (++comma < sp.Length)
+ {
+ c = Unsafe.Add(ref MemoryMarshal.GetReference(sp), comma);
+ if(c == ' ' || c == '>')
+ break;
}
- catch (Exception)
+ if (!float.TryParse(sp[start..comma], NumberStyles.Float, Utils.EnUsCulture, out float w))
{
- result = new Vector4();
+ result = Zero;
return false;
}
+
+ result = new Vector4(x, y, z, w);
+ return true;
}
#endregion Static Methods
@@ -501,10 +687,9 @@ public static bool TryParse(string val, out Vector4 result)
public override bool Equals(object obj)
{
- if (!(obj is Vector4))
+ if (obj is not Vector4 other)
return false;
- Vector4 other = (Vector4)obj;
if (X != other.X)
return false;
if (Y != other.Y)
@@ -549,7 +734,17 @@ public override int GetHashCode()
public override string ToString()
{
- return String.Format(Utils.EnUsCulture, "<{0}, {1}, {2}, {3}>", X, Y, Z, W);
+ StringBuilder sb = new();
+ sb.Append('<');
+ sb.Append(X.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Y.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(Z.ToString(Utils.EnUsCulture));
+ sb.Append(", ");
+ sb.Append(W.ToString(Utils.EnUsCulture));
+ sb.Append('>');
+ return sb.ToString();
}
///
@@ -559,10 +754,18 @@ public override string ToString()
/// Raw string representation of the vector
public string ToRawString()
{
- CultureInfo enUs = new CultureInfo("en-us");
+ CultureInfo enUs = new("en-us");
enUs.NumberFormat.NumberDecimalDigits = 3;
- return String.Format(enUs, "{0} {1} {2} {3}", X, Y, Z, W);
+ StringBuilder sb = new();
+ sb.Append(X.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Y.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(Z.ToString(enUs));
+ sb.Append(' ');
+ sb.Append(W.ToString(enUs));
+ return sb.ToString();
}
#endregion Overrides
@@ -658,18 +861,18 @@ public string ToRawString()
#endregion Operators
/// A vector with a value of 0,0,0,0
- public readonly static Vector4 Zero = new Vector4();
+ public readonly static Vector4 Zero = new();
/// A vector with a value of 1,1,1,1
- public readonly static Vector4 One = new Vector4(1f, 1f, 1f, 1f);
+ public readonly static Vector4 One = new(1f, 1f, 1f, 1f);
/// A vector with a value of 1,0,0,0
- public readonly static Vector4 UnitX = new Vector4(1f, 0f, 0f, 0f);
+ public readonly static Vector4 UnitX = new(1f, 0f, 0f, 0f);
/// A vector with a value of 0,1,0,0
- public readonly static Vector4 UnitY = new Vector4(0f, 1f, 0f, 0f);
+ public readonly static Vector4 UnitY = new(0f, 1f, 0f, 0f);
/// A vector with a value of 0,0,1,0
- public readonly static Vector4 UnitZ = new Vector4(0f, 0f, 1f, 0f);
+ public readonly static Vector4 UnitZ = new(0f, 0f, 1f, 0f);
/// A vector with a value of 0,0,0,1
- public readonly static Vector4 UnitW = new Vector4(0f, 0f, 0f, 1f);
- public readonly static Vector4 MinValue = new Vector4(float.MinValue, float.MinValue, float.MinValue, float.MinValue);
- public readonly static Vector4 MaxValue = new Vector4(float.MaxValue, float.MaxValue, float.MaxValue, float.MaxValue);
+ public readonly static Vector4 UnitW = new(0f, 0f, 0f, 1f);
+ public readonly static Vector4 MinValue = new(float.MinValue, float.MinValue, float.MinValue, float.MinValue);
+ public readonly static Vector4 MaxValue = new(float.MaxValue, float.MaxValue, float.MaxValue, float.MaxValue);
}
}
diff --git a/OpenMetaverse.Utilities/OpenMetaverse.Utilities.csproj b/OpenMetaverse.Utilities/OpenMetaverse.Utilities.csproj
index 43ec7dea..20893c6f 100644
--- a/OpenMetaverse.Utilities/OpenMetaverse.Utilities.csproj
+++ b/OpenMetaverse.Utilities/OpenMetaverse.Utilities.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
OpenMetaverse.Utilities
OpenMetaverse.Utilities
1591,1574,0419,0618
diff --git a/OpenMetaverse.sln b/OpenMetaverse.sln
index 03e57126..8157aa16 100644
--- a/OpenMetaverse.sln
+++ b/OpenMetaverse.sln
@@ -61,6 +61,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenMetaverse.PrimMesher",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{49AFD80D-D399-43FC-A9EE-9F15BC6D49E7}"
ProjectSection(SolutionItems) = preProject
+ Directory.Build.props = Directory.Build.props
README.md = README.md
EndProjectSection
EndProject
diff --git a/OpenMetaverse/BitPack.cs b/OpenMetaverse/BitPack.cs
index f1dd02f3..471a73ea 100644
--- a/OpenMetaverse/BitPack.cs
+++ b/OpenMetaverse/BitPack.cs
@@ -69,18 +69,17 @@ public BitPack(byte[] data, int pos, int? bitp = null)
{
Data = data;
bytePos = pos;
-
- if(bitp.HasValue)
+ if (bitp.HasValue)
{
bitPos = bitp.Value;
- if(bitPos < 0)
+ if (bitPos < 0)
bitPos = 0;
- else if(bitPos > 7)
+ else if (bitPos > 7)
bitPos = 7; // this is wrong anyway
if (bitPos == 0)
Data[pos] = 0;
else
- Data[pos] &= (byte)~(0xff >> bitPos);
+ Data[pos] &= (byte)~(0xff >> bitPos);
}
else
{
@@ -88,10 +87,30 @@ public BitPack(byte[] data, int pos, int? bitp = null)
}
}
+ public void Reset(byte[] data, int pos, int? bitp = null)
+ {
+ Data = data;
+ bytePos = pos;
+ if (bitp.HasValue)
+ {
+ bitPos = bitp.Value;
+ if (bitPos < 0)
+ bitPos = 0;
+ else if (bitPos > 7)
+ bitPos = 7; // this is wrong anyway
+ if (bitPos == 0)
+ Data[pos] = 0;
+ else
+ Data[pos] &= (byte)~(0xff >> bitPos);
+ }
+ else
+ bitPos = 0;
+ }
///
/// Pack a floating point value in to the data
///
/// Floating point value to pack
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public unsafe void PackFloat(float data)
{
int d = (*(int*)&data);
@@ -106,16 +125,10 @@ public unsafe void PackFloat(float data)
///
/// Integer containing the data to pack
/// Number of bits of the integer to pack
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void PackBits(int data, int totalCount)
{
- while (totalCount > 8)
- {
- PackBitsFromByte((byte)data);
- data >>= 8;
- totalCount -= 8;
- }
- if (totalCount > 0)
- PackBitsFromByte((byte)data, totalCount);
+ PackBits((uint)data, totalCount);
}
///
@@ -123,6 +136,7 @@ public void PackBits(int data, int totalCount)
///
/// Unsigned integer containing the data to pack
/// Number of bits of the integer to pack
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void PackBits(uint data, int totalCount)
{
while (totalCount > 8)
@@ -135,6 +149,7 @@ public void PackBits(uint data, int totalCount)
PackBitsFromByte((byte)data, totalCount);
}
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public void PackBitsFromUInt(uint data)
{
PackBitsFromByte((byte)data);
@@ -143,6 +158,24 @@ public void PackBitsFromUInt(uint data)
PackBitsFromByte((byte)(data >> 24));
}
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ public void PackBitsFromInt(int data)
+ {
+ PackBitsFromUInt((uint)data);
+ }
+
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ public void PackBitsFromUShort(ushort data)
+ {
+ PackBitsFromByte((byte)data);
+ PackBitsFromByte((byte)(data >> 8));
+ }
+
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ public void PackBitsFromShort(short data)
+ {
+ PackBitsFromUShort((ushort) data);
+ }
///
///
@@ -195,9 +228,50 @@ public void PackFixed(float data, bool isSigned, int intBits, int fracBits)
///
public void PackUUID(UUID data)
{
- byte[] bytes = data.GetBytes();
- for (int i = 0; i < 16; i++)
- PackBitsFromByte(bytes[i]);
+ if (BitConverter.IsLittleEndian)
+ {
+ PackBitsFromByte(data.bytea3);
+ PackBitsFromByte(data.bytea2);
+ PackBitsFromByte(data.bytea1);
+ PackBitsFromByte(data.bytea0);
+
+ PackBitsFromByte(data.byteb1);
+ PackBitsFromByte(data.byteb0);
+
+ PackBitsFromByte(data.bytec1);
+ PackBitsFromByte(data.bytec0);
+
+ PackBitsFromByte(data.d);
+ PackBitsFromByte(data.e);
+ PackBitsFromByte(data.f);
+ PackBitsFromByte(data.g);
+ PackBitsFromByte(data.h);
+ PackBitsFromByte(data.i);
+ PackBitsFromByte(data.j);
+ PackBitsFromByte(data.k);
+ }
+ else
+ {
+ PackBitsFromByte(data.bytea0);
+ PackBitsFromByte(data.bytea1);
+ PackBitsFromByte(data.bytea2);
+ PackBitsFromByte(data.bytea3);
+
+ PackBitsFromByte(data.byteb0);
+ PackBitsFromByte(data.byteb1);
+
+ PackBitsFromByte(data.bytec0);
+ PackBitsFromByte(data.bytec1);
+
+ PackBitsFromByte(data.k);
+ PackBitsFromByte(data.j);
+ PackBitsFromByte(data.i);
+ PackBitsFromByte(data.h);
+ PackBitsFromByte(data.g);
+ PackBitsFromByte(data.f);
+ PackBitsFromByte(data.e);
+ PackBitsFromByte(data.d);
+ }
}
///
@@ -206,10 +280,10 @@ public void PackUUID(UUID data)
///
public void PackColor(Color4 data)
{
- PackBitsFromByte(Utils.FloatToByte(data.R, 0f, 1f));
- PackBitsFromByte(Utils.FloatToByte(data.G, 0f, 1f));
- PackBitsFromByte(Utils.FloatToByte(data.B, 0f, 1f));
- PackBitsFromByte(Utils.FloatToByte(data.A, 0f, 1f));
+ PackBitsFromByte(Utils.FloatZeroOneToByte(data.R));
+ PackBitsFromByte(Utils.FloatZeroOneToByte(data.G));
+ PackBitsFromByte(Utils.FloatZeroOneToByte(data.B));
+ PackBitsFromByte(Utils.FloatZeroOneToByte(data.A));
}
///
@@ -292,7 +366,6 @@ public uint UnpackUInt()
tmp |= (byte)(UnpackByte() << 24);
return tmp;
}
-
public byte UnpackByte()
{
byte o = Data[bytePos];
@@ -344,7 +417,6 @@ public string UnpackString(int size)
bytePos += size;
return str;
}
-
public UUID UnpackUUID()
{
if (bitPos != 0) throw new IndexOutOfRangeException();
@@ -393,7 +465,7 @@ public void PackBitsFromByte(byte inbyte, int count)
if (count > 8) //should not happen
count = 7;
else
- count = count - 1;
+ --count;
while (count >= 0)
{
diff --git a/OpenMetaverse/Capabilities/CapsBase.cs b/OpenMetaverse/Capabilities/CapsBase.cs
index 28b39664..8db97c2a 100644
--- a/OpenMetaverse/Capabilities/CapsBase.cs
+++ b/OpenMetaverse/Capabilities/CapsBase.cs
@@ -38,10 +38,28 @@ public static class CapsBase
public delegate void OpenWriteEventHandler(HttpWebRequest request);
public delegate void DownloadProgressEventHandler(HttpWebRequest request, HttpWebResponse response, int bytesReceived, int totalBytesToReceive);
public delegate void RequestCompletedEventHandler(HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error);
+ public static bool ValidateServerCertificate(
+ object sender,
+ X509Certificate certificate,
+ X509Chain chain,
+ SslPolicyErrors sslPolicyErrors)
+ {
+ //if (m_NoVerifyCertChain)
+ sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
+
+ //if (m_NoVerifyCertHostname)
+ sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
+
+ if (sslPolicyErrors == SslPolicyErrors.None)
+ return true;
+
+ return false;
+ }
static CapsBase()
{
- ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
+ // Even though this will compile on Mono 2.4, it throws a runtime exception
+ ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
}
private class RequestState
diff --git a/OpenMetaverse/DllmapConfigHelper.cs b/OpenMetaverse/DllmapConfigHelper.cs
new file mode 100644
index 00000000..6dd01f91
--- /dev/null
+++ b/OpenMetaverse/DllmapConfigHelper.cs
@@ -0,0 +1,387 @@
+/*
+ * 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 OpenSimulator 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.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics.X86;
+using System.Xml.Serialization;
+using System.Xml;
+
+namespace OpenMetaverse
+{
+ public static class DllmapConfigHelper
+ {
+ [XmlRoot("dllmap")]
+ public class dllmap
+ {
+ [XmlAttribute("os")]
+ public string os;
+ [XmlAttribute("cpu")]
+ public string cpu;
+ [XmlAttribute("target")]
+ public string target;
+ [XmlAttribute("dll")]
+ public string dll;
+ }
+
+ [XmlRoot("configuration")]
+ public class configuration
+ {
+ [XmlElement("dllmap")]
+ public List maps = new();
+ }
+
+ private static readonly Dictionary LoadedLibs = new();
+ private static readonly HashSet RegisteredAssemblies = new();
+ private static readonly object m_mainlock = new object();
+
+ public static void RegisterAssembly(Assembly assembly)
+ {
+ lock (m_mainlock)
+ {
+ if (RegisteredAssemblies.Contains(assembly))
+ return;
+ RegisteredAssemblies.Add(assembly);
+ }
+
+ string assemblyPath = Path.GetDirectoryName(assembly.Location);
+ string path = Path.Combine(assemblyPath,
+ Path.GetFileNameWithoutExtension(assembly.Location) + ".dll.config");
+ configuration c = ParseConfig(path);
+ if (c is null)
+ return;
+
+ int matchs = ProcessAssemblyConfiguration(c, out List<(string libname, string libpath)> libstoload);
+ if (matchs == 0)
+ return;
+ if (libstoload.Count == 0)
+ return;
+
+ foreach (var (libname, libpath) in libstoload)
+ {
+ path= Path.Combine(assemblyPath, libpath);
+ if (NativeLibrary.TryLoad(path, out IntPtr ptr))
+ LoadedLibs.Add(libname, ptr);
+ else
+ LoadedLibs.Add(libname, IntPtr.Zero);
+ }
+ NativeLibrary.SetDllImportResolver(assembly, AssemblyDllImport);
+ }
+ private static IntPtr AssemblyDllImport(string libraryName, Assembly assembly, DllImportSearchPath? dllImportSearchPath)
+ {
+ if (LoadedLibs.TryGetValue(libraryName, out IntPtr ptr))
+ return ptr;
+ return IntPtr.Zero;
+ }
+
+ public static configuration ParseConfig(string path)
+ {
+ if (string.IsNullOrWhiteSpace(path))
+ return null;
+
+ configuration c;
+ try
+ {
+ if (!File.Exists(path))
+ return null;
+ using FileStream fs = new(path, FileMode.Open);
+ using XmlReader reader = XmlReader.Create(fs);
+ XmlSerializer serializer = new(typeof(configuration));
+ c = (configuration)serializer.Deserialize(reader);
+ }
+ catch
+ {
+ return null;
+ }
+ if (c is null || c.maps is null || c.maps.Count == 0)
+ return null;
+ return c;
+ }
+
+ public static int ProcessAssemblyConfiguration(configuration c, out List<(string libname, string libpath)> libsToLoad)
+ {
+ libsToLoad = new List<(string libname, string libpath)>(c.maps.Count);
+ int MatchCount = 0;
+ HashSet libsdone = new();
+ foreach (dllmap m in c.maps)
+ {
+ if (string.IsNullOrEmpty(m.target))
+ continue;
+ if (string.IsNullOrEmpty(m.os))
+ continue;
+ if (string.IsNullOrEmpty(m.dll))
+ continue;
+ if (libsdone.Contains(m.dll))
+ continue;
+
+ bool match = false;
+ bool negate = m.os[0] == '!';
+ if (negate)
+ m.os = m.os[1..];
+ string[] tos = m.os.Split(',');
+ foreach (string s in tos)
+ {
+ match = OperatingSystem.IsOSPlatform(s);
+ if (match)
+ break;
+ }
+ if (negate)
+ match = !match;
+ if (!match)
+ continue;
+
+ if (string.IsNullOrEmpty(m.cpu))
+ {
+ libsdone.Add(m.dll);
+ MatchCount++;
+ if (!LoadedLibs.ContainsKey(m.dll))
+ libsToLoad.Add((m.dll, m.target));
+ break;
+ }
+
+ negate = m.cpu[0] == '!';
+ if (negate)
+ m.cpu = m.cpu[1..];
+ m.cpu = m.cpu.ToLower();
+ string[] tcpu = m.cpu.Split(',');
+ match = false;
+ foreach (string s in tcpu)
+ {
+ switch (s)
+ {
+ case "x86":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.X86)
+ match = true;
+ break;
+ case "x86avx":
+ if (Avx.IsSupported && RuntimeInformation.ProcessArchitecture == Architecture.X86)
+ match = true;
+ break;
+ case "x86-64":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
+ match = true;
+ break;
+ case "x86-64avx":
+ if (Avx.IsSupported && RuntimeInformation.ProcessArchitecture == Architecture.X64)
+ match = true;
+ break;
+ case "arm":
+ case "aarch32":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)
+ match = true;
+ break;
+ case "arm64":
+ case "armv8":
+ case "aarch64":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+ match = true;
+ break;
+ case "s390":
+ case "s390x":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.S390x)
+ match = true;
+ break;
+ }
+ if (match)
+ break;
+ }
+ if(negate)
+ match = !match;
+
+ if (match)
+ {
+ MatchCount++;
+ libsdone.Add(m.dll);
+ if (!LoadedLibs.ContainsKey(m.dll))
+ libsToLoad.Add((m.dll, m.target));
+ }
+ }
+ return MatchCount;
+ }
+
+ public static void RegisterDll(Assembly assembly, string libname)
+ {
+ lock (m_mainlock)
+ {
+ if (RegisteredAssemblies.Contains(assembly))
+ return;
+ RegisteredAssemblies.Add(assembly);
+ }
+
+ if (!LoadedLibs.TryGetValue(libname, out IntPtr ptr))
+ {
+ string assemblyPath = Path.GetDirectoryName(assembly.Location);
+ string path = Path.Combine(assemblyPath, libname + ".dllconfig");
+ configuration c = ParseConfig(path);
+ if (c is null)
+ return;
+
+ string libpath = ProcessDllConfiguration(c);
+ if (string.IsNullOrEmpty(libpath))
+ {
+ LoadedLibs.Add(libname, IntPtr.Zero);
+ return;
+ }
+
+ libpath = Path.Combine(assemblyPath, libpath);
+ if (!NativeLibrary.TryLoad(libpath, out ptr))
+ {
+ LoadedLibs.Add(libname, IntPtr.Zero);
+ return;
+ }
+
+ LoadedLibs.Add(libname, ptr);
+ }
+ if (ptr != IntPtr.Zero)
+ NativeLibrary.SetDllImportResolver(assembly, AssemblyDllImport);
+ }
+
+ public static IntPtr LoadDll(string libname)
+ {
+ if (LoadedLibs.TryGetValue(libname, out IntPtr ptr))
+ return ptr;
+
+ string execpath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
+
+ string path = Path.Combine(execpath, libname + ".dllconfig");
+ configuration c = ParseConfig(path);
+ if (c is null)
+ return IntPtr.Zero;
+
+ string libpath = ProcessDllConfiguration(c);
+ if (string.IsNullOrEmpty(libpath))
+ {
+ LoadedLibs.Add(libname, IntPtr.Zero);
+ return IntPtr.Zero;
+ }
+
+ libpath = Path.Combine(execpath, libpath);
+ if (NativeLibrary.TryLoad(libpath, out ptr))
+ {
+ LoadedLibs.Add(libname, ptr);
+ return ptr;
+ }
+
+ LoadedLibs.Add(libname, IntPtr.Zero);
+ return IntPtr.Zero;
+ }
+
+ public static string ProcessDllConfiguration(configuration c)
+ {
+ string newlibname = null;
+ foreach (dllmap m in c.maps)
+ {
+ if (string.IsNullOrEmpty(m.target))
+ continue;
+ if (string.IsNullOrEmpty(m.os))
+ continue;
+
+ bool match = false;
+ bool negate = m.os[0] == '!';
+ if (negate)
+ m.os = m.os[1..];
+ string[] tos = m.os.Split(',');
+ foreach (string s in tos)
+ {
+ match = System.OperatingSystem.IsOSPlatform(s);
+ if (match)
+ {
+ match = !negate;
+ break;
+ }
+ }
+ if (!match)
+ continue;
+
+ if (string.IsNullOrEmpty(m.cpu))
+ {
+ newlibname = m.target;
+ break;
+ }
+
+ negate = m.cpu[0] == '!';
+ if (negate)
+ m.cpu = m.cpu[1..];
+ m.cpu = m.cpu.ToLower();
+ string[] tcpu = m.cpu.Split(',');
+ match = false;
+ foreach (string s in tcpu)
+ {
+ switch (s)
+ {
+ case "x86":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.X86)
+ match = true;
+ break;
+ case "x86avx":
+ if (Avx.IsSupported && RuntimeInformation.ProcessArchitecture == Architecture.X86)
+ match = true;
+ break;
+ case "x86-64":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
+ match = true;
+ break;
+ case "x86-64avx":
+ if (Avx.IsSupported && RuntimeInformation.ProcessArchitecture == Architecture.X64)
+ match = true;
+ break;
+ case "arm":
+ case "aarch32":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)
+ match = true;
+ break;
+ case "arm64":
+ case "armv8":
+ case "aarch64":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+ match = true;
+ break;
+ case "s390":
+ case "s390x":
+ if (RuntimeInformation.ProcessArchitecture == Architecture.S390x)
+ match = true;
+ break;
+ }
+ if (match)
+ {
+ match = !negate;
+ break;
+ }
+ }
+ if (match)
+ {
+ newlibname = m.target;
+ break;
+ }
+ }
+ return newlibname;
+ }
+ }
+}
diff --git a/OpenMetaverse/Imaging/BakeLayer.cs b/OpenMetaverse/Imaging/BakeLayer.cs
index 91326df4..bc8e6f0e 100644
--- a/OpenMetaverse/Imaging/BakeLayer.cs
+++ b/OpenMetaverse/Imaging/BakeLayer.cs
@@ -581,9 +581,9 @@ private void ApplyTint(ManagedImage dest, Color4 src)
for (int i = 0; i < dest.Red.Length; i++)
{
- dest.Red[i] = (byte)((dest.Red[i] * Utils.FloatToByte(src.R, 0f, 1f)) >> 8);
- dest.Green[i] = (byte)((dest.Green[i] * Utils.FloatToByte(src.G, 0f, 1f)) >> 8);
- dest.Blue[i] = (byte)((dest.Blue[i] * Utils.FloatToByte(src.B, 0f, 1f)) >> 8);
+ dest.Red[i] = (byte)((dest.Red[i] * Utils.FloatZeroOneToByte(src.R)) >> 8);
+ dest.Green[i] = (byte)((dest.Green[i] * Utils.FloatZeroOneToByte(src.G)) >> 8);
+ dest.Blue[i] = (byte)((dest.Blue[i] * Utils.FloatZeroOneToByte(src.B)) >> 8);
}
}
@@ -610,9 +610,9 @@ private void InitBakedLayerColor(Color4 color)
/// Blue value
private void InitBakedLayerColor(float r, float g, float b)
{
- byte rByte = Utils.FloatToByte(r, 0f, 1f);
- byte gByte = Utils.FloatToByte(g, 0f, 1f);
- byte bByte = Utils.FloatToByte(b, 0f, 1f);
+ byte rByte = Utils.FloatZeroOneToByte(r);
+ byte gByte = Utils.FloatZeroOneToByte(g);
+ byte bByte = Utils.FloatZeroOneToByte(b);
byte rAlt, gAlt, bAlt;
diff --git a/OpenMetaverse/Imaging/OpenJPEG.cs b/OpenMetaverse/Imaging/OpenJPEG.cs
index 2d68d668..71c8c804 100644
--- a/OpenMetaverse/Imaging/OpenJPEG.cs
+++ b/OpenMetaverse/Imaging/OpenJPEG.cs
@@ -27,11 +27,11 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
+using System.Reflection;
using System.Runtime.InteropServices;
namespace OpenMetaverse.Imaging
{
-#if !NO_UNSAFE
///
/// A Wrapper around openjpeg to encode and decode images to and from byte arrays
///
@@ -95,73 +95,45 @@ public override string ToString()
start_pos, end_ph_pos, end_pos);
}
}
-
#endregion JPEG2000 Structs
- #region Unmanaged Function Declarations
-
+ static OpenJPEG()
+ {
+ DllmapConfigHelper.RegisterAssembly(typeof(OpenJPEG).Assembly);
+ }
+ #region Unmanaged Function Declarations
// allocate encoded buffer based on length field
[System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet.dll", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport("openjpeg-dotnet", CallingConvention = CallingConvention.Cdecl)]
private static extern bool DotNetAllocEncoded(ref MarshalledImage image);
// allocate decoded buffer based on width and height fields
[System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet.dll", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport("openjpeg-dotnet", CallingConvention = CallingConvention.Cdecl)]
private static extern bool DotNetAllocDecoded(ref MarshalledImage image);
// free buffers
[System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet.dll", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport("openjpeg-dotnet", CallingConvention = CallingConvention.Cdecl)]
private static extern bool DotNetFree(ref MarshalledImage image);
// encode raw to jpeg2000
[System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet.dll", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport("openjpeg-dotnet", CallingConvention = CallingConvention.Cdecl)]
private static extern bool DotNetEncode(ref MarshalledImage image, bool lossless);
// decode jpeg2000 to raw
[System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet.dll", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport("openjpeg-dotnet", CallingConvention = CallingConvention.Cdecl)]
private static extern bool DotNetDecode(ref MarshalledImage image);
// decode jpeg2000 to raw, get jpeg2000 file info
[System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet.dll", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport("openjpeg-dotnet", CallingConvention = CallingConvention.Cdecl)]
private static extern bool DotNetDecodeWithInfo(ref MarshalledImage image);
- // invoke 64 bit openjpeg calls
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet-x86_64.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern bool DotNetAllocEncoded64(ref MarshalledImage image);
-
- // allocate decoded buffer based on width and height fields
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet-x86_64.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern bool DotNetAllocDecoded64(ref MarshalledImage image);
-
- // free buffers
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet-x86_64.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern bool DotNetFree64(ref MarshalledImage image);
-
- // encode raw to jpeg2000
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet-x86_64.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern bool DotNetEncode64(ref MarshalledImage image, bool lossless);
-
- // decode jpeg2000 to raw
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet-x86_64.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern bool DotNetDecode64(ref MarshalledImage image);
-
- // decode jpeg2000 to raw, get jpeg2000 file info
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("openjpeg-dotnet-x86_64.dll", CallingConvention = CallingConvention.Cdecl)]
- private static extern bool DotNetDecodeWithInfo64(ref MarshalledImage image);
- #endregion Unmanaged Function Declarations
-
+ #endregion
/// OpenJPEG is not threadsafe, so this object is used to lock
/// during calls into unmanaged code
private static object OpenJPEGLock = new object();
@@ -190,9 +162,7 @@ public static byte[] Encode(ManagedImage image, bool lossless)
lock (OpenJPEGLock)
{
-
- bool allocSuccess = (IntPtr.Size == 8) ? DotNetAllocDecoded64(ref marshalled) : DotNetAllocDecoded(ref marshalled);
-
+ bool allocSuccess = DotNetAllocDecoded(ref marshalled);
if (!allocSuccess)
throw new Exception("DotNetAllocDecoded failed");
@@ -209,7 +179,7 @@ public static byte[] Encode(ManagedImage image, bool lossless)
if ((image.Channels & ManagedImage.ImageChannels.Bump) != 0) Marshal.Copy(image.Bump, 0, (IntPtr)(marshalled.decoded.ToInt64() + n * 4), n);
// codec will allocate output buffer
- bool encodeSuccess = (IntPtr.Size == 8) ? DotNetEncode64(ref marshalled, lossless) : DotNetEncode(ref marshalled, lossless);
+ bool encodeSuccess = DotNetEncode(ref marshalled, lossless);
if (!encodeSuccess)
throw new Exception("DotNetEncode failed");
@@ -218,10 +188,7 @@ public static byte[] Encode(ManagedImage image, bool lossless)
Marshal.Copy(marshalled.encoded, encoded, 0, marshalled.length);
// free buffers
- if (IntPtr.Size == 8)
- DotNetFree64(ref marshalled);
- else
- DotNetFree(ref marshalled);
+ DotNetFree(ref marshalled);
}
return encoded;
@@ -284,18 +251,12 @@ public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage)
lock (OpenJPEGLock)
{
- if (IntPtr.Size == 8)
- DotNetAllocEncoded64(ref marshalled);
- else
- DotNetAllocEncoded(ref marshalled);
+ DotNetAllocEncoded(ref marshalled);
Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length);
// Codec will allocate output buffer
- if (IntPtr.Size == 8)
- DotNetDecode64(ref marshalled);
- else
- DotNetDecode(ref marshalled);
+ DotNetDecode(ref marshalled);
int n = marshalled.width * marshalled.height;
@@ -349,19 +310,13 @@ public static bool DecodeToImage(byte[] encoded, out ManagedImage managedImage)
Logger.Log("Decoded image with unhandled number of components: " + marshalled.components,
Helpers.LogLevel.Error);
- if (IntPtr.Size == 8)
- DotNetFree64(ref marshalled);
- else
- DotNetFree(ref marshalled);
+ DotNetFree(ref marshalled);
managedImage = null;
return false;
}
- if (IntPtr.Size == 8)
- DotNetFree64(ref marshalled);
- else
- DotNetFree(ref marshalled);
+ DotNetFree(ref marshalled);
}
return true;
@@ -386,15 +341,12 @@ public static bool DecodeLayerBoundaries(byte[] encoded, out J2KLayerInfo[] laye
lock (OpenJPEGLock)
{
- if (IntPtr.Size == 8)
- DotNetAllocEncoded64(ref marshalled);
- else
- DotNetAllocEncoded(ref marshalled);
+ DotNetAllocEncoded(ref marshalled);
Marshal.Copy(encoded, 0, marshalled.encoded, encoded.Length);
// Run the decode
- bool decodeSuccess = (IntPtr.Size == 8) ? DotNetDecodeWithInfo64(ref marshalled) : DotNetDecodeWithInfo(ref marshalled);
+ bool decodeSuccess = DotNetDecodeWithInfo(ref marshalled);
if (decodeSuccess)
{
components = marshalled.components;
@@ -499,10 +451,7 @@ public static bool DecodeLayerBoundaries(byte[] encoded, out J2KLayerInfo[] laye
}
}
- if (IntPtr.Size == 8)
- DotNetFree64(ref marshalled);
- else
- DotNetFree(ref marshalled);
+ DotNetFree(ref marshalled);
}
return success;
@@ -585,5 +534,4 @@ public unsafe static byte[] EncodeFromImage(Bitmap bitmap, bool lossless)
return encoded;
}
}
-#endif
}
diff --git a/OpenMetaverse/Imaging/TGALoader.cs b/OpenMetaverse/Imaging/TGALoader.cs
index c6c39839..111e369a 100644
--- a/OpenMetaverse/Imaging/TGALoader.cs
+++ b/OpenMetaverse/Imaging/TGALoader.cs
@@ -30,8 +30,6 @@
namespace OpenMetaverse.Imaging
{
-#if !NO_UNSAFE
-
///
/// Capability to load TGAs to Bitmap
///
@@ -635,6 +633,4 @@ public static System.Drawing.Bitmap LoadTGA(string filename)
}
}
}
-
-#endif
}
diff --git a/OpenMetaverse/Login.cs b/OpenMetaverse/Login.cs
index 43d33fb3..93de96bc 100644
--- a/OpenMetaverse/Login.cs
+++ b/OpenMetaverse/Login.cs
@@ -24,15 +24,19 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-using Nwc.XmlRpc;
-using OpenMetaverse.Http;
-using OpenMetaverse.Packets;
-using OpenMetaverse.StructuredData;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using OpenMetaverse.StructuredData;
+using OpenMetaverse.Http;
+using OpenMetaverse.Packets;
using System.Threading;
+using XmlRpcCore;
+using System.Threading.Tasks;
+using System.Net.Http;
namespace OpenMetaverse
{
@@ -149,23 +153,25 @@ public class LoginParams
///
public LoginParams()
{
- List options = new List(16);
- options.Add("inventory-root");
- options.Add("inventory-skeleton");
- options.Add("inventory-lib-root");
- options.Add("inventory-lib-owner");
- options.Add("inventory-skel-lib");
- options.Add("initial-outfit");
- options.Add("gestures");
- options.Add("event_categories");
- options.Add("event_notifications");
- options.Add("classified_categories");
- options.Add("buddy-list");
- options.Add("ui-config");
- options.Add("tutorial_settings");
- options.Add("login-flags");
- options.Add("global-textures");
- options.Add("adult_compliant");
+ var options = new List(16)
+ {
+ "inventory-root",
+ "inventory-skeleton",
+ "inventory-lib-root",
+ "inventory-lib-owner",
+ "inventory-skel-lib",
+ "initial-outfit",
+ "gestures",
+ "event_categories",
+ "event_notifications",
+ "classified_categories",
+ "buddy-list",
+ "ui-config",
+ "tutorial_settings",
+ "login-flags",
+ "global-textures",
+ "adult_compliant"
+ };
this.Options = options.ToArray();
this.MethodName = "login_to_simulator";
@@ -899,6 +905,13 @@ public event EventHandler LoginProgress
#endregion
#region Private Members
+
+ public static readonly HttpClient HTTP_CLIENT = new HttpClient(new HttpClientHandler()
+ {
+ ServerCertificateCustomValidationCallback = delegate { return true; },
+ AllowAutoRedirect = true
+ });
+
private LoginParams CurrentContext = null;
private AutoResetEvent LoginEvent = new AutoResetEvent(false);
private LoginStatus InternalStatusCode = LoginStatus.None;
@@ -1060,6 +1073,23 @@ public void AbortLogin()
#endregion
#region Private Methods
+ public static bool ValidateServerCertificate(
+ object sender,
+ X509Certificate certificate,
+ X509Chain chain,
+ SslPolicyErrors sslPolicyErrors)
+ {
+ //if (m_NoVerifyCertChain)
+ sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
+
+ //if (m_NoVerifyCertHostname)
+ sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
+
+ if (sslPolicyErrors == SslPolicyErrors.None)
+ return true;
+
+ return false;
+ }
private void BeginLogin()
{
@@ -1109,7 +1139,7 @@ private void BeginLogin()
#endregion
- ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
+ ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
if (Client.Settings.USE_LLSD_LOGIN)
{
@@ -1176,64 +1206,69 @@ private void BeginLogin()
#region XML-RPC Based Login Code
// Create the Hashtable for XmlRpcCs
- Hashtable loginXmlRpc = new Hashtable();
- loginXmlRpc["first"] = loginParams.FirstName;
- loginXmlRpc["last"] = loginParams.LastName;
- loginXmlRpc["passwd"] = loginParams.Password;
- loginXmlRpc["start"] = loginParams.Start;
- loginXmlRpc["channel"] = loginParams.Channel;
- loginXmlRpc["version"] = loginParams.Version;
- loginXmlRpc["platform"] = loginParams.Platform;
- loginXmlRpc["platform_version"] = loginParams.PlatformVersion;
- loginXmlRpc["mac"] = loginParams.MAC;
- if (loginParams.AgreeToTos)
- loginXmlRpc["agree_to_tos"] = "true";
- if (loginParams.ReadCritical)
- loginXmlRpc["read_critical"] = "true";
- loginXmlRpc["id0"] = loginParams.ID0;
- loginXmlRpc["last_exec_event"] = (int)loginParams.LastExecEvent;
+ var loginXmlRpc = new Hashtable
+ {
+ ["first"] = loginParams.FirstName,
+ ["last"] = loginParams.LastName,
+ ["passwd"] = loginParams.Password,
+ ["start"] = loginParams.Start,
+ ["channel"] = loginParams.Channel,
+ ["version"] = loginParams.Version,
+ ["platform"] = loginParams.Platform,
+ ["platform_version"] = loginParams.PlatformVersion,
+ ["mac"] = loginParams.MAC,
+ ["id0"] = loginParams.ID0,
+ ["last_exec_event"] = (int)loginParams.LastExecEvent
+ };
+ if (loginParams.AgreeToTos) { loginXmlRpc["agree_to_tos"] = "true"; }
+ if (loginParams.ReadCritical) { loginXmlRpc["read_critical"] = "true"; }
+ //if (loginParams.MfaEnabled)
+ //{
+ // loginXmlRpc["token"] = loginParams.Token;
+ // loginXmlRpc["mfa_hash"] = loginParams.MfaHash;
+ //}
// Create the options array
ArrayList options = new ArrayList();
for (int i = 0; i < loginParams.Options.Length; i++)
+ {
options.Add(loginParams.Options[i]);
-
- foreach (string[] callbackOpts in CallbackOptions.Values)
+ }
+ foreach (var callbackOpts in CallbackOptions.Values)
{
- if (callbackOpts != null)
+ if (callbackOpts == null) continue;
+ foreach (var t in callbackOpts)
{
- for (int i = 0; i < callbackOpts.Length; i++)
- {
- if (!options.Contains(callbackOpts[i]))
- options.Add(callbackOpts[i]);
- }
+ if (!options.Contains(t))
+ options.Add(t);
}
}
loginXmlRpc["options"] = options;
try
{
- ArrayList loginArray = new ArrayList(1);
- loginArray.Add(loginXmlRpc);
- XmlRpcRequest request = new XmlRpcRequest(CurrentContext.MethodName, loginArray);
+ var loginArray = new ArrayList(1) { loginXmlRpc };
+ var request = new XmlRpcRequest(CurrentContext.MethodName, loginArray);
var cc = CurrentContext;
+
// Start the request
- Thread requestThread = new Thread(
- delegate ()
+ Task.Run(async () =>
+ {
+ try
{
- try
- {
- LoginReplyXmlRpcHandler(
- request.Send(cc.URI, cc.Timeout),
- loginParams);
- }
- catch (Exception e)
- {
- UpdateLoginStatus(LoginStatus.Failed, "Error opening the login server connection: " + e.Message);
- }
- });
- requestThread.Name = "XML-RPC Login";
- requestThread.Start();
+ var cts = new CancellationTokenSource();
+ cts.CancelAfter(cc.Timeout);
+ var loginResponse = await HTTP_CLIENT.PostAsXmlRpcAsync(cc.URI, request, cts.Token);
+ cts.Dispose();
+
+ LoginReplyXmlRpcHandler(loginResponse, loginParams);
+ }
+ catch (Exception e)
+ {
+ UpdateLoginStatus(LoginStatus.Failed,
+ $"Error opening the login server connection: {e.Message}");
+ }
+ });
}
catch (Exception e)
{
diff --git a/OpenMetaverse/Messages/LindenMessages.cs b/OpenMetaverse/Messages/LindenMessages.cs
index 9664478e..9f26d1f5 100644
--- a/OpenMetaverse/Messages/LindenMessages.cs
+++ b/OpenMetaverse/Messages/LindenMessages.cs
@@ -24,13 +24,13 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-using ComponentAce.Compression.Libs.zlib;
using OpenMetaverse.Interfaces;
using OpenMetaverse.StructuredData;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
+using ComponentAce.Compression.Libs.zlib;
namespace OpenMetaverse.Messages.Linden
{
@@ -1813,6 +1813,76 @@ public OSDMap Serialize()
}
+ public class LargeGenericMessage : IMessage
+ {
+ private OSDMap RawData;
+ public UUID AgentID;
+ public UUID SessionID;
+ public UUID TransactionID;
+
+ public string Method;
+ public UUID Invoice;
+
+ public class Parameter
+ {
+ public string value;
+ }
+
+ public Parameter[] Parameters;
+
+ public void Deserialize(OSDMap map)
+ {
+ RawData = map;
+ OSD osdtmp, osdtmp2;
+ if (map.TryGetValue("AgentData", out osdtmp))
+ {
+ if (osdtmp is OSDArray agdArray && agdArray.Count > 0)
+ {
+ if (agdArray[0] is OSDMap agdMap)
+ {
+ if (agdMap.TryGetValue("AgentID", out osdtmp2))
+ AgentID = osdtmp2.AsUUID();
+ if (agdMap.TryGetValue("SessionID", out osdtmp2))
+ SessionID = osdtmp2.AsUUID();
+ if (agdMap.TryGetValue("TransactionID", out osdtmp2))
+ TransactionID = osdtmp2.AsUUID();
+ }
+ }
+ }
+ if (map.TryGetValue("MethodData", out osdtmp))
+ {
+ if (osdtmp is OSDArray mdArray && mdArray.Count > 0)
+ {
+ if (mdArray[0] is OSDMap mdMap)
+ {
+ if (mdMap.TryGetValue("Method", out osdtmp2))
+ Method = osdtmp2.AsString();
+ if (mdMap.TryGetValue("Invoice", out osdtmp2))
+ Invoice = osdtmp2.AsUUID();
+ }
+ }
+ }
+ if (map.TryGetValue("ParamList", out osdtmp))
+ {
+ if (osdtmp is OSDArray pArray && pArray.Count > 0)
+ {
+ Parameters = new Parameter[pArray.Count];
+ for(int i = 0; i < Parameters.Length; i++)
+ {
+ Parameters[i] = new Parameter(){value = pArray[i].ToString() };
+ }
+ }
+ }
+
+ Method ??="MissingMethod";
+ }
+
+ public OSDMap Serialize()
+ {
+ return RawData;
+ }
+ }
+
/// Base class for Asset uploads/results via Capabilities
public abstract class AssetUploaderBlock
{
diff --git a/OpenMetaverse/Messages/MessageEventDecoder.cs b/OpenMetaverse/Messages/MessageEventDecoder.cs
index 063b899c..cb9321ab 100644
--- a/OpenMetaverse/Messages/MessageEventDecoder.cs
+++ b/OpenMetaverse/Messages/MessageEventDecoder.cs
@@ -101,6 +101,7 @@ public static IMessage DecodeEvent(string eventName, OSDMap map)
case "BulkUpdateInventory": message = new BulkUpdateInventoryMessage(); break;
case "RenderMaterials": message = new RenderMaterialsMessage(); break;
case "GetObjectCost": message = GetObjectCostMessage.GetMessageHandler(map); break;
+ case "LargeGenericMessage": message = new LargeGenericMessage(); break;
// Capabilities TODO:
// DispatchRegionInfo
diff --git a/OpenMetaverse/OpenMetaverse.csproj b/OpenMetaverse/OpenMetaverse.csproj
index ce8212b5..755cb050 100644
--- a/OpenMetaverse/OpenMetaverse.csproj
+++ b/OpenMetaverse/OpenMetaverse.csproj
@@ -1,33 +1,29 @@
Local
- net48;netstandard2.0;netstandard2.1
+ net6.0
OpenMetaverse
1591,1574,0419,0618
True
true
+ Utopia Skye LLC, OpenMetaverse Developers
+ OMV OpenMetaverse OpenSim OpenSim-NGC OpenMetaverseFoundation VirtualWorld VirtualReality 3D SecondLife
-
+
+
+
..\bin\SmartThreadPool.dll
False
-
- ..\bin\XMLRPC.dll
- False
-
-
- ..\bin\zlib.net.dll
- False
-
-
\ No newline at end of file
+
diff --git a/OpenMetaverse/PacketDecoder.cs b/OpenMetaverse/PacketDecoder.cs
index 87f4ec89..0ad11faa 100644
--- a/OpenMetaverse/PacketDecoder.cs
+++ b/OpenMetaverse/PacketDecoder.cs
@@ -1,1926 +1,1949 @@
-/*
- * Copyright (c) 2006-2016, openmetaverse.co
- * 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.co 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 System.Reflection;
-using System.Text;
-
-namespace OpenMetaverse.Packets
-{
-
- public static class PacketDecoder
- {
- ///
- /// A custom decoder callback
- ///
- /// The key of the object
- /// the data to decode
- /// A string represending the fieldData
- public delegate string CustomPacketDecoder(string fieldName, object fieldData);
-
- private static Dictionary> Callbacks = new Dictionary>();
-
-
- static PacketDecoder()
- {
- AddCallback("Color", DecodeColorField);
- AddCallback("TextColor", DecodeColorField);
- AddCallback("Timestamp", DecodeTimeStamp);
- AddCallback("EstateCovenantReply.Data.CovenantTimestamp", DecodeTimeStamp);
- AddCallback("CreationDate", DecodeTimeStamp);
- AddCallback("BinaryBucket", DecodeBinaryBucket);
- AddCallback("ParcelData.Data", DecodeBinaryToHexString);
- AddCallback("LayerData.Data", DecodeBinaryToHexString);
- AddCallback("ImageData.Data", DecodeImageData);
- AddCallback("TransferData.Data", DecodeBinaryToHexString);
- AddCallback("ObjectData.TextureEntry", DecodeTextureEntry);
- AddCallback("ImprovedInstantMessage.MessageBlock.Dialog", DecodeDialog);
-
- // Inventory/Permissions
- AddCallback("BaseMask", DecodePermissionMask);
- AddCallback("OwnerMask", DecodePermissionMask);
- AddCallback("EveryoneMask", DecodePermissionMask);
- AddCallback("NextOwnerMask", DecodePermissionMask);
- AddCallback("GroupMask", DecodePermissionMask);
-
- // FetchInventoryDescendents
- AddCallback("InventoryData.SortOrder", DecodeInventorySort);
-
- AddCallback("WearableType", DecodeWearableType);
- //
- AddCallback("InventoryData.Type", DecodeInventoryType);
- AddCallback("InvType", DecodeInventoryInvType);
- AddCallback("InventoryData.Flags", DecodeInventoryFlags);
- // BulkUpdateInventory
- AddCallback("ItemData.Type", DecodeInventoryType);
- AddCallback("ItemData.Flags", DecodeInventoryFlags);
-
- AddCallback("SaleType", DecodeObjectSaleType);
-
- AddCallback("ScriptControlChange.Data.Controls", DecodeScriptControls);
-
- AddCallback("RegionFlags", DecodeRegionFlags);
- AddCallback("SimAccess", DecodeSimAccess);
- AddCallback("ControlFlags", DecodeControlFlags);
-
- // AgentUpdate
- AddCallback("AgentUpdate.AgentData.State", DecodeAgentState);
- AddCallback("AgentUpdate.AgentData.Flags", DecodeAgentFlags);
-
- // ViewerEffect TypeData
- AddCallback("ViewerEffect.Effect.TypeData", DecodeViewerEffectTypeData);
- AddCallback("ViewerEffect.Effect.Type", DecodeViewerEffectType);
-
- // Prim/ObjectUpdate decoders
- AddCallback("ObjectUpdate.ObjectData.PCode", DecodeObjectPCode);
- AddCallback("ObjectUpdate.ObjectData.Material", DecodeObjectMaterial);
- AddCallback("ObjectUpdate.ObjectData.ClickAction", DecodeObjectClickAction);
- AddCallback("ObjectData.UpdateFlags", DecodeObjectUpdateFlags);
-
- AddCallback("ObjectUpdate.ObjectData.ObjectData", DecodeObjectData);
- AddCallback("TextureAnim", DecodeObjectTextureAnim);
- AddCallback("ObjectUpdate.ObjectData.NameValue", DecodeNameValue);
- AddCallback("ObjectUpdate.ObjectData.Data", DecodeObjectData);
-
- AddCallback("ObjectUpdate.ObjectData.PSBlock", DecodeObjectParticleSystem);
- AddCallback("ParticleSys", DecodeObjectParticleSystem);
- AddCallback("ObjectUpdate.ObjectData.ExtraParams", DecodeObjectExtraParams);
-
- AddCallback("ImprovedTerseObjectUpdate.ObjectData.Data", DecodeTerseUpdate);
- AddCallback("ImprovedTerseObjectUpdate.ObjectData.TextureEntry", DecodeTerseTextureEntry);
-
- AddCallback("ObjectUpdateCompressed.ObjectData.Data", DecodeObjectCompressedData);
-
- // ImprovedTerseObjectUpdate & ObjectUpdate AttachmentPoint & ObjectUpdateCompressed
- AddCallback("ObjectData.State", DecodeObjectState);
- //AddCallback("ObjectUpdateCompressed.ObjectData.State", DecodeObjectState);
- //AddCallback("ImprovedTerseObjectUpdate.ObjectData.State", DecodeObjectState);
-
-
- // ChatFromSimulator
- AddCallback("ChatData.SourceType", DecodeChatSourceType);
- AddCallback("ChatData.ChatType", DecodeChatChatType);
- AddCallback("ChatData.Audible", DecodeChatAudible);
- AddCallback("AttachedSound.DataBlock.Flags", DecodeAttachedSoundFlags);
-
- AddCallback("RequestImage.Type", DecodeImageType);
-
- AddCallback("EstateOwnerMessage.ParamList.Parameter", DecodeEstateParameter);
-
- AddCallback("Codec", DecodeImageCodec);
- AddCallback("Info.TeleportFlags", DecodeTeleportFlags);
-
- // map
- AddCallback("MapBlockRequest.AgentData.Flags", DecodeMapRequestFlags);
- AddCallback("MapItemRequest.AgentData.Flags", DecodeMapRequestFlags);
- AddCallback("MapBlockReply.Data.Access", DecodeMapAccess);
- AddCallback("FolderData.Type", DecodeFolderType);
- AddCallback("RequestData.ItemType", DecodeGridItemType);
-
- // TransferRequest/TransferInfo
- AddCallback("TransferInfo.Params", DecodeTransferParams);
- AddCallback("TransferInfo.ChannelType", DecodeTransferChannelType);
- AddCallback("TransferInfo.SourceType", DecodeTransferSourceType);
- AddCallback("TransferInfo.TargetType", DecodeTransferTargetType);
- AddCallback("TransferData.ChannelType", DecodeTransferChannelType);
- // SendXferPacket
- AddCallback("DataPacket.Data", DecodeBinaryToHexString);
- // Directory Manager
- AddCallback("DirClassifiedQuery.QueryData.QueryFlags", DecodeDirClassifiedQueryFlags);
- AddCallback("QueryData.QueryFlags", DecodeDirQueryFlags);
- AddCallback("Category", DecodeCategory);
- AddCallback("QueryData.SearchType", SearchTypeFlags);
-
- AddCallback("ClassifiedFlags", DecodeDirClassifiedFlags);
- AddCallback("EventFlags", DecodeEventFlags);
-
- AddCallback("ParcelAccessListRequest.Data.Flags", DecodeParcelACL);
- AddCallback("ParcelAccessListReply.Data.Flags", DecodeParcelACL);
- //AddCallback("ParcelAccessListReply.List.Flags", DecodeParcelACLReply);
-
- // AgentAnimation
- AddCallback("AnimID", DecodeAnimToConst);
-
- AddCallback("LayerData.LayerID.Type", DecodeLayerDataType);
-
- AddCallback("GroupPowers", DecodeGroupPowers);
- }
-
- ///
- /// Add a custom decoder callback
- ///
- /// The key of the field to decode
- /// The custom decode handler
- public static void AddCallback(string key, CustomPacketDecoder customPacketHandler)
- {
- if (Callbacks.ContainsKey(key))
- {
- lock (Callbacks)
- Callbacks[key].Add(customPacketHandler);
- }
- else
- {
- lock (Callbacks)
- Callbacks.Add(key, new List() { customPacketHandler });
- }
- }
-
- ///
- /// Remove a custom decoder callback
- ///
- /// The key of the field to decode
- /// The custom decode handler
- public static void RemoveCustomHandler(string key, CustomPacketDecoder customPacketHandler)
- {
- if (Callbacks.ContainsKey(key))
- lock (Callbacks)
- {
- if (Callbacks[key].Contains(customPacketHandler))
- Callbacks[key].Remove(customPacketHandler);
- }
- }
-
- #region Custom Decoders
-
- private static string DecodeTerseUpdate(string fieldName, object fieldData)
- {
- byte[] block = (byte[])fieldData;
- int i = 4;
-
- StringBuilder result = new StringBuilder();
-
- // LocalID
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "LocalID",
- Utils.BytesToUInt(block, 0),
- "Uint32");
-
-
-
- // State
- byte point = block[i++];
- result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
- "State",
- point,
- "(" + (AttachmentPoint)point + ")",
- "AttachmentPoint");
-
- // Avatar boolean
- bool isAvatar = (block[i++] != 0);
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "IsAvatar",
- isAvatar,
- "Boolean");
-
- // Collision normal for avatar
- if (isAvatar)
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "CollisionPlane",
- new Vector4(block, i),
- "Vector4");
-
- i += 16;
- }
-
- // Position
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Position",
- new Vector3(block, i),
- "Vector3");
- i += 12;
-
- // Velocity
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Velocity",
- new Vector3(
- Utils.BytesUInt16ToFloat(block, i, -128.0f, 128.0f),
- Utils.BytesUInt16ToFloat(block, i + 2, -128.0f, 128.0f),
- Utils.BytesUInt16ToFloat(block, i + 4, -128.0f, 128.0f)),
- "Vector3");
- i += 6;
-
- // Acceleration
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Acceleration",
- new Vector3(
- Utils.BytesUInt16ToFloat(block, i, -64.0f, 64.0f),
- Utils.BytesUInt16ToFloat(block, i + 2, -64.0f, 64.0f),
- Utils.BytesUInt16ToFloat(block, i + 4, -64.0f, 64.0f)),
- "Vector3");
-
- i += 6;
- // Rotation (theta)
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Rotation",
- new Quaternion(
- Utils.BytesUInt16ToFloat(block, i, -1.0f, 1.0f),
- Utils.BytesUInt16ToFloat(block, i + 2, -1.0f, 1.0f),
- Utils.BytesUInt16ToFloat(block, i + 4, -1.0f, 1.0f),
- Utils.BytesUInt16ToFloat(block, i + 6, -1.0f, 1.0f)),
- "Quaternion");
- i += 8;
- // Angular velocity (omega)
- result.AppendFormat("{0,30}: {1,-40} [{2}]",
- "AngularVelocity",
- new Vector3(
- Utils.BytesUInt16ToFloat(block, i, -64.0f, 64.0f),
- Utils.BytesUInt16ToFloat(block, i + 2, -64.0f, 64.0f),
- Utils.BytesUInt16ToFloat(block, i + 4, -64.0f, 64.0f)),
- "Vector3");
- //pos += 6;
- // TODO: What is in these 6 bytes?
- return result.ToString();
- }
-
- private static string DecodeObjectCompressedData(string fieldName, object fieldData)
- {
- StringBuilder result = new StringBuilder();
- byte[] block = (byte[])fieldData;
- int i = 0;
-
- // UUID
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ID",
- new UUID(block, 0),
- "UUID");
- i += 16;
-
- // Local ID
- uint LocalID = (uint)(block[i++] + (block[i++] << 8) +
- (block[i++] << 16) + (block[i++] << 24));
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "LocalID",
- LocalID,
- "Uint32");
- // PCode
- PCode pcode = (PCode)block[i++];
-
- result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
- "PCode",
- (int)pcode,
- "(" + pcode + ")",
- "PCode");
-
- // State
- AttachmentPoint point = (AttachmentPoint)block[i++];
- result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
- "State",
- (byte)point,
- "(" + point + ")",
- "AttachmentPoint");
-
- //CRC
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "CRC",
- Utils.BytesToUInt(block, i),
- "UInt");
- i += 4;
-
- // Material
- result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
- "Material",
- block[i],
- "(" + (Material)block[i++] + ")",
- "Material");
-
- // Click action
- result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
- "ClickAction",
- block[i],
- "(" + (ClickAction)block[i++] + ")",
- "ClickAction");
-
- // Scale
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Scale",
- new Vector3(block, i),
- "Vector3");
- i += 12;
-
- // Position
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Position",
- new Vector3(block, i),
- "Vector3");
- i += 12;
-
- // Rotation
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Rotation",
- new Vector3(block, i),
- "Vector3");
-
- i += 12;
- // Compressed flags
-
- CompressedFlags flags = (CompressedFlags)Utils.BytesToUInt(block, i);
- result.AppendFormat("{0,30}: {1,-10} {2,-29} [{3}]" + Environment.NewLine,
- "CompressedFlags",
- Utils.BytesToUInt(block, i),
- "(" + (CompressedFlags)Utils.BytesToUInt(block, i) + ")",
- "UInt");
- i += 4;
-
- // Owners ID
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "OwnerID",
- new UUID(block, i),
- "UUID");
- i += 16;
-
- // Angular velocity
- if ((flags & CompressedFlags.HasAngularVelocity) != 0)
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "AngularVelocity",
- new Vector3(block, i),
- "Vector3");
- i += 12;
- }
-
- // Parent ID
- if ((flags & CompressedFlags.HasParent) != 0)
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ParentID",
- (uint)(block[i++] + (block[i++] << 8) +
- (block[i++] << 16) + (block[i++] << 24)),
- "UInt");
- }
-
- // Tree data
- if ((flags & CompressedFlags.Tree) != 0)
- {
- result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
- "TreeSpecies",
- block[i++],
- "(" + (Tree)block[i] + ")",
- "Tree");
- }
-
- // Scratch pad
- else if ((flags & CompressedFlags.ScratchPad) != 0)
- {
- int size = block[i++];
- byte[] scratch = new byte[size];
- Buffer.BlockCopy(block, i, scratch, 0, size);
- result.AppendFormat("{0,30}: {1,-40} [ScratchPad[]]" + Environment.NewLine,
- "ScratchPad",
- Utils.BytesToHexString(scratch, String.Format("{0,30}", "Data")));
- i += size;
- }
-
- // Floating text
- if ((flags & CompressedFlags.HasText) != 0)
- {
- string text = String.Empty;
- while (block[i] != 0)
- {
- text += (char)block[i];
- i++;
- }
- i++;
-
- // Floating text
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Text",
- text,
- "string");
-
- // Text color
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "TextColor",
- new Color4(block, i, false),
- "Color4");
- i += 4;
- }
-
- // Media URL
- if ((flags & CompressedFlags.MediaURL) != 0)
- {
- string text = String.Empty;
- while (block[i] != 0)
- {
- text += (char)block[i];
- i++;
- }
- i++;
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "MediaURL",
- text,
- "string");
- }
-
- // Particle system
- if ((flags & CompressedFlags.HasParticles) != 0)
- {
- Primitive.ParticleSystem p = new Primitive.ParticleSystem(block, i);
- result.AppendLine(DecodeObjectParticleSystem("ParticleSystem", p));
- i += 86;
- }
-
- // Extra parameters TODO:
- Primitive prim = new Primitive();
- int extrapLen = prim.SetExtraParamsFromBytes(block, i);
- i += extrapLen;
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ExtraParams[]",
- extrapLen,
- "byte[]");
-
- //Sound data
- if ((flags & CompressedFlags.HasSound) != 0)
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "SoundID",
- new UUID(block, i),
- "UUID");
- i += 16;
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "SoundGain",
- Utils.BytesToFloat(block, i),
- "Float");
- i += 4;
-
- result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
- "SoundFlags",
- block[i++],
- "(" + (SoundFlags)block[i] + ")",
- "SoundFlags");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "SoundRadius",
- Utils.BytesToFloat(block, i),
- "Float");
- i += 4;
- }
-
- // Name values
- if ((flags & CompressedFlags.HasNameValues) != 0)
- {
- string text = String.Empty;
- while (block[i] != 0)
- {
- text += (char)block[i];
- i++;
- }
- i++;
-
- // Parse the name values
- if (text.Length > 0)
- {
- string[] lines = text.Split('\n');
- NameValue[] nameValues = new NameValue[lines.Length];
-
- for (int j = 0; j < lines.Length; j++)
- {
- if (!String.IsNullOrEmpty(lines[j]))
- {
- NameValue nv = new NameValue(lines[j]);
- nameValues[j] = nv;
- }
- }
- result.AppendLine(DecodeNameValue("NameValues", nameValues));
- }
- }
-
- result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
- "PathCurve",
- block[i],
- "(" + (PathCurve)block[i++] + ")",
- "PathCurve");
-
- ushort pathBegin = Utils.BytesToUInt16(block, i);
- i += 2;
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathBegin",
- Primitive.UnpackBeginCut(pathBegin),
- "float");
-
- ushort pathEnd = Utils.BytesToUInt16(block, i);
- i += 2;
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathEnd",
- Primitive.UnpackEndCut(pathEnd),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathScaleX",
- Primitive.UnpackPathScale(block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathScaleY",
- Primitive.UnpackPathScale(block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathShearX",
- Primitive.UnpackPathShear((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathShearY",
- Primitive.UnpackPathShear((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathTwist",
- Primitive.UnpackPathTwist((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathTwistBegin",
- Primitive.UnpackPathTwist((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathRadiusOffset",
- Primitive.UnpackPathTwist((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathTaperX",
- Primitive.UnpackPathTaper((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathTaperY",
- Primitive.UnpackPathTaper((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathRevolutions",
- Primitive.UnpackPathRevolutions(block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "PathSkew",
- Primitive.UnpackPathTwist((sbyte)block[i++]),
- "float");
-
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ProfileCurve",
- block[i++],
- "float");
-
- ushort profileBegin = Utils.BytesToUInt16(block, i);
- i += 2;
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ProfileBegin",
- Primitive.UnpackBeginCut(profileBegin),
- "float");
-
- ushort profileEnd = Utils.BytesToUInt16(block, i);
- i += 2;
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ProfileEnd",
- Primitive.UnpackEndCut(profileEnd),
- "float");
-
- ushort profileHollow = Utils.BytesToUInt16(block, i);
- i += 2;
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ProfileHollow",
- Primitive.UnpackProfileHollow(profileHollow),
- "float");
-
- int textureEntryLength = (int)Utils.BytesToUInt(block, i);
- i += 4;
- //prim.Textures = new Primitive.TextureEntry(block, i, textureEntryLength);
- String s = DecodeTextureEntry("TextureEntry", new Primitive.TextureEntry(block, i, textureEntryLength));
- result.AppendLine(s);
- i += textureEntryLength;
-
- // Texture animation
- if ((flags & CompressedFlags.TextureAnimation) != 0)
- {
- i += 4;
- string a = DecodeObjectTextureAnim("TextureAnimation", new Primitive.TextureAnimation(block, i));
- result.AppendLine(a);
- }
-
- if ((flags & CompressedFlags.HasParticlesNew) != 0)
- {
- Primitive.ParticleSystem p = new Primitive.ParticleSystem(block, i);
- result.AppendLine(DecodeObjectParticleSystem("ParticleSystemNEW", p));
- i += 94;
- if ((p.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.DataGlow) != 0)
- i += 2;
- if ((p.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.DataBlend) != 0)
- i += 2;
- }
-
- return result.ToString();
- }
-
- private static string DecodeObjectData(string fieldName, object fieldData)
- {
- byte[] data = (byte[])fieldData;
- if (data.Length == 1)
- {
- return String.Format("{0,30}: {1,2} {2,-38} [{3}]",
- fieldName + " (Tree Species)",
- fieldData,
- //"(" + (Tree)(byte)fieldData + ")",
- "(" + (Tree)data[0] + ")",
- fieldData.GetType().Name);
- }
- else if (data.Length == 76)
- {
- /* TODO: these are likely useful packed fields,
- * need to unpack them */
- Vector4 col = Vector4.Zero;
- Vector3 offset = Vector3.Zero;
- Vector3 vel = Vector3.Zero;
- Vector3 acc = Vector3.Zero;
- Quaternion q = Quaternion.Identity;
- Vector3 angvel = Vector3.Zero;
-
- col.FromBytes(data, 0);
- offset.FromBytes(data, 16);
- vel.FromBytes(data, 28);
- acc.FromBytes(data, 40);
- q.FromBytes(data, 52, true);
- angvel.FromBytes(data, 64);
-
- StringBuilder result = new StringBuilder();
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "ColisionPlane",
- col,
- "Vector4");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Offset",
- offset,
- "Vector3");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Velocity",
- vel,
- "Vector3");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Acceleration",
- acc,
- "Vector3");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "rotation",
- q,
- "Quaternion");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Omega",
- angvel,
- "Vector3");
- return result.ToString();
- }
- else if (data.Length == 60)
- {
- /* TODO: these are likely useful packed fields,
- * need to unpack them */
- Vector3 offset = Vector3.Zero;
- Vector3 vel = Vector3.Zero;
- Vector3 acc = Vector3.Zero;
- Quaternion q = Quaternion.Identity;
- Vector3 angvel = Vector3.Zero;
-
- offset.FromBytes(data, 0);
- vel.FromBytes(data, 12);
- acc.FromBytes(data, 24);
- q.FromBytes(data, 36, true);
- angvel.FromBytes(data, 48);
-
- StringBuilder result = new StringBuilder();
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Offset",
- offset,
- "Vector3");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Velocity",
- vel,
- "Vector3");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Acceleration",
- acc,
- "Vector3");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "rotation",
- q,
- "Quaternion");
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- "Omega",
- angvel,
- "Vector3");
- return result.ToString();
- }
- else
- {
- return Utils.BytesToHexString((byte[])fieldData, String.Format("{0,30}", fieldName));
- }
- }
-
- private static string DecodeObjectTextureAnim(string fieldName, object fieldData)
- {
- StringBuilder result = new StringBuilder();
- Primitive.TextureAnimation TextureAnim;
- if (fieldData is Primitive.TextureAnimation)
- TextureAnim = (Primitive.TextureAnimation)fieldData;
- else
- TextureAnim = new Primitive.TextureAnimation((byte[])fieldData, 0);
-
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- GenericTypeDecoder(TextureAnim, ref result);
- result.AppendFormat("{0,30}", "");
-
- return result.ToString();
- }
-
- private static string DecodeEstateParameter(string fieldName, object fieldData)
- {
- byte[] bytes = (byte[])fieldData;
-
- if (bytes.Length == 17)
- {
- return String.Format("{0,30}: {1,-40} [UUID]", fieldName, new UUID((byte[])fieldData, 0));
- }
- else
- {
- return String.Format("{0,30}: {1,-40} [Byte[]]", fieldName, Utils.BytesToString((byte[])fieldData));
- }
- }
-
- private static string DecodeNameValue(string fieldName, object fieldData)
- {
- NameValue[] nameValues = null;
- if (fieldData is NameValue[])
- nameValues = fieldData as NameValue[];
- else
- {
- string nameValue = Utils.BytesToString((byte[])fieldData);
- if (nameValue.Length > 0)
- {
- string[] lines = nameValue.Split('\n');
- nameValues = new NameValue[lines.Length];
-
- for (int i = 0; i < lines.Length; i++)
- {
- if (!String.IsNullOrEmpty(lines[i]))
- {
- NameValue nv = new NameValue(lines[i]);
- nameValues[i] = nv;
- }
- }
- }
- }
- StringBuilder result = new StringBuilder();
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- if (nameValues != null)
- {
- for (int i = 0; i < nameValues.Length; i++)
- {
- result.AppendFormat(
- "{0,30}: Name={1} Value={2} Class={3} Type={4} Sendto={5}" + Environment.NewLine, "NameValue",
- nameValues[i].Name, nameValues[i].Value, nameValues[i].Class, nameValues[i].Type, nameValues[i].Sendto);
- }
- }
- result.AppendFormat("{0,30}", "");
- return result.ToString();
- }
-
- private static string DecodeObjectExtraParams(string fieldName, object fieldData)
- {
-
- byte[] data = (byte[])fieldData;
-
- int i = 0;
- //int totalLength = 1;
-
- Primitive.FlexibleData Flexible = null;
- Primitive.LightData Light = null;
- Primitive.SculptData Sculpt = null;
- Primitive.SculptData Mesh = null;
- uint meshFlags = 0;
- bool hasmeshFlags = false;
-
- 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 Primitive.FlexibleData(data, i);
- else if (type == ExtraParamType.Light)
- Light = new Primitive.LightData(data, i);
- else if (type == ExtraParamType.Sculpt)
- Sculpt = new Primitive.SculptData(data, i);
- else if (type == ExtraParamType.Mesh)
- Mesh = new Primitive.SculptData(data, i);
- else if ((byte)type == 0x70)
- {
- hasmeshFlags = true;
- meshFlags = Utils.BytesToUInt(data, i);
- }
- i += (int)paramLength;
- //totalLength += (int)paramLength + 6;
- }
-
- StringBuilder result = new StringBuilder();
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- if (Flexible != null)
- {
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- GenericTypeDecoder(Flexible, ref result);
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- }
-
- if (Sculpt != null)
- {
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- GenericTypeDecoder(Sculpt, ref result);
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- }
-
- if (Mesh != null)
- {
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- GenericTypeDecoder(Mesh, ref result);
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- }
-
- if (Light != null)
- {
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- GenericTypeDecoder(Light, ref result);
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- }
-
- if (hasmeshFlags)
- {
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- result.AppendFormat("{0,30}", meshFlags.ToString() + Environment.NewLine);
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- }
-
- result.AppendFormat("{0,30}", "");
- return result.ToString();
- }
-
- private static string DecodeObjectParticleSystem(string fieldName, object fieldData)
- {
- StringBuilder result = new StringBuilder();
- Primitive.ParticleSystem ParticleSys;
- if (fieldData is Primitive.ParticleSystem)
- ParticleSys = (Primitive.ParticleSystem)fieldData;
- else
- ParticleSys = new Primitive.ParticleSystem((byte[])fieldData, 0);
-
- result.AppendFormat("{0,30}", "" + Environment.NewLine);
- GenericTypeDecoder(ParticleSys, ref result);
- result.AppendFormat("{0,30}", "");
-
- return result.ToString();
- }
-
- private static void GenericTypeDecoder(object obj, ref StringBuilder result)
- {
- FieldInfo[] fields = obj.GetType().GetFields();
-
- foreach (FieldInfo field in fields)
- {
- String special;
- if (SpecialDecoder("a" + "." + "b" + "." + field.Name,
- field.GetValue(obj), out special))
- {
- result.AppendLine(special);
- }
- else
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- field.Name,
- field.GetValue(obj),
- field.FieldType.Name);
- }
- }
- }
-
- private static string DecodeObjectPCode(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [PCode]",
- fieldName,
- fieldData,
- "(" + (PCode)(byte)fieldData + ")");
- }
-
- private static string DecodeImageType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [ImageType]",
- fieldName,
- fieldData,
- "(" + (ImageType)(byte)fieldData + ")");
- }
-
- private static string DecodeImageCodec(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [ImageCodec]",
- fieldName,
- fieldData,
- "(" + (ImageCodec)(byte)fieldData + ")");
- }
-
- private static string DecodeObjectMaterial(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [Material]",
- fieldName,
- fieldData,
- "(" + (Material)(byte)fieldData + ")");
- }
-
- private static string DecodeObjectClickAction(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [ClickAction]",
- fieldName,
- fieldData,
- "(" + (ClickAction)(byte)fieldData + ")");
- }
-
- private static string DecodeEventFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [EventFlags]",
- fieldName,
- fieldData,
- "(" + (DirectoryManager.EventFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeDirQueryFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [DirectoryManager.DirFindFlags]",
- fieldName,
- fieldData,
- "(" + (DirectoryManager.DirFindFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeDirClassifiedQueryFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [ClassifiedQueryFlags]",
- fieldName,
- fieldData,
- "(" + (DirectoryManager.ClassifiedQueryFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeDirClassifiedFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [ClassifiedFlags]",
- fieldName,
- fieldData,
- "(" + (DirectoryManager.ClassifiedFlags)(byte)fieldData + ")");
- }
-
- private static string DecodeGroupPowers(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-20} {2,-19} [GroupPowers]",
- fieldName,
- fieldData,
- "(" + (GroupPowers)(ulong)fieldData + ")");
- }
-
- private static string DecodeParcelACL(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [AccessList]",
- fieldName,
- fieldData,
- "(" + (AccessList)(uint)fieldData + ")");
- }
-
- private static string SearchTypeFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [DirectoryManager.SearchTypeFlags]",
- fieldName,
- fieldData,
- "(" + (DirectoryManager.SearchTypeFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeCategory(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-3} {2,-36} [ParcelCategory]",
- fieldName,
- fieldData,
- "(" + fieldData + ")");
- }
-
- private static string DecodeObjectUpdateFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [PrimFlags]",
- fieldName,
- fieldData,
- "(" + (PrimFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeTeleportFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [TeleportFlags]",
- fieldName,
- fieldData,
- "(" + (TeleportFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeScriptControls(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [AgentManager.ControlFlags]",
- fieldName,
- (uint)fieldData,
- "(" + (AgentManager.ControlFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeColorField(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-40} [Color4]",
- fieldName,
- fieldData.GetType().Name.Equals("Color4") ? (Color4)fieldData : new Color4((byte[])fieldData, 0, false));
- }
-
- private static string DecodeTimeStamp(string fieldName, object fieldData)
- {
- if (fieldData is Int32 && (int)fieldData > 0)
- return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
- fieldName,
- fieldData,
- "(" + Utils.UnixTimeToDateTime((int)fieldData) + ")",
- fieldData.GetType().Name);
- else if (fieldData is uint && (uint)fieldData > 0)
- return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
- fieldName,
- fieldData,
- "(" + Utils.UnixTimeToDateTime((uint)fieldData) + ")",
- fieldData.GetType().Name);
- else
- return String.Format("{0,30}: {1,-40} [{2}]",
- fieldName,
- fieldData,
- fieldData.GetType().Name);
- }
-
- private static string DecodeBinaryBucket(string fieldName, object fieldData)
- {
- byte[] bytes = (byte[])fieldData;
- string bucket = String.Empty;
- if (bytes.Length == 1)
- {
- bucket = String.Format("{0}", bytes[0]);
- }
- else if (bytes.Length == 17)
- {
- bucket = String.Format("{0,-36} {1} ({2})",
- new UUID(bytes, 1),
- bytes[0],
- (AssetType)(sbyte)bytes[0]);
- }
- else if (bytes.Length == 16) // the folder ID for the asset to be stored into if we accept an inventory offer
- {
- bucket = new UUID(bytes, 0).ToString();
- }
- else
- {
- bucket = Utils.BytesToString(bytes); // we'll try a string lastly
- }
-
- return String.Format("{0,30}: {1,-40} [Byte[{2}]]", fieldName, bucket, bytes.Length);
- }
-
- private static string DecodeBinaryToHexString(string fieldName, object fieldData)
- {
- return String.Format("{0,30}",
- Utils.BytesToHexString((byte[])fieldData,
- String.Format("{0,30}", fieldName)));
- }
-
- private static string DecodeWearableType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [WearableType]",
- fieldName,
- (byte)fieldData,
- "(" + (WearableType)fieldData + ")");
- }
-
- private static string DecodeInventoryType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [AssetType]",
- fieldName,
- (sbyte)fieldData,
- "(" + (AssetType)(sbyte)fieldData + ")");
- }
-
- private static string DecodeInventorySort(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [InventorySortOrder]",
- fieldName,
- fieldData,
- "(" + (InventorySortOrder)(int)fieldData + ")");
- }
-
- private static string DecodeInventoryInvType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [InventoryType]",
- fieldName,
- (sbyte)fieldData,
- "(" + (InventoryType)fieldData + ")");
- }
-
- private static string DecodeFolderType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [Folderype]",
- fieldName,
- (sbyte)fieldData,
- "(" + (FolderType)fieldData + ")");
- }
-
- private static string DecodeInventoryFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [InventoryItemFlags]",
- fieldName,
- (uint)fieldData,
- "(" + (InventoryItemFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeObjectSaleType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [SaleType]",
- fieldName,
- (byte)fieldData,
- "(" + (SaleType)fieldData + ")");
- }
-
- private static string DecodeRegionFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [RegionFlags]",
- fieldName,
- fieldData,
- "(" + (RegionFlags)(uint)fieldData + ")");
- }
-
- private static string DecodeTransferParams(string fieldName, object fieldData)
- {
- byte[] paramData = (byte[])fieldData;
- StringBuilder result = new StringBuilder();
- result.AppendLine(" ");
- if (paramData.Length == 20)
- {
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "AssetID",
- new UUID(paramData, 0));
-
- result.AppendFormat("{0,30}: {1,-2} {2,-37} [AssetType]" + Environment.NewLine,
- "AssetType",
- (sbyte)paramData[16],
- "(" + (AssetType)(sbyte)paramData[16] + ")");
-
- }
- else if (paramData.Length == 100)
- {
- //UUID agentID = new UUID(info.TransferInfo.Params, 0);
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "AgentID",
- new UUID(paramData, 0));
-
- //UUID sessionID = new UUID(info.TransferInfo.Params, 16);
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "SessionID",
- new UUID(paramData, 16));
- //UUID ownerID = new UUID(info.TransferInfo.Params, 32);
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "OwnerID",
- new UUID(paramData, 32));
- //UUID taskID = new UUID(info.TransferInfo.Params, 48);
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "TaskID",
- new UUID(paramData, 48));
- //UUID itemID = new UUID(info.TransferInfo.Params, 64);
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "ItemID",
- new UUID(paramData, 64));
-
- result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
- "AssetID",
- new UUID(paramData, 80));
-
- result.AppendFormat("{0,30}: {1,-2} {2,-37} [AssetType]" + Environment.NewLine,
- "AssetType",
- (sbyte)paramData[96],
- "(" + (AssetType)(sbyte)paramData[96] + ")");
- }
- else
- {
- Console.WriteLine("Oh Poop!");
- }
-
- result.Append("");
-
- return result.ToString();
- }
-
- private static string DecodeTransferChannelType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [ChannelType]",
- fieldName,
- fieldData,
- "(" + (ChannelType)(int)fieldData + ")");
- }
-
- private static string DecodeTransferSourceType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [SourceType]",
- fieldName,
- fieldData,
- "(" + (SourceType)(int)fieldData + ")");
- }
-
- private static string DecodeTransferTargetType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [TargetType]",
- fieldName,
- fieldData,
- "(" + (TargetType)(int)fieldData + ")");
- }
-
- private static string DecodeMapRequestFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [GridLayerType]",
- fieldName,
- fieldData,
- "(" + (GridLayerType)(uint)fieldData + ")");
- }
-
- private static string DecodeGridItemType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [GridItemType]",
- fieldName,
- fieldData,
- "(" + (GridItemType)(uint)fieldData + ")");
-
- }
-
- private static string DecodeLayerDataType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [LayerType]",
- fieldName,
- fieldData,
- "(" + (TerrainPatch.LayerType)(byte)fieldData + ")");
- }
-
- private static string DecodeMapAccess(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [SimAccess]",
- fieldName,
- fieldData,
- "(" + (SimAccess)(byte)fieldData + ")");
- }
-
- private static string DecodeSimAccess(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [SimAccess]",
- fieldName,
- (byte)fieldData,
- "(" + (SimAccess)fieldData + ")");
- }
-
- private static string DecodeAttachedSoundFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [SoundFlags]",
- fieldName,
- (byte)fieldData,
- "(" + (SoundFlags)fieldData + ")");
- }
-
-
- private static string DecodeChatSourceType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [SourceType]",
- fieldName,
- fieldData,
- "(" + (SourceType)(byte)fieldData + ")");
- }
-
- private static string DecodeChatChatType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [ChatType]",
- fieldName,
- (byte)fieldData,
- "(" + (ChatType)fieldData + ")");
- }
-
- private static string DecodeChatAudible(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [ChatAudibleLevel]",
- fieldName,
- (byte)fieldData,
- "(" + (ChatAudibleLevel)(byte)fieldData + ")");
- }
-
- private static string DecodeImageData(string fieldName, object fieldData)
- {
- return String.Format("{0,10}",
- Utils.BytesToHexString((byte[])fieldData,
- String.Format("{0,30}", fieldName)));
- }
-
- private static string DecodeTerseTextureEntry(string fieldName, object fieldData)
- {
- byte[] block = (byte[])fieldData;
-
- Primitive.TextureEntry te = new Primitive.TextureEntry(block, 4, block.Length - 4);
-
- StringBuilder result = new StringBuilder();
-
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- if (te.DefaultTexture != null)
- {
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- GenericFieldsDecoder(te.DefaultTexture, ref result);
- GenericPropertiesDecoder(te.DefaultTexture, ref result);
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- }
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- for (int i = 0; i < te.FaceTextures.Length; i++)
- {
- if (te.FaceTextures[i] != null)
- {
- result.AppendFormat("{0,30}[{1}]" + Environment.NewLine, "FaceTexture", i);
- GenericFieldsDecoder(te.FaceTextures[i], ref result);
- GenericPropertiesDecoder(te.FaceTextures[i], ref result);
- }
- }
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- result.AppendFormat("{0,30}", "");
-
- return result.ToString();
- }
-
- private static string DecodeTextureEntry(string fieldName, object fieldData)
- {
- Primitive.TextureEntry te;
- if (fieldData is Primitive.TextureEntry)
- te = (Primitive.TextureEntry)fieldData;
- else
- {
- byte[] tebytes = (byte[])fieldData;
- te = new Primitive.TextureEntry(tebytes, 0, tebytes.Length);
- }
-
- StringBuilder result = new StringBuilder();
-
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- if (te.DefaultTexture != null)
- {
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- GenericFieldsDecoder(te.DefaultTexture, ref result);
- GenericPropertiesDecoder(te.DefaultTexture, ref result);
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- }
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- for (int i = 0; i < te.FaceTextures.Length; i++)
- {
- if (te.FaceTextures[i] != null)
- {
- result.AppendFormat("{0,30}[{1}]" + Environment.NewLine, "FaceTexture", i);
- GenericFieldsDecoder(te.FaceTextures[i], ref result);
- GenericPropertiesDecoder(te.FaceTextures[i], ref result);
- }
- }
- result.AppendFormat("{0,30}", " " + Environment.NewLine);
- result.AppendFormat("{0,30}", "");
-
- return result.ToString();
- }
-
- private static void GenericFieldsDecoder(object obj, ref StringBuilder result)
- {
- Type parcelType = obj.GetType();
- FieldInfo[] fields = parcelType.GetFields();
- foreach (FieldInfo field in fields)
- {
- String special;
- if (SpecialDecoder("a" + "." + "b" + "." + field.Name,
- field.GetValue(obj), out special))
- {
- result.AppendLine(special);
- }
- else
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- field.Name,
- field.GetValue(obj),
- field.FieldType.Name);
- }
- }
- }
-
- private static void GenericPropertiesDecoder(object obj, ref StringBuilder result)
- {
- Type parcelType = obj.GetType();
- PropertyInfo[] propertyInfos = parcelType.GetProperties();
- foreach (PropertyInfo property in propertyInfos)
- {
- String special;
- if (SpecialDecoder("a" + "." + "b" + "." + property.Name,
- property.GetValue(obj, null), out special))
- {
- result.AppendLine(special);
- }
- else
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- property.Name,
- property.GetValue(obj, null),
- property.PropertyType.Name);
- }
- }
- }
-
- private static string DecodeDialog(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [{3}]",
- fieldName,
- (byte)fieldData,
- "(" + (InstantMessageDialog)fieldData + ")",
- fieldData.GetType().Name);
- }
-
- private static string DecodeControlFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
- fieldName,
- fieldData,
- "(" + (AgentManager.ControlFlags)(uint)fieldData + ")",
- fieldData.GetType().Name);
- }
-
- private static string DecodePermissionMask(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
- fieldName,
- (uint)fieldData,
- "(" + (PermissionMask)fieldData + ")",
- fieldData.GetType().Name);
- }
-
- private static string DecodeViewerEffectTypeData(string fieldName, object fieldData)
- {
- byte[] data = (byte[])fieldData;
- StringBuilder sb = new StringBuilder();
- if (data.Length == 56 || data.Length == 57)
- {
- UUID sourceAvatar = new UUID(data, 0);
- UUID targetObject = new UUID(data, 16);
- Vector3d targetPos = new Vector3d(data, 32);
- sb.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine, fieldName, "Source AvatarID=" + sourceAvatar);
- sb.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine, fieldName, "Target ObjectID=" + targetObject);
-
-
- float lx, ly;
- Helpers.GlobalPosToRegionHandle((float)targetPos.X, (float)targetPos.Y, out lx, out ly);
-
- sb.AppendFormat("{0,30}: {1,-40} [Vector3d]", fieldName, targetPos);
-
- if (data.Length == 57)
- {
- sb.AppendLine();
- sb.AppendFormat("{0,30}: {1,-17} {2,-22} [Byte]", fieldName, "Point At Type=" + data[56],
- "(" + (PointAtType)data[56] + ")");
- }
-
- return sb.ToString();
- }
- else
- {
- return String.Format("{0,30}: (No Decoder) Length={1}" + Environment.NewLine, fieldName, data.Length) + Utils.BytesToHexString(data, String.Format("{0,30}", ""));
- }
- }
-
- private static string DecodeAgentState(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [AgentState]",
- fieldName,
- fieldData,
- "(" + (AgentState)(byte)fieldData + ")");
- }
-
- private static string DecodeAgentFlags(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [AgentFlags]",
- fieldName,
- fieldData,
- "(" + (AgentFlags)(byte)fieldData + ")");
- }
-
- private static string DecodeObjectState(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [AttachmentPoint]",
- fieldName,
- fieldData,
- "(" + (AttachmentPoint)(byte)fieldData + ")");
- }
-
- private static string DecodeViewerEffectType(string fieldName, object fieldData)
- {
- return String.Format("{0,30}: {1,-2} {2,-37} [{3}]",
- fieldName,
- fieldData,
- "(" + (EffectType)(byte)fieldData + ")",
- fieldData.GetType().Name);
- }
-
- private static string DecodeAnimToConst(string fieldName, object fieldData)
- {
- string animConst = "UUID";
- Dictionary animsDict = Animations.ToDictionary();
- if (animsDict.ContainsKey((UUID)fieldData))
- animConst = animsDict[(UUID)fieldData];
- return String.Format("{0,30}: {1,-40} [{2}]",
- fieldName,
- fieldData,
- animConst);
- }
- #endregion
-
- ///
- /// Creates a formatted string containing the values of a Packet
- ///
- /// The Packet
- /// A formatted string of values of the nested items in the Packet object
- public static string PacketToString(Packet packet)
- {
- StringBuilder result = new StringBuilder();
-
- result.AppendFormat("Packet Type: {0}" + Environment.NewLine, packet.Type);
- result.AppendLine("[Packet Header]");
- // payload
- result.AppendFormat("Sequence: {0}" + Environment.NewLine, packet.Header.Sequence);
- result.AppendFormat(" Options: {0}" + Environment.NewLine, InterpretOptions(packet.Header));
- result.AppendLine();
-
- result.AppendLine("[Packet Payload]");
-
- FieldInfo[] fields = packet.GetType().GetFields();
-
- for (int i = 0; i < fields.Length; i++)
- {
- // we're not interested in any of these here
- if (fields[i].Name == "Type" || fields[i].Name == "Header" || fields[i].Name == "HasVariableBlocks")
- continue;
-
- if (fields[i].FieldType.IsArray)
- {
- result.AppendFormat("{0,30} []" + Environment.NewLine, "-- " + fields[i].Name + " --");
- RecursePacketArray(fields[i], packet, ref result);
- }
- else
- {
- result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + fields[i].Name + " --");
- RecursePacketField(fields[i], packet, ref result);
- }
- }
- return result.ToString();
- }
-
- public static string InterpretOptions(Header header)
- {
- return "["
- + (header.AppendedAcks ? "Ack" : " ")
- + " "
- + (header.Resent ? "Res" : " ")
- + " "
- + (header.Reliable ? "Rel" : " ")
- + " "
- + (header.Zerocoded ? "Zer" : " ")
- + "]"
- ;
- }
-
- private static void RecursePacketArray(FieldInfo fieldInfo, object packet, ref StringBuilder result)
- {
- var packetDataObject = fieldInfo.GetValue(packet);
- int k = -1;
- foreach (object nestedArrayRecord in packetDataObject as Array)
- {
- FieldInfo[] fields = nestedArrayRecord.GetType().GetFields();
- ++k;
- for (int i = 0; i < fields.Length; i++)
- {
- String special;
- if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + fields[i].Name,
- fields[i].GetValue(nestedArrayRecord), out special))
- {
- result.AppendLine(special);
- }
- else if (fields[i].FieldType.IsArray) // default for an array (probably a byte[])
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- fields[i].Name + "[" + k.ToString() + "]",
- Utils.BytesToString((byte[])fields[i].GetValue(nestedArrayRecord)),
- /*fields[i].GetValue(nestedArrayRecord).GetType().Name*/ "String");
- }
- else // default for a field
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- fields[i].Name + "[" + k.ToString() + "]",
- fields[i].GetValue(nestedArrayRecord),
- fields[i].GetValue(nestedArrayRecord).GetType().Name);
- }
- }
-
- // Handle Properties
- foreach (PropertyInfo propertyInfo in nestedArrayRecord.GetType().GetProperties())
- {
- if (propertyInfo.Name.Equals("Length"))
- continue;
-
- string special;
- if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + propertyInfo.Name,
- propertyInfo.GetValue(nestedArrayRecord, null),
- out special))
- {
- result.AppendLine(special);
- }
- else
- {
- var p = propertyInfo.GetValue(nestedArrayRecord, null);
- /* Leave the c for now at the end, it signifies something useful that still needs to be done i.e. a decoder written */
- result.AppendFormat("{0, 30}: {1,-40} [{2}]c" + Environment.NewLine,
- propertyInfo.Name,
- Utils.BytesToString((byte[])propertyInfo.GetValue(nestedArrayRecord, null)),
- propertyInfo.PropertyType.Name);
- }
- }
- result.AppendFormat("{0,32}" + Environment.NewLine, "***");
- }
- }
-
- private static void RecursePacketField(FieldInfo fieldInfo, object packet, ref StringBuilder result)
- {
- object packetDataObject = fieldInfo.GetValue(packet);
-
- // handle Fields
- foreach (FieldInfo packetValueField in fieldInfo.GetValue(packet).GetType().GetFields())
- {
- string special;
- if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + packetValueField.Name,
- packetValueField.GetValue(packetDataObject),
- out special))
- {
- result.AppendLine(special);
- }
- else if (packetValueField.FieldType.IsArray)
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- packetValueField.Name,
- Utils.BytesToString((byte[])packetValueField.GetValue(packetDataObject)),
- /*packetValueField.FieldType.Name*/ "String");
- }
- else
- {
- result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
- packetValueField.Name, packetValueField.GetValue(packetDataObject), packetValueField.FieldType.Name);
-
- }
- }
-
- // Handle Properties
- foreach (PropertyInfo propertyInfo in packetDataObject.GetType().GetProperties())
- {
- if (propertyInfo.Name.Equals("Length"))
- continue;
-
- string special;
- if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + propertyInfo.Name,
- propertyInfo.GetValue(packetDataObject, null),
- out special))
- {
- result.AppendLine(special);
- }
- else if (propertyInfo.GetValue(packetDataObject, null).GetType() == typeof(byte[]))
- {
- result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
- propertyInfo.Name,
- Utils.BytesToString((byte[])propertyInfo.GetValue(packetDataObject, null)),
- propertyInfo.PropertyType.Name);
- }
- else
- {
- result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
- propertyInfo.Name,
- propertyInfo.GetValue(packetDataObject, null),
- propertyInfo.PropertyType.Name);
- }
- }
- }
-
- private static bool SpecialDecoder(string decoderKey, object fieldData, out string result)
- {
- result = string.Empty;
- string[] keys = decoderKey.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
- string[] keyList = { decoderKey, decoderKey.Replace("Packet", ""), keys[1] + "." + keys[2], keys[2] };
- foreach (string key in keyList)
- {
-
- bool ok = true;
- if (fieldData is byte[])
- {
- byte[] fd = (byte[])fieldData;
- ok = fd.Length > 0;
- if (!ok)
- {
- // bypass the decoder since we were passed an empty byte array
- result = String.Format("{0,30}:", keys[2]);
- return true;
- }
- }
-
- if (ok && Callbacks.ContainsKey(key)) // fieldname e.g: Plane
- {
- foreach (CustomPacketDecoder decoder in Callbacks[key])
- result = decoder(keys[2], fieldData);
- return true;
- }
- }
- return false;
- }
-
- ///
- /// Decode an IMessage object into a beautifully formatted string
- ///
- /// The IMessage object
- /// Recursion level (used for indenting)
- /// A formatted string containing the names and values of the source object
- public static string MessageToString(object message, int recurseLevel)
- {
- if (message == null)
- return String.Empty;
-
- StringBuilder result = new StringBuilder();
- // common/custom types
- if (recurseLevel <= 0)
- {
- result.AppendFormat("Message Type: {0}" + Environment.NewLine, message.GetType().Name);
- }
- else
- {
- string pad = " +--".PadLeft(recurseLevel + 3);
- result.AppendFormat("{0} {1}" + Environment.NewLine, pad, message.GetType().Name);
- }
-
- recurseLevel++;
-
- foreach (FieldInfo messageField in message.GetType().GetFields())
- {
- // an abstract message class
- if (messageField.FieldType.IsAbstract)
- {
- result.AppendLine(MessageToString(messageField.GetValue(message), recurseLevel));
- }
- // a byte array
- else if (messageField.GetValue(message) != null && messageField.GetValue(message).GetType() == typeof(Byte[]))
- {
- result.AppendFormat("{0, 30}:" + Environment.NewLine, messageField.Name);
-
- result.AppendFormat("{0}" + Environment.NewLine,
- Utils.BytesToHexString((byte[])messageField.GetValue(message),
- String.Format("{0,30}", "")));
- }
-
- // an array of class objects
- else if (messageField.FieldType.IsArray)
- {
- var messageObjectData = messageField.GetValue(message);
- result.AppendFormat("-- {0} --" + Environment.NewLine, messageField.FieldType.Name);
- foreach (object nestedArrayObject in messageObjectData as Array)
- {
- if (nestedArrayObject == null)
- {
- result.AppendFormat("{0,30}" + Environment.NewLine, "-- null --");
- continue;
- }
- else
- {
- result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + nestedArrayObject.GetType().Name + " --");
- }
- foreach (FieldInfo nestedField in nestedArrayObject.GetType().GetFields())
- {
- if (nestedField.FieldType.IsEnum)
- {
- result.AppendFormat("{0,30}: {1,-10} {2,-29} [{3}]" + Environment.NewLine,
- nestedField.Name,
- Enum.Format(nestedField.GetValue(nestedArrayObject).GetType(),
- nestedField.GetValue(nestedArrayObject), "D"),
- "(" + nestedField.GetValue(nestedArrayObject) + ")",
- nestedField.GetValue(nestedArrayObject).GetType().Name);
- }
- else if (nestedField.FieldType.IsInterface)
- {
- result.AppendLine(MessageToString(nestedField.GetValue(nestedArrayObject), recurseLevel));
- }
- else
- {
- result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
- nestedField.Name,
- nestedField.GetValue(nestedArrayObject),
- nestedField.FieldType.Name);
- }
- }
- }
- }
- else
- {
- if (messageField.FieldType.IsEnum)
- {
- result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
- messageField.Name,
- Enum.Format(messageField.GetValue(message).GetType(),
- messageField.GetValue(message), "D"),
- "(" + messageField.GetValue(message) + ")",
- messageField.FieldType.Name);
- }
- else if (messageField.FieldType.IsInterface)
- {
- result.AppendLine(MessageToString(messageField.GetValue(message), recurseLevel));
- }
- else
- {
- result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
- messageField.Name, messageField.GetValue(message), messageField.FieldType.Name);
- }
- }
- }
-
- return result.ToString();
- }
- }
-}
+/*
+ * Copyright (c) 2006-2016, openmetaverse.co
+ * 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.co 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 System.Reflection;
+using System.Text;
+
+namespace OpenMetaverse.Packets
+{
+
+ public static class PacketDecoder
+ {
+ ///
+ /// A custom decoder callback
+ ///
+ /// The key of the object
+ /// the data to decode
+ /// A string represending the fieldData
+ public delegate string CustomPacketDecoder(string fieldName, object fieldData);
+
+ private static Dictionary> Callbacks = new Dictionary>();
+
+
+ static PacketDecoder()
+ {
+ AddCallback("Color", DecodeColorField);
+ AddCallback("TextColor", DecodeColorField);
+ AddCallback("Timestamp", DecodeTimeStamp);
+ AddCallback("EstateCovenantReply.Data.CovenantTimestamp", DecodeTimeStamp);
+ AddCallback("CreationDate", DecodeTimeStamp);
+ AddCallback("BinaryBucket", DecodeBinaryBucket);
+ AddCallback("ParcelData.Data", DecodeBinaryToHexString);
+ AddCallback("LayerData.Data", DecodeBinaryToHexString);
+ AddCallback("ImageData.Data", DecodeImageData);
+ AddCallback("TransferData.Data", DecodeBinaryToHexString);
+ AddCallback("ObjectData.TextureEntry", DecodeTextureEntry);
+ AddCallback("ImprovedInstantMessage.MessageBlock.Dialog", DecodeDialog);
+
+ // Inventory/Permissions
+ AddCallback("BaseMask", DecodePermissionMask);
+ AddCallback("OwnerMask", DecodePermissionMask);
+ AddCallback("EveryoneMask", DecodePermissionMask);
+ AddCallback("NextOwnerMask", DecodePermissionMask);
+ AddCallback("GroupMask", DecodePermissionMask);
+
+ // FetchInventoryDescendents
+ AddCallback("InventoryData.SortOrder", DecodeInventorySort);
+
+ AddCallback("WearableType", DecodeWearableType);
+ //
+ AddCallback("InventoryData.Type", DecodeInventoryType);
+ AddCallback("InvType", DecodeInventoryInvType);
+ AddCallback("InventoryData.Flags", DecodeInventoryFlags);
+ // BulkUpdateInventory
+ AddCallback("ItemData.Type", DecodeInventoryType);
+ AddCallback("ItemData.Flags", DecodeInventoryFlags);
+
+ AddCallback("SaleType", DecodeObjectSaleType);
+
+ AddCallback("ScriptControlChange.Data.Controls", DecodeScriptControls);
+
+ AddCallback("RegionFlags", DecodeRegionFlags);
+ AddCallback("SimAccess", DecodeSimAccess);
+ AddCallback("ControlFlags", DecodeControlFlags);
+
+ // AgentUpdate
+ AddCallback("AgentUpdate.AgentData.State", DecodeAgentState);
+ AddCallback("AgentUpdate.AgentData.Flags", DecodeAgentFlags);
+
+ // ViewerEffect TypeData
+ AddCallback("ViewerEffect.Effect.TypeData", DecodeViewerEffectTypeData);
+ AddCallback("ViewerEffect.Effect.Type", DecodeViewerEffectType);
+
+ // Prim/ObjectUpdate decoders
+ AddCallback("ObjectUpdate.ObjectData.PCode", DecodeObjectPCode);
+ AddCallback("ObjectUpdate.ObjectData.Material", DecodeObjectMaterial);
+ AddCallback("ObjectUpdate.ObjectData.ClickAction", DecodeObjectClickAction);
+ AddCallback("ObjectData.UpdateFlags", DecodeObjectUpdateFlags);
+
+ AddCallback("ObjectUpdate.ObjectData.ObjectData", DecodeObjectData);
+ AddCallback("TextureAnim", DecodeObjectTextureAnim);
+ AddCallback("ObjectUpdate.ObjectData.NameValue", DecodeNameValue);
+ AddCallback("ObjectUpdate.ObjectData.Data", DecodeObjectData);
+
+ AddCallback("ObjectUpdate.ObjectData.PSBlock", DecodeObjectParticleSystem);
+ AddCallback("ParticleSys", DecodeObjectParticleSystem);
+ AddCallback("ObjectUpdate.ObjectData.ExtraParams", DecodeObjectExtraParams);
+
+ AddCallback("ImprovedTerseObjectUpdate.ObjectData.Data", DecodeTerseUpdate);
+ AddCallback("ImprovedTerseObjectUpdate.ObjectData.TextureEntry", DecodeTerseTextureEntry);
+
+ AddCallback("ObjectUpdateCompressed.ObjectData.Data", DecodeObjectCompressedData);
+
+ // ImprovedTerseObjectUpdate & ObjectUpdate AttachmentPoint & ObjectUpdateCompressed
+ AddCallback("ObjectData.State", DecodeObjectState);
+ //AddCallback("ObjectUpdateCompressed.ObjectData.State", DecodeObjectState);
+ //AddCallback("ImprovedTerseObjectUpdate.ObjectData.State", DecodeObjectState);
+
+
+ // ChatFromSimulator
+ AddCallback("ChatData.SourceType", DecodeChatSourceType);
+ AddCallback("ChatData.ChatType", DecodeChatChatType);
+ AddCallback("ChatData.Audible", DecodeChatAudible);
+ AddCallback("AttachedSound.DataBlock.Flags", DecodeAttachedSoundFlags);
+
+ AddCallback("RequestImage.Type", DecodeImageType);
+
+ AddCallback("EstateOwnerMessage.ParamList.Parameter", DecodeEstateParameter);
+
+ AddCallback("Codec", DecodeImageCodec);
+ AddCallback("Info.TeleportFlags", DecodeTeleportFlags);
+
+ // map
+ AddCallback("MapBlockRequest.AgentData.Flags", DecodeMapRequestFlags);
+ AddCallback("MapItemRequest.AgentData.Flags", DecodeMapRequestFlags);
+ AddCallback("MapBlockReply.Data.Access", DecodeMapAccess);
+ AddCallback("FolderData.Type", DecodeFolderType);
+ AddCallback("RequestData.ItemType", DecodeGridItemType);
+
+ // TransferRequest/TransferInfo
+ AddCallback("TransferInfo.Params", DecodeTransferParams);
+ AddCallback("TransferInfo.ChannelType", DecodeTransferChannelType);
+ AddCallback("TransferInfo.SourceType", DecodeTransferSourceType);
+ AddCallback("TransferInfo.TargetType", DecodeTransferTargetType);
+ AddCallback("TransferData.ChannelType", DecodeTransferChannelType);
+ // SendXferPacket
+ AddCallback("DataPacket.Data", DecodeBinaryToHexString);
+ // Directory Manager
+ AddCallback("DirClassifiedQuery.QueryData.QueryFlags", DecodeDirClassifiedQueryFlags);
+ AddCallback("QueryData.QueryFlags", DecodeDirQueryFlags);
+ AddCallback("Category", DecodeCategory);
+ AddCallback("QueryData.SearchType", SearchTypeFlags);
+
+ AddCallback("ClassifiedFlags", DecodeDirClassifiedFlags);
+ AddCallback("EventFlags", DecodeEventFlags);
+
+ AddCallback("ParcelAccessListRequest.Data.Flags", DecodeParcelACL);
+ AddCallback("ParcelAccessListReply.Data.Flags", DecodeParcelACL);
+ //AddCallback("ParcelAccessListReply.List.Flags", DecodeParcelACLReply);
+
+ // AgentAnimation
+ AddCallback("AnimID", DecodeAnimToConst);
+
+ AddCallback("LayerData.LayerID.Type", DecodeLayerDataType);
+
+ AddCallback("GroupPowers", DecodeGroupPowers);
+ }
+
+ ///
+ /// Add a custom decoder callback
+ ///
+ /// The key of the field to decode
+ /// The custom decode handler
+ public static void AddCallback(string key, CustomPacketDecoder customPacketHandler)
+ {
+ if (Callbacks.ContainsKey(key))
+ {
+ lock (Callbacks)
+ Callbacks[key].Add(customPacketHandler);
+ }
+ else
+ {
+ lock (Callbacks)
+ Callbacks.Add(key, new List() { customPacketHandler });
+ }
+ }
+
+ ///
+ /// Remove a custom decoder callback
+ ///
+ /// The key of the field to decode
+ /// The custom decode handler
+ public static void RemoveCustomHandler(string key, CustomPacketDecoder customPacketHandler)
+ {
+ if (Callbacks.ContainsKey(key))
+ lock (Callbacks)
+ {
+ if (Callbacks[key].Contains(customPacketHandler))
+ Callbacks[key].Remove(customPacketHandler);
+ }
+ }
+
+ #region Custom Decoders
+
+ private static string DecodeTerseUpdate(string fieldName, object fieldData)
+ {
+ byte[] block = (byte[])fieldData;
+ int i = 4;
+
+ StringBuilder result = new StringBuilder();
+
+ // LocalID
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "LocalID",
+ Utils.BytesToUInt(block, 0),
+ "Uint32");
+
+
+
+ // State
+ byte point = block[i++];
+ result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
+ "State",
+ point,
+ "(" + (AttachmentPoint)point + ")",
+ "AttachmentPoint");
+
+ // Avatar boolean
+ bool isAvatar = (block[i++] != 0);
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "IsAvatar",
+ isAvatar,
+ "Boolean");
+
+ // Collision normal for avatar
+ if (isAvatar)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "CollisionPlane",
+ new Vector4(block, i),
+ "Vector4");
+
+ i += 16;
+ }
+
+ // Position
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Position",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+
+ // Velocity
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Velocity",
+ new Vector3(
+ Utils.BytesUInt16ToFloat(block, i, -128.0f, 128.0f),
+ Utils.BytesUInt16ToFloat(block, i + 2, -128.0f, 128.0f),
+ Utils.BytesUInt16ToFloat(block, i + 4, -128.0f, 128.0f)),
+ "Vector3");
+ i += 6;
+
+ // Acceleration
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Acceleration",
+ new Vector3(
+ Utils.BytesUInt16ToFloat(block, i, -64.0f, 64.0f),
+ Utils.BytesUInt16ToFloat(block, i + 2, -64.0f, 64.0f),
+ Utils.BytesUInt16ToFloat(block, i + 4, -64.0f, 64.0f)),
+ "Vector3");
+
+ i += 6;
+ // Rotation (theta)
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Rotation",
+ new Quaternion(
+ Utils.BytesUInt16ToFloat(block, i, -1.0f, 1.0f),
+ Utils.BytesUInt16ToFloat(block, i + 2, -1.0f, 1.0f),
+ Utils.BytesUInt16ToFloat(block, i + 4, -1.0f, 1.0f),
+ Utils.BytesUInt16ToFloat(block, i + 6, -1.0f, 1.0f)),
+ "Quaternion");
+ i += 8;
+ // Angular velocity (omega)
+ result.AppendFormat("{0,30}: {1,-40} [{2}]",
+ "AngularVelocity",
+ new Vector3(
+ Utils.BytesUInt16ToFloat(block, i, -64.0f, 64.0f),
+ Utils.BytesUInt16ToFloat(block, i + 2, -64.0f, 64.0f),
+ Utils.BytesUInt16ToFloat(block, i + 4, -64.0f, 64.0f)),
+ "Vector3");
+ //pos += 6;
+ // TODO: What is in these 6 bytes?
+ return result.ToString();
+ }
+
+ private static string DecodeObjectCompressedData(string fieldName, object fieldData)
+ {
+ StringBuilder result = new StringBuilder();
+ byte[] block = (byte[])fieldData;
+ int i = 0;
+
+ // UUID
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ID",
+ new UUID(block, 0),
+ "UUID");
+ i += 16;
+
+ // Local ID
+ uint LocalID = (uint)(block[i++] + (block[i++] << 8) +
+ (block[i++] << 16) + (block[i++] << 24));
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "LocalID",
+ LocalID,
+ "Uint32");
+ // PCode
+ PCode pcode = (PCode)block[i++];
+
+ result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
+ "PCode",
+ (int)pcode,
+ "(" + pcode + ")",
+ "PCode");
+
+ // State
+ AttachmentPoint point = (AttachmentPoint)block[i++];
+ result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
+ "State",
+ (byte)point,
+ "(" + point + ")",
+ "AttachmentPoint");
+
+ //CRC
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "CRC",
+ Utils.BytesToUInt(block, i),
+ "UInt");
+ i += 4;
+
+ // Material
+ result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
+ "Material",
+ block[i],
+ "(" + (Material)block[i++] + ")",
+ "Material");
+
+ // Click action
+ result.AppendFormat("{0,30}: {1,-3} {2,-36} [{3}]" + Environment.NewLine,
+ "ClickAction",
+ block[i],
+ "(" + (ClickAction)block[i++] + ")",
+ "ClickAction");
+
+ // Scale
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Scale",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+
+ // Position
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Position",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+
+ // Rotation
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Rotation",
+ new Vector3(block, i),
+ "Vector3");
+
+ i += 12;
+ // Compressed flags
+
+ CompressedFlags flags = (CompressedFlags)Utils.BytesToUInt(block, i);
+ result.AppendFormat("{0,30}: {1,-10} {2,-29} [{3}]" + Environment.NewLine,
+ "CompressedFlags",
+ Utils.BytesToUInt(block, i),
+ "(" + (CompressedFlags)Utils.BytesToUInt(block, i) + ")",
+ "UInt");
+ i += 4;
+
+ // Owners ID
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "OwnerID",
+ new UUID(block, i),
+ "UUID");
+ i += 16;
+
+ // Angular velocity
+ if ((flags & CompressedFlags.HasAngularVelocity) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "AngularVelocity",
+ new Vector3(block, i),
+ "Vector3");
+ i += 12;
+ }
+
+ // Parent ID
+ if ((flags & CompressedFlags.HasParent) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ParentID",
+ (uint)(block[i++] + (block[i++] << 8) +
+ (block[i++] << 16) + (block[i++] << 24)),
+ "UInt");
+ }
+
+ // Tree data
+ if ((flags & CompressedFlags.Tree) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "TreeSpecies",
+ block[i++],
+ "(" + (Tree)block[i] + ")",
+ "Tree");
+ }
+
+ // Scratch pad
+ else if ((flags & CompressedFlags.ScratchPad) != 0)
+ {
+ int size = block[i++];
+ byte[] scratch = new byte[size];
+ Buffer.BlockCopy(block, i, scratch, 0, size);
+ result.AppendFormat("{0,30}: {1,-40} [ScratchPad[]]" + Environment.NewLine,
+ "ScratchPad",
+ Utils.BytesToHexString(scratch, String.Format("{0,30}", "Data")));
+ i += size;
+ }
+
+ // Floating text
+ if ((flags & CompressedFlags.HasText) != 0)
+ {
+ string text = String.Empty;
+ while (block[i] != 0)
+ {
+ text += (char)block[i];
+ i++;
+ }
+ i++;
+
+ // Floating text
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Text",
+ text,
+ "string");
+
+ // Text color
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "TextColor",
+ new Color4(block, i, false),
+ "Color4");
+ i += 4;
+ }
+
+ // Media URL
+ if ((flags & CompressedFlags.MediaURL) != 0)
+ {
+ string text = String.Empty;
+ while (block[i] != 0)
+ {
+ text += (char)block[i];
+ i++;
+ }
+ i++;
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "MediaURL",
+ text,
+ "string");
+ }
+
+ // Particle system
+ if ((flags & CompressedFlags.HasParticles) != 0)
+ {
+ Primitive.ParticleSystem p = new Primitive.ParticleSystem(block, i);
+ result.AppendLine(DecodeObjectParticleSystem("ParticleSystem", p));
+ i += 86;
+ }
+
+ // Extra parameters TODO:
+ Primitive prim = new Primitive();
+ int extrapLen = prim.SetExtraParamsFromBytes(block, i);
+ i += extrapLen;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ExtraParams[]",
+ extrapLen,
+ "byte[]");
+
+ //Sound data
+ if ((flags & CompressedFlags.HasSound) != 0)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "SoundID",
+ new UUID(block, i),
+ "UUID");
+ i += 16;
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "SoundGain",
+ Utils.BytesToFloat(block, i),
+ "Float");
+ i += 4;
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "SoundFlags",
+ block[i++],
+ "(" + (SoundFlags)block[i] + ")",
+ "SoundFlags");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "SoundRadius",
+ Utils.BytesToFloat(block, i),
+ "Float");
+ i += 4;
+ }
+
+ // Name values
+ if ((flags & CompressedFlags.HasNameValues) != 0)
+ {
+ string text = String.Empty;
+ while (block[i] != 0)
+ {
+ text += (char)block[i];
+ i++;
+ }
+ i++;
+
+ // Parse the name values
+ if (text.Length > 0)
+ {
+ string[] lines = text.Split('\n');
+ NameValue[] nameValues = new NameValue[lines.Length];
+
+ for (int j = 0; j < lines.Length; j++)
+ {
+ if (!String.IsNullOrEmpty(lines[j]))
+ {
+ NameValue nv = new NameValue(lines[j]);
+ nameValues[j] = nv;
+ }
+ }
+ result.AppendLine(DecodeNameValue("NameValues", nameValues));
+ }
+ }
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ "PathCurve",
+ block[i],
+ "(" + (PathCurve)block[i++] + ")",
+ "PathCurve");
+
+ ushort pathBegin = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathBegin",
+ Primitive.UnpackBeginCut(pathBegin),
+ "float");
+
+ ushort pathEnd = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathEnd",
+ Primitive.UnpackEndCut(pathEnd),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathScaleX",
+ Primitive.UnpackPathScale(block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathScaleY",
+ Primitive.UnpackPathScale(block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathShearX",
+ Primitive.UnpackPathShear((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathShearY",
+ Primitive.UnpackPathShear((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTwist",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTwistBegin",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathRadiusOffset",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTaperX",
+ Primitive.UnpackPathTaper((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathTaperY",
+ Primitive.UnpackPathTaper((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathRevolutions",
+ Primitive.UnpackPathRevolutions(block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "PathSkew",
+ Primitive.UnpackPathTwist((sbyte)block[i++]),
+ "float");
+
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileCurve",
+ block[i++],
+ "float");
+
+ ushort profileBegin = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileBegin",
+ Primitive.UnpackBeginCut(profileBegin),
+ "float");
+
+ ushort profileEnd = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileEnd",
+ Primitive.UnpackEndCut(profileEnd),
+ "float");
+
+ ushort profileHollow = Utils.BytesToUInt16(block, i);
+ i += 2;
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ProfileHollow",
+ Primitive.UnpackProfileHollow(profileHollow),
+ "float");
+
+ int textureEntryLength = (int)Utils.BytesToUInt(block, i);
+ i += 4;
+ //prim.Textures = new Primitive.TextureEntry(block, i, textureEntryLength);
+ String s = DecodeTextureEntry("TextureEntry", new Primitive.TextureEntry(block, i, textureEntryLength));
+ result.AppendLine(s);
+ i += textureEntryLength;
+
+ // Texture animation
+ if ((flags & CompressedFlags.TextureAnimation) != 0)
+ {
+ i += 4;
+ string a = DecodeObjectTextureAnim("TextureAnimation", new Primitive.TextureAnimation(block, i));
+ result.AppendLine(a);
+ }
+
+ if ((flags & CompressedFlags.HasParticlesNew) != 0)
+ {
+ Primitive.ParticleSystem p = new Primitive.ParticleSystem(block, i);
+ result.AppendLine(DecodeObjectParticleSystem("ParticleSystemNEW", p));
+ i += 94;
+ if ((p.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.DataGlow) != 0)
+ i += 2;
+ if ((p.PartDataFlags & Primitive.ParticleSystem.ParticleDataFlags.DataBlend) != 0)
+ i += 2;
+ }
+
+ return result.ToString();
+ }
+
+ private static string DecodeObjectData(string fieldName, object fieldData)
+ {
+ byte[] data = (byte[])fieldData;
+ if (data.Length == 1)
+ {
+ return String.Format("{0,30}: {1,2} {2,-38} [{3}]",
+ fieldName + " (Tree Species)",
+ fieldData,
+ //"(" + (Tree)(byte)fieldData + ")",
+ "(" + (Tree)data[0] + ")",
+ fieldData.GetType().Name);
+ }
+ else if (data.Length == 76)
+ {
+ /* TODO: these are likely useful packed fields,
+ * need to unpack them */
+ Vector4 col = Vector4.Zero;
+ Vector3 offset = Vector3.Zero;
+ Vector3 vel = Vector3.Zero;
+ Vector3 acc = Vector3.Zero;
+ Quaternion q = Quaternion.Identity;
+ Vector3 angvel = Vector3.Zero;
+
+ col.FromBytes(data, 0);
+ offset.FromBytes(data, 16);
+ vel.FromBytes(data, 28);
+ acc.FromBytes(data, 40);
+ q.FromBytes(data, 52, true);
+ angvel.FromBytes(data, 64);
+
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "ColisionPlane",
+ col,
+ "Vector4");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Offset",
+ offset,
+ "Vector3");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Velocity",
+ vel,
+ "Vector3");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Acceleration",
+ acc,
+ "Vector3");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "rotation",
+ q,
+ "Quaternion");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Omega",
+ angvel,
+ "Vector3");
+ return result.ToString();
+ }
+ else if (data.Length == 60)
+ {
+ /* TODO: these are likely useful packed fields,
+ * need to unpack them */
+ Vector3 offset = Vector3.Zero;
+ Vector3 vel = Vector3.Zero;
+ Vector3 acc = Vector3.Zero;
+ Quaternion q = Quaternion.Identity;
+ Vector3 angvel = Vector3.Zero;
+
+ offset.FromBytes(data, 0);
+ vel.FromBytes(data, 12);
+ acc.FromBytes(data, 24);
+ q.FromBytes(data, 36, true);
+ angvel.FromBytes(data, 48);
+
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Offset",
+ offset,
+ "Vector3");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Velocity",
+ vel,
+ "Vector3");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Acceleration",
+ acc,
+ "Vector3");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "rotation",
+ q,
+ "Quaternion");
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ "Omega",
+ angvel,
+ "Vector3");
+ return result.ToString();
+ }
+ else
+ {
+ return Utils.BytesToHexString((byte[])fieldData, String.Format("{0,30}", fieldName));
+ }
+ }
+
+ private static string DecodeObjectTextureAnim(string fieldName, object fieldData)
+ {
+ StringBuilder result = new StringBuilder();
+ Primitive.TextureAnimation TextureAnim;
+ if (fieldData is Primitive.TextureAnimation)
+ TextureAnim = (Primitive.TextureAnimation)fieldData;
+ else
+ TextureAnim = new Primitive.TextureAnimation((byte[])fieldData, 0);
+
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ GenericTypeDecoder(TextureAnim, ref result);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static string DecodeEstateParameter(string fieldName, object fieldData)
+ {
+ byte[] bytes = (byte[])fieldData;
+
+ if (bytes.Length == 17)
+ {
+ return String.Format("{0,30}: {1,-40} [UUID]", fieldName, new UUID((byte[])fieldData, 0));
+ }
+ else
+ {
+ return String.Format("{0,30}: {1,-40} [Byte[]]", fieldName, Utils.BytesToString((byte[])fieldData));
+ }
+ }
+
+ private static string DecodeNameValue(string fieldName, object fieldData)
+ {
+ NameValue[] nameValues = null;
+ if (fieldData is NameValue[])
+ nameValues = fieldData as NameValue[];
+ else
+ {
+ string nameValue = Utils.BytesToString((byte[])fieldData);
+ if (nameValue.Length > 0)
+ {
+ string[] lines = nameValue.Split('\n');
+ nameValues = new NameValue[lines.Length];
+
+ for (int i = 0; i < lines.Length; i++)
+ {
+ if (!String.IsNullOrEmpty(lines[i]))
+ {
+ NameValue nv = new NameValue(lines[i]);
+ nameValues[i] = nv;
+ }
+ }
+ }
+ }
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ if (nameValues != null)
+ {
+ for (int i = 0; i < nameValues.Length; i++)
+ {
+ result.AppendFormat(
+ "{0,30}: Name={1} Value={2} Class={3} Type={4} Sendto={5}" + Environment.NewLine, "NameValue",
+ nameValues[i].Name, nameValues[i].Value, nameValues[i].Class, nameValues[i].Type, nameValues[i].Sendto);
+ }
+ }
+ result.AppendFormat("{0,30}", "");
+ return result.ToString();
+ }
+
+ private static string DecodeObjectExtraParams(string fieldName, object fieldData)
+ {
+
+ byte[] data = (byte[])fieldData;
+
+ int i = 0;
+ //int totalLength = 1;
+
+ Primitive.FlexibleData Flexible = null;
+ Primitive.LightData Light = null;
+ Primitive.SculptData Sculpt = null;
+ Primitive.SculptData Mesh = null;
+ Primitive.ReflectionProbe rprobe = null;
+ Primitive.RenderMaterials RenderMaterials = null;
+ uint meshFlags = 0;
+ bool hasmeshFlags = false;
+
+ byte extraParamCount = data[i++];
+
+ for (int k = 0; k < extraParamCount; k++)
+ {
+ ExtraParamType type = (ExtraParamType)Utils.BytesToUInt16(data, i);
+ i += 2;
+
+ int paramLength = (int)Utils.BytesToUInt(data, i);
+ i += 4;
+
+ if (type == ExtraParamType.Flexible)
+ Flexible = new Primitive.FlexibleData(data, i);
+ else if (type == ExtraParamType.Light)
+ Light = new Primitive.LightData(data, i);
+ else if (type == ExtraParamType.Sculpt)
+ Sculpt = new Primitive.SculptData(data, i);
+ else if (type == ExtraParamType.Mesh)
+ Mesh = new Primitive.SculptData(data, i);
+ else if (type == ExtraParamType.MeshFlag)
+ {
+ hasmeshFlags = true;
+ meshFlags = Utils.BytesToUInt(data, i);
+ }
+ else if (type == ExtraParamType.RenderMaterial)
+ {
+ RenderMaterials = new Primitive.RenderMaterials(data, i, paramLength);
+ }
+ else if (type == ExtraParamType.ReflectionProbe)
+ {
+ rprobe = new Primitive.ReflectionProbe(data, i);
+ }
+
+ i += paramLength;
+ //totalLength += (int)paramLength + 6;
+ }
+
+ StringBuilder result = new StringBuilder();
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ if (Flexible != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Flexible, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ if (Sculpt != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Sculpt, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ if (Mesh != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Mesh, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ if (Light != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(Light, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ if (hasmeshFlags)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ result.AppendFormat("{0,30}", meshFlags.ToString() + Environment.NewLine);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+ if (rprobe != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(rprobe, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+ if (RenderMaterials != null)
+ {
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(RenderMaterials, ref result);
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ }
+
+ result.AppendFormat("{0,30}", "");
+ return result.ToString();
+ }
+
+ private static string DecodeObjectParticleSystem(string fieldName, object fieldData)
+ {
+ StringBuilder result = new StringBuilder();
+ Primitive.ParticleSystem ParticleSys;
+ if (fieldData is Primitive.ParticleSystem)
+ ParticleSys = (Primitive.ParticleSystem)fieldData;
+ else
+ ParticleSys = new Primitive.ParticleSystem((byte[])fieldData, 0);
+
+ result.AppendFormat("{0,30}", "" + Environment.NewLine);
+ GenericTypeDecoder(ParticleSys, ref result);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static void GenericTypeDecoder(object obj, ref StringBuilder result)
+ {
+ FieldInfo[] fields = obj.GetType().GetFields();
+
+ foreach (FieldInfo field in fields)
+ {
+ String special;
+ if (SpecialDecoder("a" + "." + "b" + "." + field.Name,
+ field.GetValue(obj), out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ field.Name,
+ field.GetValue(obj),
+ field.FieldType.Name);
+ }
+ }
+ }
+
+ private static string DecodeObjectPCode(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [PCode]",
+ fieldName,
+ fieldData,
+ "(" + (PCode)(byte)fieldData + ")");
+ }
+
+ private static string DecodeImageType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [ImageType]",
+ fieldName,
+ fieldData,
+ "(" + (ImageType)(byte)fieldData + ")");
+ }
+
+ private static string DecodeImageCodec(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [ImageCodec]",
+ fieldName,
+ fieldData,
+ "(" + (ImageCodec)(byte)fieldData + ")");
+ }
+
+ private static string DecodeObjectMaterial(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [Material]",
+ fieldName,
+ fieldData,
+ "(" + (Material)(byte)fieldData + ")");
+ }
+
+ private static string DecodeObjectClickAction(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [ClickAction]",
+ fieldName,
+ fieldData,
+ "(" + (ClickAction)(byte)fieldData + ")");
+ }
+
+ private static string DecodeEventFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [EventFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.EventFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeDirQueryFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [DirectoryManager.DirFindFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.DirFindFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeDirClassifiedQueryFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [ClassifiedQueryFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.ClassifiedQueryFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeDirClassifiedFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [ClassifiedFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.ClassifiedFlags)(byte)fieldData + ")");
+ }
+
+ private static string DecodeGroupPowers(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-20} {2,-19} [GroupPowers]",
+ fieldName,
+ fieldData,
+ "(" + (GroupPowers)(ulong)fieldData + ")");
+ }
+
+ private static string DecodeParcelACL(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [AccessList]",
+ fieldName,
+ fieldData,
+ "(" + (AccessList)(uint)fieldData + ")");
+ }
+
+ private static string SearchTypeFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [DirectoryManager.SearchTypeFlags]",
+ fieldName,
+ fieldData,
+ "(" + (DirectoryManager.SearchTypeFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeCategory(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-3} {2,-36} [ParcelCategory]",
+ fieldName,
+ fieldData,
+ "(" + fieldData + ")");
+ }
+
+ private static string DecodeObjectUpdateFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [PrimFlags]",
+ fieldName,
+ fieldData,
+ "(" + (PrimFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeTeleportFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [TeleportFlags]",
+ fieldName,
+ fieldData,
+ "(" + (TeleportFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeScriptControls(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [AgentManager.ControlFlags]",
+ fieldName,
+ (uint)fieldData,
+ "(" + (AgentManager.ControlFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeColorField(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-40} [Color4]",
+ fieldName,
+ fieldData.GetType().Name.Equals("Color4") ? (Color4)fieldData : new Color4((byte[])fieldData, 0, false));
+ }
+
+ private static string DecodeTimeStamp(string fieldName, object fieldData)
+ {
+ if (fieldData is Int32 && (int)fieldData > 0)
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + Utils.UnixTimeToDateTime((int)fieldData) + ")",
+ fieldData.GetType().Name);
+ else if (fieldData is uint && (uint)fieldData > 0)
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + Utils.UnixTimeToDateTime((uint)fieldData) + ")",
+ fieldData.GetType().Name);
+ else
+ return String.Format("{0,30}: {1,-40} [{2}]",
+ fieldName,
+ fieldData,
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeBinaryBucket(string fieldName, object fieldData)
+ {
+ byte[] bytes = (byte[])fieldData;
+ string bucket = String.Empty;
+ if (bytes.Length == 1)
+ {
+ bucket = String.Format("{0}", bytes[0]);
+ }
+ else if (bytes.Length == 17)
+ {
+ bucket = String.Format("{0,-36} {1} ({2})",
+ new UUID(bytes, 1),
+ bytes[0],
+ (AssetType)(sbyte)bytes[0]);
+ }
+ else if (bytes.Length == 16) // the folder ID for the asset to be stored into if we accept an inventory offer
+ {
+ bucket = new UUID(bytes, 0).ToString();
+ }
+ else
+ {
+ bucket = Utils.BytesToString(bytes); // we'll try a string lastly
+ }
+
+ return String.Format("{0,30}: {1,-40} [Byte[{2}]]", fieldName, bucket, bytes.Length);
+ }
+
+ private static string DecodeBinaryToHexString(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}",
+ Utils.BytesToHexString((byte[])fieldData,
+ String.Format("{0,30}", fieldName)));
+ }
+
+ private static string DecodeWearableType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [WearableType]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (WearableType)fieldData + ")");
+ }
+
+ private static string DecodeInventoryType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [AssetType]",
+ fieldName,
+ (sbyte)fieldData,
+ "(" + (AssetType)(sbyte)fieldData + ")");
+ }
+
+ private static string DecodeInventorySort(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [InventorySortOrder]",
+ fieldName,
+ fieldData,
+ "(" + (InventorySortOrder)(int)fieldData + ")");
+ }
+
+ private static string DecodeInventoryInvType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [InventoryType]",
+ fieldName,
+ (sbyte)fieldData,
+ "(" + (InventoryType)fieldData + ")");
+ }
+
+ private static string DecodeFolderType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [Folderype]",
+ fieldName,
+ (sbyte)fieldData,
+ "(" + (FolderType)fieldData + ")");
+ }
+
+ private static string DecodeInventoryFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [InventoryItemFlags]",
+ fieldName,
+ (uint)fieldData,
+ "(" + (InventoryItemFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeObjectSaleType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [SaleType]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (SaleType)fieldData + ")");
+ }
+
+ private static string DecodeRegionFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [RegionFlags]",
+ fieldName,
+ fieldData,
+ "(" + (RegionFlags)(uint)fieldData + ")");
+ }
+
+ private static string DecodeTransferParams(string fieldName, object fieldData)
+ {
+ byte[] paramData = (byte[])fieldData;
+ StringBuilder result = new StringBuilder();
+ result.AppendLine(" ");
+ if (paramData.Length == 20)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "AssetID",
+ new UUID(paramData, 0));
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [AssetType]" + Environment.NewLine,
+ "AssetType",
+ (sbyte)paramData[16],
+ "(" + (AssetType)(sbyte)paramData[16] + ")");
+
+ }
+ else if (paramData.Length == 100)
+ {
+ //UUID agentID = new UUID(info.TransferInfo.Params, 0);
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "AgentID",
+ new UUID(paramData, 0));
+
+ //UUID sessionID = new UUID(info.TransferInfo.Params, 16);
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "SessionID",
+ new UUID(paramData, 16));
+ //UUID ownerID = new UUID(info.TransferInfo.Params, 32);
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "OwnerID",
+ new UUID(paramData, 32));
+ //UUID taskID = new UUID(info.TransferInfo.Params, 48);
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "TaskID",
+ new UUID(paramData, 48));
+ //UUID itemID = new UUID(info.TransferInfo.Params, 64);
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "ItemID",
+ new UUID(paramData, 64));
+
+ result.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine,
+ "AssetID",
+ new UUID(paramData, 80));
+
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [AssetType]" + Environment.NewLine,
+ "AssetType",
+ (sbyte)paramData[96],
+ "(" + (AssetType)(sbyte)paramData[96] + ")");
+ }
+ else
+ {
+ Console.WriteLine("Oh Poop!");
+ }
+
+ result.Append("");
+
+ return result.ToString();
+ }
+
+ private static string DecodeTransferChannelType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [ChannelType]",
+ fieldName,
+ fieldData,
+ "(" + (ChannelType)(int)fieldData + ")");
+ }
+
+ private static string DecodeTransferSourceType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [SourceType]",
+ fieldName,
+ fieldData,
+ "(" + (SourceType)(int)fieldData + ")");
+ }
+
+ private static string DecodeTransferTargetType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [TargetType]",
+ fieldName,
+ fieldData,
+ "(" + (TargetType)(int)fieldData + ")");
+ }
+
+ private static string DecodeMapRequestFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [GridLayerType]",
+ fieldName,
+ fieldData,
+ "(" + (GridLayerType)(uint)fieldData + ")");
+ }
+
+ private static string DecodeGridItemType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [GridItemType]",
+ fieldName,
+ fieldData,
+ "(" + (GridItemType)(uint)fieldData + ")");
+
+ }
+
+ private static string DecodeLayerDataType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [LayerType]",
+ fieldName,
+ fieldData,
+ "(" + (TerrainPatch.LayerType)(byte)fieldData + ")");
+ }
+
+ private static string DecodeMapAccess(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [SimAccess]",
+ fieldName,
+ fieldData,
+ "(" + (SimAccess)(byte)fieldData + ")");
+ }
+
+ private static string DecodeSimAccess(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [SimAccess]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (SimAccess)fieldData + ")");
+ }
+
+ private static string DecodeAttachedSoundFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [SoundFlags]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (SoundFlags)fieldData + ")");
+ }
+
+
+ private static string DecodeChatSourceType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [SourceType]",
+ fieldName,
+ fieldData,
+ "(" + (SourceType)(byte)fieldData + ")");
+ }
+
+ private static string DecodeChatChatType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [ChatType]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (ChatType)fieldData + ")");
+ }
+
+ private static string DecodeChatAudible(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [ChatAudibleLevel]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (ChatAudibleLevel)(byte)fieldData + ")");
+ }
+
+ private static string DecodeImageData(string fieldName, object fieldData)
+ {
+ return String.Format("{0,10}",
+ Utils.BytesToHexString((byte[])fieldData,
+ String.Format("{0,30}", fieldName)));
+ }
+
+ private static string DecodeTerseTextureEntry(string fieldName, object fieldData)
+ {
+ byte[] block = (byte[])fieldData;
+
+ Primitive.TextureEntry te = new Primitive.TextureEntry(block, 4, block.Length - 4);
+
+ StringBuilder result = new StringBuilder();
+
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ if (te.DefaultTexture != null)
+ {
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ GenericFieldsDecoder(te.DefaultTexture, ref result);
+ GenericPropertiesDecoder(te.DefaultTexture, ref result);
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ for (int i = 0; i < te.FaceTextures.Length; i++)
+ {
+ if (te.FaceTextures[i] != null)
+ {
+ result.AppendFormat("{0,30}[{1}]" + Environment.NewLine, "FaceTexture", i);
+ GenericFieldsDecoder(te.FaceTextures[i], ref result);
+ GenericPropertiesDecoder(te.FaceTextures[i], ref result);
+ }
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static string DecodeTextureEntry(string fieldName, object fieldData)
+ {
+ Primitive.TextureEntry te;
+ if (fieldData is Primitive.TextureEntry)
+ te = (Primitive.TextureEntry)fieldData;
+ else
+ {
+ byte[] tebytes = (byte[])fieldData;
+ te = new Primitive.TextureEntry(tebytes, 0, tebytes.Length);
+ }
+
+ StringBuilder result = new StringBuilder();
+
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ if (te.DefaultTexture != null)
+ {
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ GenericFieldsDecoder(te.DefaultTexture, ref result);
+ GenericPropertiesDecoder(te.DefaultTexture, ref result);
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ for (int i = 0; i < te.FaceTextures.Length; i++)
+ {
+ if (te.FaceTextures[i] != null)
+ {
+ result.AppendFormat("{0,30}[{1}]" + Environment.NewLine, "FaceTexture", i);
+ GenericFieldsDecoder(te.FaceTextures[i], ref result);
+ GenericPropertiesDecoder(te.FaceTextures[i], ref result);
+ }
+ }
+ result.AppendFormat("{0,30}", " " + Environment.NewLine);
+ result.AppendFormat("{0,30}", "");
+
+ return result.ToString();
+ }
+
+ private static void GenericFieldsDecoder(object obj, ref StringBuilder result)
+ {
+ Type parcelType = obj.GetType();
+ FieldInfo[] fields = parcelType.GetFields();
+ foreach (FieldInfo field in fields)
+ {
+ String special;
+ if (SpecialDecoder("a" + "." + "b" + "." + field.Name,
+ field.GetValue(obj), out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ field.Name,
+ field.GetValue(obj),
+ field.FieldType.Name);
+ }
+ }
+ }
+
+ private static void GenericPropertiesDecoder(object obj, ref StringBuilder result)
+ {
+ Type parcelType = obj.GetType();
+ PropertyInfo[] propertyInfos = parcelType.GetProperties();
+ foreach (PropertyInfo property in propertyInfos)
+ {
+ String special;
+ if (SpecialDecoder("a" + "." + "b" + "." + property.Name,
+ property.GetValue(obj, null), out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ property.Name,
+ property.GetValue(obj, null),
+ property.PropertyType.Name);
+ }
+ }
+ }
+
+ private static string DecodeDialog(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [{3}]",
+ fieldName,
+ (byte)fieldData,
+ "(" + (InstantMessageDialog)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeControlFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (AgentManager.ControlFlags)(uint)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodePermissionMask(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-10} {2,-29} [{3}]",
+ fieldName,
+ (uint)fieldData,
+ "(" + (PermissionMask)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeViewerEffectTypeData(string fieldName, object fieldData)
+ {
+ byte[] data = (byte[])fieldData;
+ StringBuilder sb = new StringBuilder();
+ if (data.Length == 56 || data.Length == 57)
+ {
+ UUID sourceAvatar = new UUID(data, 0);
+ UUID targetObject = new UUID(data, 16);
+ Vector3d targetPos = new Vector3d(data, 32);
+ sb.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine, fieldName, "Source AvatarID=" + sourceAvatar);
+ sb.AppendFormat("{0,30}: {1,-40} [UUID]" + Environment.NewLine, fieldName, "Target ObjectID=" + targetObject);
+
+
+ float lx, ly;
+ Helpers.GlobalPosToRegionHandle((float)targetPos.X, (float)targetPos.Y, out lx, out ly);
+
+ sb.AppendFormat("{0,30}: {1,-40} [Vector3d]", fieldName, targetPos);
+
+ if (data.Length == 57)
+ {
+ sb.AppendLine();
+ sb.AppendFormat("{0,30}: {1,-17} {2,-22} [Byte]", fieldName, "Point At Type=" + data[56],
+ "(" + (PointAtType)data[56] + ")");
+ }
+
+ return sb.ToString();
+ }
+ else
+ {
+ return String.Format("{0,30}: (No Decoder) Length={1}" + Environment.NewLine, fieldName, data.Length) + Utils.BytesToHexString(data, String.Format("{0,30}", ""));
+ }
+ }
+
+ private static string DecodeAgentState(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [AgentState]",
+ fieldName,
+ fieldData,
+ "(" + (AgentState)(byte)fieldData + ")");
+ }
+
+ private static string DecodeAgentFlags(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [AgentFlags]",
+ fieldName,
+ fieldData,
+ "(" + (AgentFlags)(byte)fieldData + ")");
+ }
+
+ private static string DecodeObjectState(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [AttachmentPoint]",
+ fieldName,
+ fieldData,
+ "(" + (AttachmentPoint)(byte)fieldData + ")");
+ }
+
+ private static string DecodeViewerEffectType(string fieldName, object fieldData)
+ {
+ return String.Format("{0,30}: {1,-2} {2,-37} [{3}]",
+ fieldName,
+ fieldData,
+ "(" + (EffectType)(byte)fieldData + ")",
+ fieldData.GetType().Name);
+ }
+
+ private static string DecodeAnimToConst(string fieldName, object fieldData)
+ {
+ string animConst = "UUID";
+ Dictionary animsDict = Animations.ToDictionary();
+ if (animsDict.ContainsKey((UUID)fieldData))
+ animConst = animsDict[(UUID)fieldData];
+ return String.Format("{0,30}: {1,-40} [{2}]",
+ fieldName,
+ fieldData,
+ animConst);
+ }
+ #endregion
+
+ ///
+ /// Creates a formatted string containing the values of a Packet
+ ///
+ /// The Packet
+ /// A formatted string of values of the nested items in the Packet object
+ public static string PacketToString(Packet packet)
+ {
+ StringBuilder result = new StringBuilder();
+
+ result.AppendFormat("Packet Type: {0}" + Environment.NewLine, packet.Type);
+ result.AppendLine("[Packet Header]");
+ // payload
+ result.AppendFormat("Sequence: {0}" + Environment.NewLine, packet.Header.Sequence);
+ result.AppendFormat(" Options: {0}" + Environment.NewLine, InterpretOptions(packet.Header));
+ result.AppendLine();
+
+ result.AppendLine("[Packet Payload]");
+
+ FieldInfo[] fields = packet.GetType().GetFields();
+
+ for (int i = 0; i < fields.Length; i++)
+ {
+ // we're not interested in any of these here
+ if (fields[i].Name == "Type" || fields[i].Name == "Header" || fields[i].Name == "HasVariableBlocks")
+ continue;
+
+ if (fields[i].FieldType.IsArray)
+ {
+ result.AppendFormat("{0,30} []" + Environment.NewLine, "-- " + fields[i].Name + " --");
+ RecursePacketArray(fields[i], packet, ref result);
+ }
+ else
+ {
+ result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + fields[i].Name + " --");
+ RecursePacketField(fields[i], packet, ref result);
+ }
+ }
+ return result.ToString();
+ }
+
+ public static string InterpretOptions(Header header)
+ {
+ return "["
+ + (header.AppendedAcks ? "Ack" : " ")
+ + " "
+ + (header.Resent ? "Res" : " ")
+ + " "
+ + (header.Reliable ? "Rel" : " ")
+ + " "
+ + (header.Zerocoded ? "Zer" : " ")
+ + "]"
+ ;
+ }
+
+ private static void RecursePacketArray(FieldInfo fieldInfo, object packet, ref StringBuilder result)
+ {
+ var packetDataObject = fieldInfo.GetValue(packet);
+ int k = -1;
+ foreach (object nestedArrayRecord in packetDataObject as Array)
+ {
+ FieldInfo[] fields = nestedArrayRecord.GetType().GetFields();
+ ++k;
+ for (int i = 0; i < fields.Length; i++)
+ {
+ String special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + fields[i].Name,
+ fields[i].GetValue(nestedArrayRecord), out special))
+ {
+ result.AppendLine(special);
+ }
+ else if (fields[i].FieldType.IsArray) // default for an array (probably a byte[])
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ fields[i].Name + "[" + k.ToString() + "]",
+ Utils.BytesToString((byte[])fields[i].GetValue(nestedArrayRecord)),
+ /*fields[i].GetValue(nestedArrayRecord).GetType().Name*/ "String");
+ }
+ else // default for a field
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ fields[i].Name + "[" + k.ToString() + "]",
+ fields[i].GetValue(nestedArrayRecord),
+ fields[i].GetValue(nestedArrayRecord).GetType().Name);
+ }
+ }
+
+ // Handle Properties
+ foreach (PropertyInfo propertyInfo in nestedArrayRecord.GetType().GetProperties())
+ {
+ if (propertyInfo.Name.Equals("Length"))
+ continue;
+
+ string special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + propertyInfo.Name,
+ propertyInfo.GetValue(nestedArrayRecord, null),
+ out special))
+ {
+ result.AppendLine(special);
+ }
+ else
+ {
+ var p = propertyInfo.GetValue(nestedArrayRecord, null);
+ /* Leave the c for now at the end, it signifies something useful that still needs to be done i.e. a decoder written */
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]c" + Environment.NewLine,
+ propertyInfo.Name,
+ Utils.BytesToString((byte[])propertyInfo.GetValue(nestedArrayRecord, null)),
+ propertyInfo.PropertyType.Name);
+ }
+ }
+ result.AppendFormat("{0,32}" + Environment.NewLine, "***");
+ }
+ }
+
+ private static void RecursePacketField(FieldInfo fieldInfo, object packet, ref StringBuilder result)
+ {
+ object packetDataObject = fieldInfo.GetValue(packet);
+
+ // handle Fields
+ foreach (FieldInfo packetValueField in fieldInfo.GetValue(packet).GetType().GetFields())
+ {
+ string special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + packetValueField.Name,
+ packetValueField.GetValue(packetDataObject),
+ out special))
+ {
+ result.AppendLine(special);
+ }
+ else if (packetValueField.FieldType.IsArray)
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ packetValueField.Name,
+ Utils.BytesToString((byte[])packetValueField.GetValue(packetDataObject)),
+ /*packetValueField.FieldType.Name*/ "String");
+ }
+ else
+ {
+ result.AppendFormat("{0,30}: {1,-40} [{2}]" + Environment.NewLine,
+ packetValueField.Name, packetValueField.GetValue(packetDataObject), packetValueField.FieldType.Name);
+
+ }
+ }
+
+ // Handle Properties
+ foreach (PropertyInfo propertyInfo in packetDataObject.GetType().GetProperties())
+ {
+ if (propertyInfo.Name.Equals("Length"))
+ continue;
+
+ string special;
+ if (SpecialDecoder(packet.GetType().Name + "." + fieldInfo.Name + "." + propertyInfo.Name,
+ propertyInfo.GetValue(packetDataObject, null),
+ out special))
+ {
+ result.AppendLine(special);
+ }
+ else if (propertyInfo.GetValue(packetDataObject, null).GetType() == typeof(byte[]))
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
+ propertyInfo.Name,
+ Utils.BytesToString((byte[])propertyInfo.GetValue(packetDataObject, null)),
+ propertyInfo.PropertyType.Name);
+ }
+ else
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
+ propertyInfo.Name,
+ propertyInfo.GetValue(packetDataObject, null),
+ propertyInfo.PropertyType.Name);
+ }
+ }
+ }
+
+ private static bool SpecialDecoder(string decoderKey, object fieldData, out string result)
+ {
+ result = string.Empty;
+ string[] keys = decoderKey.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
+ string[] keyList = { decoderKey, decoderKey.Replace("Packet", ""), keys[1] + "." + keys[2], keys[2] };
+ foreach (string key in keyList)
+ {
+
+ bool ok = true;
+ if (fieldData is byte[])
+ {
+ byte[] fd = (byte[])fieldData;
+ ok = fd.Length > 0;
+ if (!ok)
+ {
+ // bypass the decoder since we were passed an empty byte array
+ result = String.Format("{0,30}:", keys[2]);
+ return true;
+ }
+ }
+
+ if (ok && Callbacks.ContainsKey(key)) // fieldname e.g: Plane
+ {
+ foreach (CustomPacketDecoder decoder in Callbacks[key])
+ result = decoder(keys[2], fieldData);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Decode an IMessage object into a beautifully formatted string
+ ///
+ /// The IMessage object
+ /// Recursion level (used for indenting)
+ /// A formatted string containing the names and values of the source object
+ public static string MessageToString(object message, int recurseLevel)
+ {
+ if (message == null)
+ return String.Empty;
+
+ StringBuilder result = new StringBuilder();
+ // common/custom types
+ if (recurseLevel <= 0)
+ {
+ result.AppendFormat("Message Type: {0}" + Environment.NewLine, message.GetType().Name);
+ }
+ else
+ {
+ string pad = " +--".PadLeft(recurseLevel + 3);
+ result.AppendFormat("{0} {1}" + Environment.NewLine, pad, message.GetType().Name);
+ }
+
+ recurseLevel++;
+
+ foreach (FieldInfo messageField in message.GetType().GetFields())
+ {
+ // an abstract message class
+ if (messageField.FieldType.IsAbstract)
+ {
+ result.AppendLine(MessageToString(messageField.GetValue(message), recurseLevel));
+ }
+ // a byte array
+ else if (messageField.GetValue(message) != null && messageField.GetValue(message).GetType() == typeof(Byte[]))
+ {
+ result.AppendFormat("{0, 30}:" + Environment.NewLine, messageField.Name);
+
+ result.AppendFormat("{0}" + Environment.NewLine,
+ Utils.BytesToHexString((byte[])messageField.GetValue(message),
+ String.Format("{0,30}", "")));
+ }
+
+ // an array of class objects
+ else if (messageField.FieldType.IsArray)
+ {
+ var messageObjectData = messageField.GetValue(message);
+ result.AppendFormat("-- {0} --" + Environment.NewLine, messageField.FieldType.Name);
+ foreach (object nestedArrayObject in messageObjectData as Array)
+ {
+ if (nestedArrayObject == null)
+ {
+ result.AppendFormat("{0,30}" + Environment.NewLine, "-- null --");
+ continue;
+ }
+ else
+ {
+ result.AppendFormat("{0,30}" + Environment.NewLine, "-- " + nestedArrayObject.GetType().Name + " --");
+ }
+ foreach (FieldInfo nestedField in nestedArrayObject.GetType().GetFields())
+ {
+ if (nestedField.FieldType.IsEnum)
+ {
+ result.AppendFormat("{0,30}: {1,-10} {2,-29} [{3}]" + Environment.NewLine,
+ nestedField.Name,
+ Enum.Format(nestedField.GetValue(nestedArrayObject).GetType(),
+ nestedField.GetValue(nestedArrayObject), "D"),
+ "(" + nestedField.GetValue(nestedArrayObject) + ")",
+ nestedField.GetValue(nestedArrayObject).GetType().Name);
+ }
+ else if (nestedField.FieldType.IsInterface)
+ {
+ result.AppendLine(MessageToString(nestedField.GetValue(nestedArrayObject), recurseLevel));
+ }
+ else
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
+ nestedField.Name,
+ nestedField.GetValue(nestedArrayObject),
+ nestedField.FieldType.Name);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (messageField.FieldType.IsEnum)
+ {
+ result.AppendFormat("{0,30}: {1,-2} {2,-37} [{3}]" + Environment.NewLine,
+ messageField.Name,
+ Enum.Format(messageField.GetValue(message).GetType(),
+ messageField.GetValue(message), "D"),
+ "(" + messageField.GetValue(message) + ")",
+ messageField.FieldType.Name);
+ }
+ else if (messageField.FieldType.IsInterface)
+ {
+ result.AppendLine(MessageToString(messageField.GetValue(message), recurseLevel));
+ }
+ else
+ {
+ result.AppendFormat("{0, 30}: {1,-40} [{2}]" + Environment.NewLine,
+ messageField.Name, messageField.GetValue(message), messageField.FieldType.Name);
+ }
+ }
+ }
+
+ return result.ToString();
+ }
+ }
+}
diff --git a/OpenMetaverse/Primitives/Primitive.cs b/OpenMetaverse/Primitives/Primitive.cs
index cbccd7ec..b9430a6f 100644
--- a/OpenMetaverse/Primitives/Primitive.cs
+++ b/OpenMetaverse/Primitives/Primitive.cs
@@ -24,8 +24,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-using OpenMetaverse.StructuredData;
using System;
+using System.Collections.Generic;
+using OpenMetaverse.StructuredData;
namespace OpenMetaverse
{
@@ -33,11 +34,17 @@ public partial class Primitive : IEquatable
{
// Used for packing and unpacking parameters
protected const float CUT_QUANTA = 0.00002f;
+ protected const float CUT_QUANTAINV = 1.0f / CUT_QUANTA;
protected const float SCALE_QUANTA = 0.01f;
+ protected const float SCALE_QUANTAINV = 1-0f/ SCALE_QUANTA;
protected const float SHEAR_QUANTA = 0.01f;
+ protected const float SHEAR_QUANTAINV = 1.0f / SHEAR_QUANTA;
protected const float TAPER_QUANTA = 0.01f;
+ protected const float TAPER_QUANTAINV = 1.0f / TAPER_QUANTA;
protected const float REV_QUANTA = 0.015f;
+ protected const float REV_QUANTAINV = 1.0f / REV_QUANTA;
protected const float HOLLOW_QUANTA = 0.00002f;
+ protected const float HOLLOW_QUANTAINV = 1.0f / HOLLOW_QUANTA;
#region Subclasses
@@ -129,7 +136,7 @@ public Vector2 PathBeginScale
{
get
{
- Vector2 begin = new Vector2(1f, 1f);
+ Vector2 begin = new(1f, 1f);
if (PathScaleX > 1f)
begin.X = 2f - PathScaleX;
if (PathScaleY > 1f)
@@ -143,7 +150,7 @@ public Vector2 PathEndScale
{
get
{
- Vector2 end = new Vector2(1f, 1f);
+ Vector2 end = new(1f, 1f);
if (PathScaleX < 1f)
end.X = PathScaleX;
if (PathScaleY < 1f)
@@ -267,14 +274,15 @@ public byte[] GetBytes()
///
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);
+ OSDMap map = new()
+ {
+ ["simulate_lod"] = OSD.FromInteger(Softness),
+ ["gravity"] = OSD.FromReal(Gravity),
+ ["air_friction"] = OSD.FromReal(Drag),
+ ["wind_sensitivity"] = OSD.FromReal(Wind),
+ ["tension"] = OSD.FromReal(Tension),
+ ["user_force"] = OSD.FromVector3(Force)
+ };
return map;
}
@@ -382,13 +390,14 @@ public byte[] GetBytes()
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);
+ OSDMap map = new()
+ {
+ ["color"] = OSD.FromColor4(Color),
+ ["intensity"] = OSD.FromReal(Intensity),
+ ["radius"] = OSD.FromReal(Radius),
+ ["cutoff"] = OSD.FromReal(Cutoff),
+ ["falloff"] = OSD.FromReal(Falloff)
+ };
return map;
}
@@ -485,10 +494,11 @@ public byte[] GetBytes()
public OSD GetOSD()
{
- OSDMap map = new OSDMap();
-
- map["texture"] = OSD.FromUUID(LightTexture);
- map["params"] = OSD.FromVector3(Params);
+ OSDMap map = new()
+ {
+ ["texture"] = OSD.FromUUID(LightTexture),
+ ["params"] = OSD.FromVector3(Params)
+ };
return map;
}
@@ -519,7 +529,7 @@ public override int GetHashCode()
///
public override string ToString()
{
- return String.Format("LightTexture: {0} Params; {1]", LightTexture, Params);
+ return String.Format("LightTexture: {0} Params; {1}", LightTexture, Params);
}
}
@@ -551,7 +561,7 @@ public bool Invert
public bool Mirror
{
get { return ((type & (byte)SculptType.Mirror) != 0); }
- }
+ }
///
/// Default constructor
@@ -591,10 +601,11 @@ public byte[] GetBytes()
public OSD GetOSD()
{
- OSDMap map = new OSDMap();
-
- map["texture"] = OSD.FromUUID(SculptTexture);
- map["type"] = OSD.FromInteger(type);
+ OSDMap map = new()
+ {
+ ["texture"] = OSD.FromUUID(SculptTexture),
+ ["type"] = OSD.FromInteger(type)
+ };
return map;
}
@@ -620,6 +631,236 @@ public override int GetHashCode()
}
}
+ ///
+ /// Information on the ReflectionProbe properties of a primitive
+ ///
+ public class ReflectionProbe
+ {
+ ///
+ /// Default constructor
+ ///
+ public ReflectionProbe()
+ {
+ }
+
+ public float Ambiance = 0;
+ public float ClipDistance = 0;
+ public byte Flags = 0;
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ReflectionProbe(byte[] data, int pos)
+ {
+ if (data.Length - pos >= 9)
+ {
+ Ambiance = Utils.Clamp(Utils.BytesToFloat(data, pos), 0, 1.0f);
+ ClipDistance = Utils.Clamp(Utils.BytesToFloat(data, pos + 4), 0, 1024f);
+ Flags = data[pos + 8];
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public byte[] GetBytes()
+ {
+ byte[] data = new byte[9];
+ Utils.FloatToBytes(Ambiance, data, 0);
+ Utils.FloatToBytes(ClipDistance, data, 4);
+ data[8] = Flags;
+ return data;
+ }
+
+ public OSD GetOSD()
+ {
+ OSDMap map = new()
+ {
+ ["ambiance"] = OSD.FromReal(Ambiance),
+ ["clip_distance"] = OSD.FromReal(ClipDistance),
+ ["flags"] = OSD.FromInteger(Flags)
+ };
+ return map;
+ }
+
+ public static ReflectionProbe FromOSD(OSD osd)
+ {
+ ReflectionProbe probe = new ReflectionProbe();
+
+ if (osd.Type == OSDType.Map)
+ {
+ OSDMap map = (OSDMap)osd;
+
+ probe.Ambiance = (float)map["ambiance"].AsReal();
+ probe.ClipDistance = (float)map["clip_distance"].AsReal();
+ probe.Flags = (byte)map["flags"].AsInteger();
+ }
+
+ return probe;
+ }
+
+ public override int GetHashCode()
+ {
+ return Ambiance.GetHashCode() ^ ClipDistance.GetHashCode() ^ (int)Flags;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public override string ToString()
+ {
+ return String.Format("ReflectionProbe: amb {0} clip {1} flags {2}", Ambiance, ClipDistance, Flags);
+ }
+ }
+
+ ///
+ /// Information on the RenderMaterial properties of a primitive
+ ///
+ public class RenderMaterials
+ {
+ public struct RenderMaterialEntry : IComparable
+ {
+ public byte te_index;
+ public UUID id;
+ public int CompareTo(RenderMaterialEntry other)
+ {
+ return te_index.CompareTo(other.te_index);
+ }
+ }
+
+ public struct RenderMaterialOverrideEntry : IComparable
+ {
+ public byte te_index;
+ public string data;
+ public int CompareTo(RenderMaterialEntry other)
+ {
+ return te_index.CompareTo(other.te_index);
+ }
+ }
+
+ public RenderMaterialEntry[] entries = null;
+ public RenderMaterialOverrideEntry[] overrides = null;
+
+ ///
+ /// Default constructor
+ ///
+ public RenderMaterials()
+ {
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RenderMaterials(byte[] data, int pos, int size)
+ {
+ if (size > 17)
+ {
+ int count = data[pos];
+ ++pos;
+ if (size >= 1 + 17 * count)
+ {
+ entries = new RenderMaterialEntry[count];
+ for (int i = 0; i < count; ++i)
+ {
+ entries[i].te_index = data[pos++];
+ entries[i].id = new UUID(data, pos);
+ pos += 16;
+ }
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public byte[] GetBytes()
+ {
+ if (entries == null || entries.Length == 0)
+ {
+ return new byte[] {0};
+ }
+ byte[] data = new byte[1 + 17 * entries.Length];
+ data[0] = (byte)entries.Length;
+ int pos = 1;
+ for (int i = 0; i < entries.Length; ++i)
+ {
+ data[pos++] = entries[i].te_index;
+ entries[i].id.ToBytes(data, pos);
+ pos += 16;
+ }
+ return data;
+ }
+
+ public OSD GetOSD()
+ {
+ OSDArray eMaterials = new OSDArray();
+ if(entries != null)
+ {
+ for(int i = 0; i < entries.Length;++i)
+ {
+ OSDMap map = new OSDMap()
+ {
+ ["te_idx"] = OSD.FromInteger(entries[i].te_index),
+ ["id"] = OSD.FromUUID(entries[i].id)
+ };
+ eMaterials[i] = map;
+ }
+ }
+ return eMaterials;
+ }
+
+ public static RenderMaterials FromOSD(OSD osd)
+ {
+ RenderMaterials rm = new();
+ try
+ {
+ if (osd.Type == OSDType.Array)
+ {
+ OSDArray mra = (OSDArray)osd;
+ if(mra.Count > 0)
+ {
+ RenderMaterialEntry[] entries = new RenderMaterialEntry[mra.Count];
+ for(int i = 0; i < mra.Count; ++i)
+ {
+ OSDMap map = (OSDMap)mra[i];
+ entries[i].te_index = (byte)map["te_idx"].AsInteger();
+ entries[i].id = map["id"].AsUUID();
+ }
+ rm.entries = entries;
+ }
+ }
+ }
+ catch
+ {
+ rm.entries = null;
+ }
+ return rm;
+ }
+
+ public override int GetHashCode()
+ {
+ int h = entries.Length.GetHashCode();
+ for(int i = 0 ; i < entries.Length; ++i)
+ h ^= (int)entries[i].te_index ^ entries[i].id.GetHashCode();
+ return h;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public override string ToString()
+ {
+ return String.Format("RenderMaterials: nentries {0}}", entries==null? 0:entries.Length);
+ }
+ }
+
///
/// Extended properties to describe an object
///
@@ -983,7 +1224,7 @@ public Primitive(Primitive prim)
TextColor = prim.TextColor;
MediaURL = prim.MediaURL;
Joint = prim.Joint;
- JointPivot = prim.JointPivot;
+ JointPivot = prim.JointPivot;
JointAxisOrAnchor = prim.JointAxisOrAnchor;
if (prim.NameValues != null)
{
@@ -1148,10 +1389,10 @@ public static Primitive FromOSD(OSD osd)
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"]);
@@ -1162,7 +1403,7 @@ public static Primitive FromOSD(OSD osd)
prim.Sculpt = SculptData.FromOSD(map["sculpt"]);
prim.Textures = TextureEntry.FromOSD(map["textures"]);
-
+
if (map["texture_anim"])
prim.TextureAnim = TextureAnimation.FromOSD(map["texture_anim"]);
@@ -1412,22 +1653,22 @@ public override int GetHashCode()
public static ushort PackBeginCut(float beginCut)
{
- return (ushort)Math.Round(beginCut / CUT_QUANTA);
+ return (ushort)MathF.Round(beginCut * CUT_QUANTAINV);
}
public static ushort PackEndCut(float endCut)
{
- return (ushort)(50000 - (ushort)Math.Round(endCut / CUT_QUANTA));
+ return (ushort)(50000 - (ushort)MathF.Round(endCut * CUT_QUANTAINV));
}
public static byte PackPathScale(float pathScale)
{
- return (byte)(200 - (byte)Math.Round(pathScale / SCALE_QUANTA));
+ return (byte)(200 - (byte)MathF.Round(pathScale * SCALE_QUANTAINV));
}
public static sbyte PackPathShear(float pathShear)
{
- return (sbyte)Math.Round(pathShear / SHEAR_QUANTA);
+ return (sbyte)MathF.Round(pathShear * SHEAR_QUANTAINV);
}
///
@@ -1438,22 +1679,22 @@ public static sbyte PackPathShear(float pathShear)
/// Signed eight bit value containing the packed parameter
public static sbyte PackPathTwist(float pathTwist)
{
- return (sbyte)Math.Round(pathTwist / SCALE_QUANTA);
+ return (sbyte)MathF.Round(pathTwist * SCALE_QUANTAINV);
}
public static sbyte PackPathTaper(float pathTaper)
{
- return (sbyte)Math.Round(pathTaper / TAPER_QUANTA);
+ return (sbyte)MathF.Round(pathTaper * TAPER_QUANTAINV);
}
public static byte PackPathRevolutions(float pathRevolutions)
{
- return (byte)Math.Round((pathRevolutions - 1f) / REV_QUANTA);
+ return (byte)MathF.Round((pathRevolutions - 1f) * REV_QUANTAINV);
}
public static ushort PackProfileHollow(float profileHollow)
{
- return (ushort)Math.Round(profileHollow / HOLLOW_QUANTA);
+ return (ushort)MathF.Round(profileHollow * HOLLOW_QUANTAINV);
}
#endregion Parameter Packing Methods
diff --git a/OpenMetaverse/Rendering/Rendering.cs b/OpenMetaverse/Rendering/Rendering.cs
index 9506eb5c..2c9f73d4 100644
--- a/OpenMetaverse/Rendering/Rendering.cs
+++ b/OpenMetaverse/Rendering/Rendering.cs
@@ -303,20 +303,14 @@ public static bool TryDecodeFromAsset(Primitive prim, AssetMesh meshAsset, Detai
// Decode each individual face
if (subMeshOsd is OSDMap)
{
- OSDMap subMeshMap = (OSDMap)subMeshOsd;
-
- // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
- // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no
- // geometry for this submesh.
- if (subMeshMap.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshMap["NoGeometry"]))
- continue;
-
Face oface = new Face();
oface.ID = faceNr;
oface.Vertices = new List();
oface.Indices = new List();
oface.TextureFace = prim.Textures.GetFace((uint)faceNr);
+ OSDMap subMeshMap = (OSDMap)subMeshOsd;
+
Vector3 posMax;
Vector3 posMin;
diff --git a/Programs/AvatarPreview/AvatarPreview.csproj b/Programs/AvatarPreview/AvatarPreview.csproj
index ca2e3d6e..2d0e5941 100644
--- a/Programs/AvatarPreview/AvatarPreview.csproj
+++ b/Programs/AvatarPreview/AvatarPreview.csproj
@@ -1,7 +1,8 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
avatarpreview
Millions Of Us
@@ -11,9 +12,6 @@
True
-
- False
-
False
../../bin/Tao.OpenGl.dll
diff --git a/Programs/AvatarPreview/GLMesh.cs b/Programs/AvatarPreview/GLMesh.cs
index 27f08ee8..1dd8983b 100644
--- a/Programs/AvatarPreview/GLMesh.cs
+++ b/Programs/AvatarPreview/GLMesh.cs
@@ -109,6 +109,7 @@ public override void LoadMesh(string filename)
}
}
+ [Obsolete]
public override void LoadLODMesh(int level, string filename)
{
LODMesh lod = new LODMesh();
diff --git a/Programs/Baker/Baker.csproj b/Programs/Baker/Baker.csproj
index e836cf5a..66a006f6 100644
--- a/Programs/Baker/Baker.csproj
+++ b/Programs/Baker/Baker.csproj
@@ -1,16 +1,12 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
True
1591,1574,0419,0618
-
-
- False
-
-
diff --git a/Programs/GridImageUpload/GridImageUpload.csproj b/Programs/GridImageUpload/GridImageUpload.csproj
index 6fc517f5..462eaa42 100644
--- a/Programs/GridImageUpload/GridImageUpload.csproj
+++ b/Programs/GridImageUpload/GridImageUpload.csproj
@@ -1,7 +1,8 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
GridImageUpload
Open Metaverse Foundation
@@ -11,11 +12,6 @@
1591,1574,0419,0618
True
-
-
- False
-
-
diff --git a/Programs/GridImageUpload/Properties/Resources.Designer.cs b/Programs/GridImageUpload/Properties/Resources.Designer.cs
index f5a366c1..3f6b225b 100644
--- a/Programs/GridImageUpload/Properties/Resources.Designer.cs
+++ b/Programs/GridImageUpload/Properties/Resources.Designer.cs
@@ -1,17 +1,17 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:2.0.50727.42
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace GridImageUpload.Properties
-{
-
-
+namespace GridImageUpload.Properties {
+ using System;
+
+
///
/// A strongly-typed resource class, for looking up localized strings, etc.
///
@@ -19,51 +19,43 @@ namespace GridImageUpload.Properties
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources
- {
-
+ internal class Resources {
+
private static global::System.Resources.ResourceManager resourceMan;
-
+
private static global::System.Globalization.CultureInfo resourceCulture;
-
+
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources()
- {
+ internal Resources() {
}
-
+
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager
- {
- get
- {
- if ((resourceMan == null))
- {
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GridImageUpload.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture
- {
- get
- {
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
return resourceCulture;
}
- set
- {
+ set {
resourceCulture = value;
}
}
diff --git a/Programs/GridImageUpload/Properties/Settings.Designer.cs b/Programs/GridImageUpload/Properties/Settings.Designer.cs
index 3c5c10ac..2f41626b 100644
--- a/Programs/GridImageUpload/Properties/Settings.Designer.cs
+++ b/Programs/GridImageUpload/Properties/Settings.Designer.cs
@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:2.0.50727.42
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace SLImageUpload.Properties
-{
-
-
+namespace GridImageUpload.Properties {
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
- {
-
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default
- {
- get
- {
+
+ public static Settings Default {
+ get {
return defaultInstance;
}
}
diff --git a/Programs/GridProxy/GridProxy.cs b/Programs/GridProxy/GridProxy.cs
index ff1d182b..bad29d49 100644
--- a/Programs/GridProxy/GridProxy.cs
+++ b/Programs/GridProxy/GridProxy.cs
@@ -41,12 +41,15 @@
using System.Threading;
using System.Xml;
-using Nwc.XmlRpc;
-
using OpenMetaverse;
using OpenMetaverse.Http;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
+using log4net;
+using XmlRpcCore;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using System.Net.Http;
namespace GridProxy
{
@@ -188,6 +191,8 @@ public class Proxy
public ProxyConfig proxyConfig;
private string loginURI;
+ private static readonly HttpClient HttpClient = new HttpClient();
+
static List BinaryResponseCaps = new List()
{
"ViewerAsset",
@@ -199,6 +204,23 @@ public class Proxy
/*
* Proxy Management
*/
+ public static bool ValidateServerCertificate(
+ object sender,
+ X509Certificate certificate,
+ X509Chain chain,
+ SslPolicyErrors sslPolicyErrors)
+ {
+ //if (m_NoVerifyCertChain)
+ sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
+
+ //if (m_NoVerifyCertHostname)
+ sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateNameMismatch;
+
+ if (sslPolicyErrors == SslPolicyErrors.None)
+ return true;
+
+ return false;
+ }
// Proxy: construct a proxy server with the given configuration
public Proxy(ProxyConfig proxyConfig)
@@ -207,7 +229,7 @@ public Proxy(ProxyConfig proxyConfig)
ServicePointManager.Expect100Continue = false;
ServicePointManager.DefaultConnectionLimit = 128;
- ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
+ ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
InitializeLoginProxy();
InitializeSimProxy();
@@ -585,7 +607,7 @@ private void ProxyHTTP(Socket client)
headers["method"] = meth;
if (contentType == "application/llsd+xml" || contentType == "application/xml+llsd" || contentType == "application/xml")
{
- ProxyLoginSD(netStream, content);
+ ProxyLoginSD(netStream, content, headers);
}
else
{
@@ -620,9 +642,11 @@ private void ProxyHTTP(Socket client)
public ObservableDictionary KnownCaps = new ObservableDictionary();
//private Dictionary SubHack = new Dictionary();
+ private static Regex CapMainRegex = new Regex(@"^(https?)://([^:/]+)(:\d+)?(/.*)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
+ private static Regex CapUriRegex = new Regex(@"/?\?.*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
private void ProxyCaps(NetworkStream netStream, string meth, string uri, Dictionary headers, byte[] content, int reqNo)
{
- Match match = new Regex(@"^(https?)://([^:/]+)(:\d+)?(/.*)$").Match(uri);
+ Match match = CapMainRegex.Match(uri);
if (!match.Success)
{
OpenMetaverse.Logger.Log("[" + reqNo + "] Malformed proxy URI: " + uri, Helpers.LogLevel.Error);
@@ -638,8 +662,7 @@ private void ProxyCaps(NetworkStream netStream, string meth, string uri, Diction
CapInfo cap = null;
lock (this)
{
- string capuri = Regex.Replace(uri, @"/?\?.*$", string.Empty);
-
+ string capuri = CapUriRegex.Replace(uri, string.Empty);
// detect AIS url
int indx = capuri.IndexOf("/item/");
if (indx < 0)
@@ -647,9 +670,14 @@ private void ProxyCaps(NetworkStream netStream, string meth, string uri, Diction
if(indx > 0)
capuri = capuri.Substring(0,indx);
- if (KnownCaps.ContainsKey(capuri))
+ if (!KnownCaps.TryGetValue(capuri, out cap))
{
- cap = KnownCaps[capuri];
+ indx = capuri.IndexOf("cap/");
+ if(indx > 0)
+ {
+ capuri = capuri.Substring(0,indx + 36 + 4);
+ _ = KnownCaps.TryGetValue(capuri, out cap);
+ }
}
}
@@ -1063,15 +1091,10 @@ private bool FixupEventQueueGet(CapsRequest capReq, CapsStage stage)
{
if (stage != CapsStage.Response) return false;
- OSDMap map = null;
- if (capReq.Response is OSDMap)
- map = (OSDMap)capReq.Response;
- else return false;
+ if (capReq.Response is not OSDMap map)
+ return false;
- OSDArray array = null;
- if (map.ContainsKey("events") && map["events"] is OSDArray)
- array = (OSDArray)map["events"];
- else
+ if(!map.TryGetValue("events", out OSD oarray) || oarray is not OSDArray array)
return false;
for (int i = 0; i < array.Count; i++)
@@ -1169,7 +1192,10 @@ private void ProxyLogin(NetworkStream netStream, byte[] content, Dictionary headers)
{
lock (this)
{
AutoResetEvent remoteComplete = new AutoResetEvent(false);
CapsClient loginRequest = new CapsClient(proxyConfig.remoteLoginUri);
+
OSD response = null;
loginRequest.OnComplete += new CapsClient.CompleteCallback(
delegate (CapsClient client, OSD result, Exception error)
@@ -1257,6 +1284,7 @@ private void ProxyLoginSD(NetworkStream netStream, byte[] content)
remoteComplete.Set();
}
);
+
loginRequest.BeginGetResponse(content, "application/llsd+xml", 1000 * 100);
remoteComplete.WaitOne(1000 * 100, false);
@@ -2169,8 +2197,7 @@ public class CapInfo
public CapInfo(string URI, IPEndPoint Sim, string CapType)
:
- this(URI, Sim, CapType, CapsDataFormat.OSD, CapsDataFormat.OSD)
- { }
+ this(URI, Sim, CapType, CapsDataFormat.OSD, CapsDataFormat.OSD) { }
public CapInfo(string URI, IPEndPoint Sim, string CapType, CapsDataFormat ReqFmt, CapsDataFormat RespFmt)
{
uri = URI; sim = Sim; type = CapType; reqFmt = ReqFmt; respFmt = RespFmt;
@@ -2252,6 +2279,7 @@ public CapsRequest(CapInfo info)
public string FullUri = string.Empty;
public string Method = string.Empty;
+ public string ExtraInfo = string.Empty;
}
// XmlRpcRequestDelegate: specifies a delegate to be called for XML-RPC requests
diff --git a/Programs/GridProxy/GridProxy.csproj b/Programs/GridProxy/GridProxy.csproj
index 21da9dc5..a6ca4dbc 100644
--- a/Programs/GridProxy/GridProxy.csproj
+++ b/Programs/GridProxy/GridProxy.csproj
@@ -1,18 +1,12 @@
Local
- net48
+ net6.0
True
1591,1574,0419,0618
-
-
-
-
- False
- ..\..\bin\XMLRPC.dll
-
+
diff --git a/Programs/GridProxy/GridProxyLoader.cs b/Programs/GridProxy/GridProxyLoader.cs
index 7adf98dd..cb1afe05 100644
--- a/Programs/GridProxy/GridProxyLoader.cs
+++ b/Programs/GridProxy/GridProxyLoader.cs
@@ -1,5 +1,4 @@
-
-using Nwc.XmlRpc;
+using XmlRpcCore;
using OpenMetaverse;
using OpenMetaverse.Packets;
using System;
diff --git a/Programs/GridProxyApp/GridProxyApp.csproj b/Programs/GridProxyApp/GridProxyApp.csproj
index d0b9e776..3f43bdc1 100644
--- a/Programs/GridProxyApp/GridProxyApp.csproj
+++ b/Programs/GridProxyApp/GridProxyApp.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
True
1591,1574,0419,0618
diff --git a/Programs/PrimWorkshop/PrimWorkshop.csproj b/Programs/PrimWorkshop/PrimWorkshop.csproj
index 66e37f2d..433f6781 100644
--- a/Programs/PrimWorkshop/PrimWorkshop.csproj
+++ b/Programs/PrimWorkshop/PrimWorkshop.csproj
@@ -1,7 +1,8 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
primpreview
Metaverse Industries LLC
@@ -19,9 +20,6 @@
False
..\..\bin\ICSharpCode.SharpZipLib.dll
-
- False
-
False
..\..\bin\Tao.OpenGl.dll
diff --git a/Programs/PrimWorkshop/Properties/Resources.Designer.cs b/Programs/PrimWorkshop/Properties/Resources.Designer.cs
index ab76bed3..d3db8c4f 100644
--- a/Programs/PrimWorkshop/Properties/Resources.Designer.cs
+++ b/Programs/PrimWorkshop/Properties/Resources.Designer.cs
@@ -1,17 +1,17 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:2.0.50727.42
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace PrimWorkshop.Properties
-{
-
-
+namespace PrimWorkshop.Properties {
+ using System;
+
+
///
/// A strongly-typed resource class, for looking up localized strings, etc.
///
@@ -19,51 +19,43 @@ namespace PrimWorkshop.Properties
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- internal class Resources
- {
-
+ internal class Resources {
+
private static global::System.Resources.ResourceManager resourceMan;
-
+
private static global::System.Globalization.CultureInfo resourceCulture;
-
+
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal Resources()
- {
+ internal Resources() {
}
-
+
///
/// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager
- {
- get
- {
- if ((resourceMan == null))
- {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("primpreview.Properties.Resources", typeof(Resources).Assembly);
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PrimWorkshop.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture
- {
- get
- {
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
return resourceCulture;
}
- set
- {
+ set {
resourceCulture = value;
}
}
diff --git a/Programs/PrimWorkshop/Properties/Settings.Designer.cs b/Programs/PrimWorkshop/Properties/Settings.Designer.cs
index 2b903164..f20d649a 100644
--- a/Programs/PrimWorkshop/Properties/Settings.Designer.cs
+++ b/Programs/PrimWorkshop/Properties/Settings.Designer.cs
@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:2.0.50727.42
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
-namespace PrimWorkshop.Properties
-{
-
-
+namespace PrimWorkshop.Properties {
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
- internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
- {
-
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
- public static Settings Default
- {
- get
- {
+
+ public static Settings Default {
+ get {
return defaultInstance;
}
}
diff --git a/Programs/PrimWorkshop/frmBrowser.cs b/Programs/PrimWorkshop/frmBrowser.cs
index 4e6aa76e..60082cd8 100644
--- a/Programs/PrimWorkshop/frmBrowser.cs
+++ b/Programs/PrimWorkshop/frmBrowser.cs
@@ -20,8 +20,8 @@ public partial class frmBrowser : Form
const float DEG_TO_RAD = 0.0174532925f;
const uint TERRAIN_START = (uint)Int32.MaxValue + 1;
- ContextMenu ExportPrimMenu;
- ContextMenu ExportTerrainMenu;
+ ContextMenuStrip ExportPrimMenu;
+ ContextMenuStrip ExportTerrainMenu;
GridClient Client;
Camera Camera;
@@ -82,14 +82,14 @@ public frmBrowser()
cboServer.SelectedIndex = 0;
// Context menus
- ExportPrimMenu = new ContextMenu();
- ExportPrimMenu.MenuItems.Add("Download", new EventHandler(DownloadMenu_Clicked));
- ExportPrimMenu.MenuItems.Add("Download All Objects", new EventHandler(DownloadAllMenu_Clicked));
- ExportTerrainMenu = new ContextMenu();
- ExportTerrainMenu.MenuItems.Add("Teleport", new EventHandler(TeleportMenu_Clicked));
- ExportTerrainMenu.MenuItems.Add("Export Terrain", new EventHandler(ExportTerrainMenu_Clicked));
- ExportTerrainMenu.MenuItems.Add("Import Object", new EventHandler(ImportObjectMenu_Clicked));
- ExportTerrainMenu.MenuItems.Add("Import Sim", new EventHandler(ImportSimMenu_Clicked));
+ ExportPrimMenu = new ContextMenuStrip();
+ ExportPrimMenu.Items.Add("Download", null,new EventHandler(DownloadMenu_Clicked) );
+ ExportPrimMenu.Items.Add("Download All Objects",null, new EventHandler(DownloadAllMenu_Clicked));
+ ExportTerrainMenu = new ContextMenuStrip();
+ ExportTerrainMenu.Items.Add("Teleport", null, new EventHandler(TeleportMenu_Clicked));
+ ExportTerrainMenu.Items.Add("Export Terrain",null, new EventHandler(ExportTerrainMenu_Clicked));
+ ExportTerrainMenu.Items.Add("Import Object",null, new EventHandler(ImportObjectMenu_Clicked));
+ ExportTerrainMenu.Items.Add("Import Sim",null, new EventHandler(ImportSimMenu_Clicked));
// Setup a timer for updating the progress bar
ProgressTimer = new System.Timers.Timer(250);
@@ -556,14 +556,14 @@ private void DownloadMenu_Clicked(object sender, EventArgs e)
{
// This should have already been fixed in the picking processing code
Console.WriteLine("Download menu clicked when a child prim is selected!");
- glControl.ContextMenu = null;
+ glControl.ContextMenuStrip = null;
LastHit = 0;
}
}
else
{
Console.WriteLine("Download menu clicked when there is no selected prim!");
- glControl.ContextMenu = null;
+ glControl.ContextMenuStrip = null;
LastHit = 0;
}
}
@@ -696,7 +696,7 @@ private void TeleportMenu_Clicked(object sender, EventArgs e)
else
{
// This shouldn't have happened...
- glControl.ContextMenu = null;
+ glControl.ContextMenuStrip = null;
}
}
}
@@ -867,7 +867,7 @@ private void StopPicking()
else
{
LastHit = 0;
- glControl.ContextMenu = null;
+ glControl.ContextMenuStrip = null;
}
}
@@ -903,7 +903,7 @@ private void ProcessHits(int hits, uint[] selectBuffer)
if (LastHit >= TERRAIN_START)
{
// Terrain was clicked on, turn off the context menu
- glControl.ContextMenu = ExportTerrainMenu;
+ glControl.ContextMenuStrip = ExportTerrainMenu;
}
else
{
@@ -922,7 +922,7 @@ private void ProcessHits(int hits, uint[] selectBuffer)
if (RenderPrimList.TryGetValue(render.Prim.ParentID, out renderParent))
{
// Turn on the context menu
- glControl.ContextMenu = ExportPrimMenu;
+ glControl.ContextMenuStrip = ExportPrimMenu;
// Change the clicked on prim to the parent. Camera position stays on the
// clicked child but the highlighting is applied to all the children
diff --git a/Programs/VisualParamGenerator/VisualParamGenerator.csproj b/Programs/VisualParamGenerator/VisualParamGenerator.csproj
index 6d4e1ad7..cba7b22f 100644
--- a/Programs/VisualParamGenerator/VisualParamGenerator.csproj
+++ b/Programs/VisualParamGenerator/VisualParamGenerator.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
True
1591,1574,0419,0618
diff --git a/Programs/VoiceTest/VoiceTest.csproj b/Programs/VoiceTest/VoiceTest.csproj
index 014fa068..8292f5e3 100644
--- a/Programs/VoiceTest/VoiceTest.csproj
+++ b/Programs/VoiceTest/VoiceTest.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
True
1591,1574,0419,0618
diff --git a/Programs/WinGridProxy/AboutBox1.cs b/Programs/WinGridProxy/AboutBox1.cs
index e99af7b5..a120ac1f 100644
--- a/Programs/WinGridProxy/AboutBox1.cs
+++ b/Programs/WinGridProxy/AboutBox1.cs
@@ -32,7 +32,8 @@ public string AssemblyTitle
return titleAttribute.Title;
}
}
- return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
+
+ return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location);
}
}
diff --git a/Programs/WinGridProxy/FormWinGridProxy.cs b/Programs/WinGridProxy/FormWinGridProxy.cs
index 4193d3d7..e1652583 100644
--- a/Programs/WinGridProxy/FormWinGridProxy.cs
+++ b/Programs/WinGridProxy/FormWinGridProxy.cs
@@ -25,7 +25,7 @@
*/
using GridProxy;
-using Nwc.XmlRpc;
+using XmlRpcCore;
using OpenMetaverse;
using OpenMetaverse.Interfaces;
using OpenMetaverse.Packets;
@@ -309,7 +309,7 @@ private void ProxyManager_OnMessageLog(CapsRequest req, CapsStage stage)
}
else
{
- capsSession = new SessionEvent(req.RawResponse, req.ResponseHeaders, req.Info.URI, req.Info.CapType, proto);
+ capsSession = new SessionEvent(req.RawResponse, req.ResponseHeaders, req.Info.URI, req.Info.CapType, proto, req.ExtraInfo);
}
string[] s = { PacketCounter.ToString(), capsSession.TimeStamp.ToString("HH:mm:ss.fff"), capsSession.Protocol, capsSession.Name, capsSession.Length.ToString(), capsSession.Host, capsSession.ContentType };
diff --git a/Programs/WinGridProxy/ProxyManager.cs b/Programs/WinGridProxy/ProxyManager.cs
index 4a2a7a21..9993e5c2 100644
--- a/Programs/WinGridProxy/ProxyManager.cs
+++ b/Programs/WinGridProxy/ProxyManager.cs
@@ -25,7 +25,7 @@
*/
using GridProxy;
-using Nwc.XmlRpc;
+using XmlRpcCore;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
@@ -170,30 +170,37 @@ private bool CapsHandler(CapsRequest req, CapsStage stage)
///
private bool EventQueueGetHandler(CapsRequest req, CapsStage stage)
{
- if (stage == CapsStage.Response && req.Response is OSDMap)
+ if (stage == CapsStage.Response && req.Response is OSDMap map)
{
- OSDMap map = (OSDMap)req.Response;
+ if (OnEventMessageLog is null)
+ return false;
- if (map.ContainsKey("events"))
+ if (map.TryGetValue("events", out OSD tmposd))
{
- OSDArray eventsArray = (OSDArray)map["events"];
+ OSDArray eventsArray = (OSDArray)tmposd;
+ int EventID = 0;
+ if(map.TryGetValue("id", out OSD idsd))
+ EventID = idsd.AsInteger();
+
+ int events = eventsArray.Count;
for (int i = 0; i < eventsArray.Count; i++)
{
OSDMap bodyMap = (OSDMap)eventsArray[i];
- if (OnEventMessageLog != null)
- {
- CapInfo capInfo = new CapInfo(req.Info.URI, req.Info.Sim, bodyMap["message"].AsString());
- CapsRequest capReq = new CapsRequest(capInfo);
- capReq.RequestHeaders = req.RequestHeaders;
- capReq.ResponseHeaders = req.ResponseHeaders;
- capReq.Request = null;// req.Request;
- capReq.RawRequest = null;// req.RawRequest;
- capReq.RawResponse = OSDParser.SerializeLLSDXmlBytes(bodyMap);
- capReq.Response = bodyMap;
-
- OnEventMessageLog(capReq, CapsStage.Response);
- }
+
+ CapInfo capInfo = new CapInfo(req.Info.URI, req.Info.Sim, bodyMap["message"].AsString());
+ CapsRequest capReq = new CapsRequest(capInfo)
+ {
+ RequestHeaders = req.RequestHeaders,
+ ResponseHeaders = req.ResponseHeaders,
+ Request = null,// req.Request;
+ RawRequest = null,// req.RawRequest;
+ RawResponse = OSDParser.SerializeLLSDXmlBytes(bodyMap),
+ Response = bodyMap
+ };
+ capReq.ExtraInfo = $"Event iD {EventID} Message {i + 1}/{events}";
+
+ OnEventMessageLog?.Invoke(capReq, CapsStage.Response);
}
}
}
diff --git a/Programs/WinGridProxy/SessionTypes.cs b/Programs/WinGridProxy/SessionTypes.cs
index 16838b09..d95be245 100644
--- a/Programs/WinGridProxy/SessionTypes.cs
+++ b/Programs/WinGridProxy/SessionTypes.cs
@@ -38,7 +38,7 @@
using OpenMetaverse.StructuredData;
using GridProxy;
-using Nwc.XmlRpc;
+using XmlRpcCore;
namespace WinGridProxy
{
@@ -76,7 +76,7 @@ public virtual string ToRawString(Direction direction)
public virtual byte[] ToBytes(Direction direction)
{
- return OpenMetaverse.Utils.EmptyBytes;
+ return Array.Empty();
}
public virtual string ToXml(Direction direction)
@@ -203,12 +203,12 @@ public SessionCaps(byte[] requestBytes, byte[] responseBytes,
if (requestBytes != null)
RequestBytes = requestBytes;
else
- RequestBytes = OpenMetaverse.Utils.EmptyBytes;
+ RequestBytes = Array.Empty();
if (responseBytes != null)
ResponseBytes = responseBytes;
else
- ResponseBytes = OpenMetaverse.Utils.EmptyBytes;
+ ResponseBytes = Array.Empty();
RequestHeaders = requestHeaders;
ResponseHeaders = responseHeaders;
Protocol = proto;
@@ -666,10 +666,11 @@ internal class SessionEvent : Session
{
private byte[] ResponseBytes;
private WebHeaderCollection ResponseHeaders;
+ private string ExtraInfo;
public SessionEvent() : base() { this.Protocol = "EventQ"; }
public SessionEvent(byte[] responseBytes, WebHeaderCollection responseHeaders,
- String uri, String capsKey, String proto)
+ String uri, String capsKey, String proto, string ExtraInfo)
: base()
{
this.Protocol = proto;
@@ -680,10 +681,8 @@ public SessionEvent(byte[] responseBytes, WebHeaderCollection responseHeaders,
this.Name = capsKey;
this.ContentType = responseHeaders.Get("Content-Type");
var ContentLength = responseHeaders.Get("Content-Length");
- if (ContentLength != null)
- this.Length = Int32.Parse(ContentLength);
- else
- this.Length = 0;
+ this.Length = ContentLength is null ? 0 : Int32.Parse (ContentLength);
+ this.ExtraInfo = ExtraInfo;
}
public override string ToPrettyString(Direction direction)
@@ -729,9 +728,16 @@ public override string ToRawString(Direction direction)
StringBuilder result = new StringBuilder();
foreach (String key in ResponseHeaders.Keys)
{
- result.AppendFormat("{0} {1}" + Environment.NewLine, key, ResponseHeaders[key]);
+ //result.AppendFormat("{0} {1}" + Environment.NewLine, key, ResponseHeaders[key]);
+ result.AppendLine($"{key} {ResponseHeaders[key]}");
}
result.AppendLine();
+ if (!string.IsNullOrEmpty(this.ExtraInfo))
+ {
+ result.Append(this.ExtraInfo);
+ result.AppendLine();
+ result.AppendLine();
+ }
result.AppendLine(this.ToXml(direction));
return result.ToString();
}
diff --git a/Programs/WinGridProxy/WinGridProxy.csproj b/Programs/WinGridProxy/WinGridProxy.csproj
index d8a2ca26..c8ac894d 100644
--- a/Programs/WinGridProxy/WinGridProxy.csproj
+++ b/Programs/WinGridProxy/WinGridProxy.csproj
@@ -1,7 +1,8 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
WinGridProxy
OpenMetaverse
@@ -13,7 +14,7 @@
True
-
+
@@ -21,13 +22,6 @@
False
..\..\bin\Be.Windows.Forms.HexBox.dll
-
- False
-
-
- False
- ..\..\bin\XMLRPC.dll
-
diff --git a/Programs/examples/Dashboard/Dashboard.csproj b/Programs/examples/Dashboard/Dashboard.csproj
index cfe23f15..3e1ef3d1 100644
--- a/Programs/examples/Dashboard/Dashboard.csproj
+++ b/Programs/examples/Dashboard/Dashboard.csproj
@@ -1,16 +1,12 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
True
1591,1574,0419,0618
-
-
- False
-
-
diff --git a/Programs/examples/GridAccountant/GridAccountant.csproj b/Programs/examples/GridAccountant/GridAccountant.csproj
index d8ffd302..ecae4198 100644
--- a/Programs/examples/GridAccountant/GridAccountant.csproj
+++ b/Programs/examples/GridAccountant/GridAccountant.csproj
@@ -1,7 +1,8 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
1591,1574,0419,0618
True
@@ -10,11 +11,6 @@
-
-
- False
-
-
diff --git a/Programs/examples/Heightmap/Heightmap.csproj b/Programs/examples/Heightmap/Heightmap.csproj
index a54e86a1..514f0460 100644
--- a/Programs/examples/Heightmap/Heightmap.csproj
+++ b/Programs/examples/Heightmap/Heightmap.csproj
@@ -1,16 +1,13 @@
Local
- net48
+ net6.0-windows
+ true
+ true
WinExe
1591,1574,0419,0618
True
-
-
- False
-
-
diff --git a/Programs/examples/IRCGateway/IRCGateway.csproj b/Programs/examples/IRCGateway/IRCGateway.csproj
index 5dc17432..fc2305dc 100644
--- a/Programs/examples/IRCGateway/IRCGateway.csproj
+++ b/Programs/examples/IRCGateway/IRCGateway.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
True
1591,1574,0419,0618
diff --git a/Programs/examples/PacketDump/PacketDump.csproj b/Programs/examples/PacketDump/PacketDump.csproj
index 5dc17432..fc2305dc 100644
--- a/Programs/examples/PacketDump/PacketDump.csproj
+++ b/Programs/examples/PacketDump/PacketDump.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
True
1591,1574,0419,0618
diff --git a/Programs/examples/TestClient/TestClient.csproj b/Programs/examples/TestClient/TestClient.csproj
index 597fa047..359b2d05 100644
--- a/Programs/examples/TestClient/TestClient.csproj
+++ b/Programs/examples/TestClient/TestClient.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
TestClient
TestClient
@@ -9,11 +9,6 @@
True
1591,1574,0419,0618
-
-
- False
-
-
diff --git a/Programs/examples/groupmanager/groupmanager.csproj b/Programs/examples/groupmanager/groupmanager.csproj
index 359d27d6..8ae1ae36 100644
--- a/Programs/examples/groupmanager/groupmanager.csproj
+++ b/Programs/examples/groupmanager/groupmanager.csproj
@@ -1,16 +1,12 @@
Local
- net48
+ net6.0-windows
+ true
WinExe
1591,1574,0419,0618
True
-
-
- False
-
-
diff --git a/Programs/importprimscript/importprimscript.csproj b/Programs/importprimscript/importprimscript.csproj
index 55fb072e..2985612f 100644
--- a/Programs/importprimscript/importprimscript.csproj
+++ b/Programs/importprimscript/importprimscript.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
1591,1574,0419,0618
True
diff --git a/Programs/mapgenerator/ProtocolManager.cs b/Programs/mapgenerator/ProtocolManager.cs
index 659822a0..6196857a 100644
--- a/Programs/mapgenerator/ProtocolManager.cs
+++ b/Programs/mapgenerator/ProtocolManager.cs
@@ -656,9 +656,9 @@ private void LoadMapFile(string mapFile)
r.Close();
map.Close();
}
- catch (Exception e)
+ catch (Exception)
{
- throw e;
+ throw;
}
}
diff --git a/Programs/mapgenerator/mapgenerator.csproj b/Programs/mapgenerator/mapgenerator.csproj
index 10acbb0f..07225ee6 100644
--- a/Programs/mapgenerator/mapgenerator.csproj
+++ b/Programs/mapgenerator/mapgenerator.csproj
@@ -1,7 +1,7 @@
Local
- net48
+ net6.0
Exe
True
1591,1574,0419,0618
diff --git a/bin/AvatarPreview.runtimeconfig.json b/bin/AvatarPreview.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/AvatarPreview.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/Baker.runtimeconfig.json b/bin/Baker.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/Baker.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/Dashboard.runtimeconfig.json b/bin/Dashboard.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/Dashboard.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/GridAccountant.runtimeconfig.json b/bin/GridAccountant.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/GridAccountant.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/GridImageUpload.runtimeconfig.json b/bin/GridImageUpload.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/GridImageUpload.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/GridProxyApp.runtimeconfig.json b/bin/GridProxyApp.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/GridProxyApp.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/Heightmap.runtimeconfig.json b/bin/Heightmap.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/Heightmap.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/ICSharpCode.SharpZipLib.dll b/bin/ICSharpCode.SharpZipLib.dll
index 536337c2..3b268b7c 100755
Binary files a/bin/ICSharpCode.SharpZipLib.dll and b/bin/ICSharpCode.SharpZipLib.dll differ
diff --git a/bin/IRCGateway.runtimeconfig.json b/bin/IRCGateway.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/IRCGateway.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/OpenMetaverse.dll.config b/bin/OpenMetaverse.dll.config
index 6b7b9993..20b1df5e 100755
--- a/bin/OpenMetaverse.dll.config
+++ b/bin/OpenMetaverse.dll.config
@@ -1,7 +1,9 @@
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/bin/PacketDump.runtimeconfig.json b/bin/PacketDump.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/PacketDump.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/PrimWorkshop.runtimeconfig.json b/bin/PrimWorkshop.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/PrimWorkshop.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/TestClient.runtimeconfig.json b/bin/TestClient.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/TestClient.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/VisualParamGenerator.runtimeconfig.json b/bin/VisualParamGenerator.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/VisualParamGenerator.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/VoiceTest.runtimeconfig.json b/bin/VoiceTest.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/VoiceTest.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/WinGridProxy.runtimeconfig.json b/bin/WinGridProxy.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/WinGridProxy.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/XMLRPC.dll b/bin/XMLRPC.dll
deleted file mode 100755
index 2189d090..00000000
Binary files a/bin/XMLRPC.dll and /dev/null differ
diff --git a/bin/groupmanager.runtimeconfig.json b/bin/groupmanager.runtimeconfig.json
new file mode 100644
index 00000000..1b351ac9
--- /dev/null
+++ b/bin/groupmanager.runtimeconfig.json
@@ -0,0 +1,19 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ {
+ "name": "Microsoft.WindowsDesktop.App",
+ "version": "6.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/importprimscript.runtimeconfig.json b/bin/importprimscript.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/importprimscript.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/log4net.dll b/bin/log4net.dll
deleted file mode 100755
index ffc57e11..00000000
Binary files a/bin/log4net.dll and /dev/null differ
diff --git a/bin/mapgenerator.runtimeconfig.json b/bin/mapgenerator.runtimeconfig.json
new file mode 100644
index 00000000..e355688b
--- /dev/null
+++ b/bin/mapgenerator.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/libopenjpeg-dotnet-2-1.5.0-dotnet-1-x86_64.so b/bin/openjpeg-dotnet-x86_64.so
old mode 100755
new mode 100644
similarity index 100%
rename from bin/libopenjpeg-dotnet-2-1.5.0-dotnet-1-x86_64.so
rename to bin/openjpeg-dotnet-x86_64.so
diff --git a/bin/openjpeg-dotnet.dll b/bin/openjpeg-dotnet.dll
index 6377b8d9..677b1350 100755
Binary files a/bin/openjpeg-dotnet.dll and b/bin/openjpeg-dotnet.dll differ
diff --git a/bin/libopenjpeg-dotnet-2-1.5.0-dotnet-1.dylib b/bin/openjpeg-dotnet.dylib
old mode 100755
new mode 100644
similarity index 100%
rename from bin/libopenjpeg-dotnet-2-1.5.0-dotnet-1.dylib
rename to bin/openjpeg-dotnet.dylib
diff --git a/bin/libopenjpeg-dotnet-2-1.5.0-dotnet-1-i686.so b/bin/openjpeg-dotnet.so
old mode 100755
new mode 100644
similarity index 100%
rename from bin/libopenjpeg-dotnet-2-1.5.0-dotnet-1-i686.so
rename to bin/openjpeg-dotnet.so
diff --git a/bin/openmetaverse_data/avatar_lad.xml b/bin/openmetaverse_data/avatar_lad.xml
index 5d6b10c0..0c3fa9d4 100644
--- a/bin/openmetaverse_data/avatar_lad.xml
+++ b/bin/openmetaverse_data/avatar_lad.xml
@@ -1,6 +1,6 @@
+ version="2.0" wearable_definition_version="22">
@@ -21,6 +22,7 @@
pie_slice="2"
name="Skull"
joint="mHead"
+ location="ATTACH_HEAD"
position="0 0 0.15"
rotation="0 0 90"
visible_in_first_person="false" />
@@ -28,9 +30,10 @@
@@ -38,18 +41,21 @@
@@ -78,9 +87,10 @@
@@ -91,6 +101,7 @@
pie_slice="7"
name="Spine"
joint="mChest"
+ location="ATTACH_BACK"
position="-0.15 0 -0.1"
rotation="0 -90 90"
visible_in_first_person="true" />
@@ -101,6 +112,7 @@
pie_slice="6"
name="Pelvis"
joint="mPelvis"
+ location="ATTACH_PELVIS"
position="0 0 -0.15"
rotation="0 0 0"
visible_in_first_person="true" />
@@ -111,6 +123,7 @@
pie_slice="6"
name="Mouth"
joint="mHead"
+ location="ATTACH_MOUTH"
position="0.12 0 0.001"
rotation="0 0 0"
visible_in_first_person="false"/>
@@ -121,6 +134,7 @@
pie_slice="7"
name="Chin"
joint="mHead"
+ location="ATTACH_CHIN"
position="0.12 0 -0.04"
rotation="0 0 0"
visible_in_first_person="false" />
@@ -131,6 +145,7 @@
pie_slice="4"
name="Left Ear"
joint="mHead"
+ location="ATTACH_LEAR"
position="0.015 0.08 0.017"
rotation="0 0 0"
visible_in_first_person="false" />
@@ -141,6 +156,7 @@
pie_slice="0"
name="Right Ear"
joint="mHead"
+ location="ATTACH_REAR"
position="0.015 -0.08 0.017"
rotation="0 0 0"
visible_in_first_person="false" />
@@ -151,6 +167,7 @@
pie_slice="3"
name="Left Eyeball"
joint="mEyeLeft"
+ location="ATTACH_LEYE"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="false"/>
@@ -161,6 +178,7 @@
pie_slice="1"
name="Right Eyeball"
joint="mEyeRight"
+ location="ATTACH_REYE"
position="0 0 0"
rotation="0 0 0"
visible_in_first_person="false" />
@@ -171,6 +189,7 @@
pie_slice="5"
name="Nose"
joint="mHead"
+ location="ATTACH_NOSE"
position="0.1 0 0.05"
rotation="0 0 0"
visible_in_first_person="false"/>
@@ -178,9 +197,10 @@
@@ -188,9 +208,10 @@
@@ -198,9 +219,10 @@
@@ -208,9 +230,10 @@
@@ -218,9 +241,10 @@
@@ -228,9 +252,10 @@
@@ -238,9 +263,10 @@
@@ -248,9 +274,10 @@
@@ -258,9 +285,10 @@
@@ -268,9 +296,10 @@
@@ -281,6 +310,7 @@
pie_slice="5"
name="Stomach"
joint="mPelvis"
+ location="ATTACH_BELLY"
position="0.092 0.0 0.088"
rotation="0 0 0"
visible_in_first_person="true" />
@@ -291,6 +321,7 @@
pie_slice="3"
name="Left Pec"
joint="mTorso"
+ location="ATTACH_LEFT_PEC"
position="0.104 0.082 0.247"
rotation="0 0 0"
visible_in_first_person="true" />
@@ -301,15 +332,17 @@
pie_slice="1"
name="Right Pec"
joint="mTorso"
+ location="ATTACH_RIGHT_PEC"
position="0.104 -0.082 0.247"
rotation="0 0 0"
visible_in_first_person="true" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name="mSpine3"
+ scale="0 0 .05" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -514,8 +771,12 @@
scale="0 0 0.05" />
+ name="mSpine3"
+ scale="0 0 0.05" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -586,10 +937,26 @@
name="mTorso"
scale="0.1 0.1 0" />
+
+
+
+
+
+
+
+
@@ -605,6 +972,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -643,6 +1041,17 @@
+
+
+
+
+
@@ -650,7 +1059,7 @@
id="37"
group="0"
name="Hip Width"
- label="Hip Width"
+ label="Hip Width"
wearable="shape"
edit_group="shape_legs"
edit_group_order="3"
@@ -665,6 +1074,14 @@
name="mPelvis"
scale="0 0.1 0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -693,7 +1129,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -732,6 +1196,26 @@
+
+
+
+
+
+
+
+
+
+
@@ -755,10 +1239,82 @@
name="mEyeRight"
scale="0 0 0"
offset="0 -.009 0" />
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -801,9 +1507,10 @@
name="mEyeRight"
scale="0 0 0"
offset=".016 0 0" />
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -831,7 +1612,7 @@
id="655"
group="1"
name="Head Size"
- label="Head Size"
+ label="Head Size"
wearable="shape"
edit_group="shape_head"
label_min="Small Head"
@@ -840,6 +1621,36 @@
value_min="-.25"
value_max=".10">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+ name="mFaceEyeAltLeft"
+ scale="1 1 1"
+ offset="0 0 -0.001" />
-
-
-
-
-
+ name="mFaceEyeAltRight"
+ scale="1 1 1"
+ offset="0 0 -0.001" />
+
+ name="mFaceForeheadLeft"
+ scale="1 1 1"
+ offset="0 0 0" />
-
-
+ name="mFaceForeheadCenter"
+ scale="1 1 1"
+ offset="0 0 0" />
-
-
-
-
-
-
-
-
-
-
+ name="mFaceEyebrowInnerLeft"
+ scale="1 1 1"
+ offset="0 0 0" />
+ name="mFaceEyebrowOuterRight"
+ scale="1 1 1"
+ offset="0 0 0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ id="197"
+ group="1"
+ wearable="shoes"
+ name="Shoe_Heels"
+ edit_group="shoes"
+ label_min="No Heels"
+ label_max="High Heels"
+ value_min="0"
+ value_max="1">
+ name="mFootRight"
+ scale="0 0 0"
+ offset="0 0 -.08" />
+ name="mFootLeft"
+ scale="0 0 0"
+ offset="0 0 -.08" />
+ name="mHindLimb4Left"
+ scale="0 0 0"
+ offset="0 0 -.08" />
+ name="mHindLimb4Right"
+ scale="0 0 0"
+ offset="0 0 -.08" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit_group_order="10"
+ label_min="Small Hands"
+ label_max="Large Hands"
+ value_min="-.3"
+ value_max=".3"
+ camera_elevation=".1"
+ camera_distance="1.4"
+ camera_angle="0">
+ name="mWristRight"
+ scale="1 1 1"
+ offset="0 0 0" />
+ name="mWristLeft"
+ scale="1 1 1"
+ offset="0 0 0" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ scale="1 1 0"
+ offset="0 0 0" />
-
-
-
-
-
-
-
-
-
-
-
-
+ value_max="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ camera_distance="2.5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_default=".6"
+ camera_distance="1.5">
+
+
+
+
+
+
+
+
+
-
+ value_default="0"
+ camera_elevation=".3"
+ camera_distance=".8"
+ camera_angle="15">
+
+
+
-
+
-
+ value_default="0"
+ camera_distance="2.5">
+
+
+
+
+
+
+
+
+
+
+
-
+ id="30004"
+ group="1"
+ name="Broad_Nostrils"
+ value_min="-.5"
+ value_max="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ id="30517"
+ group="1"
+ name="Wide_Nose"
+ value_min="-.5"
+ value_max="1">
+
+
+
+
+
-
-
+ id="30656"
+ group="1"
+ name="Crooked_Nose"
+ value_min="-2"
+ value_max="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ name="Lip Width"
+ value_min="-0.9"
+ value_max="1.3"
+ value_default="0">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ name="Tall_Lips"
+ value_min="-1"
+ value_max="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_max="0.7">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_max="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_max="1.5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_max="1.5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_max="1.4">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_max="1.4">
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
+ value_max="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_max="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ name="Big_Ears"
+ value_min="-1"
+ value_max="2">
+
+
+
+
-
+
-
+ name="Ears_Out"
+ value_min="-.5"
+ value_max="1.5">
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+ id="30185"
+ group="1"
+ name="Deep_Chin"
+ value_min="-1"
+ value_max="1">
+
+
+
+
-
-
+
+
+
+
-
+
-
+ name="Jaw_Angle"
+ value_min="-1.2"
+ value_max="2"
+ value_default="0">
+
+
+
-
+
+
-
-
+ name="Jaw_Jut"
+ value_min="-2"
+ value_max="2">
+
-
-
-
+
+
+
+
+
+
-
+ name="Bulbous_Nose_Tip"
+ value_min="-1"
+ value_max="1.5">
+
+
+
+
-
+
-
+ name="Weak_Chin"
+ value_min="-.5"
+ value_max=".5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
+
-
-
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
-
-
+
-
+
-
-
+ name="Eyelid_Corner_Up"
+ value_min="-1.3"
+ value_max="1.2">
+
+
-
-
+
+
-
+
-
-
+ name="Eyelid_Inner_Corner_Up"
+ value_min="-1.3"
+ value_max="1.2">
+
+
+
+
+
+
-
+ name="Puffy_Lower_Lids"
+ value_min="-.3"
+ value_max="2.5">
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+ value_max="2">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ id="30011"
+ group="1"
+ name="Noble_Nose_Bridge"
+ value_min="-.5"
+ value_max="1.5">
+
+
+
+
+
+
+
-
+ id="30758"
+ group="1"
+ name="Lower_Bridge_Nose"
+ value_min="-1.5"
+ value_max="1.5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_default="0.5">
+
-
-
-
+
+
+
+
+
+
-
+ id="30010"
+ group="1"
+ name="Sunken_Cheeks"
+ value_min="-1.5"
+ value_max="3">
+
+
+
+
+
+
-
-
+ id="30017"
+ group="1"
+ name="Square_Jaw"
+ value_min="-0.5"
+ value_max="1">
+
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_max="2.5">
+
-
-
-
+
+
+
+
+
+
-
+ id="30021"
+ group="1"
+ name="Upper_Eyelid_Fold"
+ value_min="-0.2"
+ value_max="1.3">
+
+
+
+
+
+
+
-
-
+ value_max="1.5">
+
-
-
+
+
+
+
+
-
-
+ value_max="1">
+
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_default="0">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_default="0.5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ id="30031"
+ group="1"
+ name="Arced_Eyebrows"
+ value_min="0"
+ value_max="2"
+ value_default=".5">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ id="30757"
+ group="1"
+ name="Lower_Eyebrows"
+ value_min="-4"
+ value_max="2"
+ value_default="-1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ camera_distance=".5"
+ camera_angle="20">
+ camera_distance=".5"
+ camera_angle="20">
+ camera_distance=".5"
+ camera_angle="90">
+ camera_distance=".5"
+ camera_angle="90">
+ camera_distance=".7"
+ camera_angle="90">
+ camera_distance=".5"
+ camera_angle="20">
+ name="Hair_Part_Middle"
+ label="Middle Part"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="17"
+ label_min="No Part"
+ label_max="Part"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ name="Hair_Part_Right"
+ label="Right Part"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="18"
+ label_min="No Part"
+ label_max="Part"
+ value_min="0"
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ camera_distance=".5"
+ camera_angle="20">
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ clothing_morph="true"
+ name="Bangs_Front_Down"
+ label="Front Bangs Down"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Bangs"
+ label_max="Bangs Down"
+ value_min="0"
+ value_max="5"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ name="Bangs_Sides_Up"
+ label="Side Bangs Up"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Side Bangs"
+ label_max="Side Bangs Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
-
+ value_max="2"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
-
+ edit_group="hair_style"
+ label_min="Back Bangs"
+ label_max="Back Bangs Up"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
-
-
-
-
-
-
-
-
+ camera_distance=".5"
+ camera_angle="150">
-
-
-
+
@@ -2589,12 +4802,14 @@
+ name="Hair_Back_Down"
+ label="Back Hair Down"
+ clothing_morph="true"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Back Hair"
+ label_max="Back Hair Down"
+ value_min="0"
+ value_max="3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="150">
+ wearable="hair"
+ clothing_morph="true"
+ edit_group="hair_style"
+ edit_group_order="14.5"
+ label_min="Smooth Hair"
+ label_max="Rumpled Hair"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
-
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="90">
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ id="191"
+ group="1"
+ name="Hair_Tilt_Left"
+ label="Hair Tilted Left"
+ wearable="hair"
+ edit_group="hair_style"
+ label_min="Hair"
+ label_max="Tilt Left"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
+ id="192"
+ group="0"
+ name="Bangs_Part_Middle"
+ label="Part Bangs"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="20"
+ label_min="No Part"
+ label_max="Part Bangs"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="0">
-
+ id="640"
+ group="1"
+ name="Hair_Egg_Head"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="-1.3"
+ value_max="1">
+ id="641"
+ group="1"
+ name="Hair_Squash_Stretch_Head"
+ wearable="hair"
+ edit_group="hair_style"
+ cross_wearable="true"
+ value_min="-.5"
+ value_max="1">
+ value_max="1">
+ value_max="1">
+ value_max="1">
+ value_max="1">
+ value_max="2">
-
-
-
+ value_max="1">
+
+ value_default="-0.3"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="100">
+ camera_distance=".5"
+ camera_angle="30">
-
-
-
-
-
-
-
-
+ camera_angle="160">
+ id="755"
+ group="0"
+ name="Hair_Taper_Front"
+ wearable="hair"
+ edit_group="hair_style"
+ edit_group_order="13"
+ label="Taper Front"
+ label_min="Wide Front"
+ label_max="Narrow Front"
+ value_min="-1.5"
+ value_max="1.5"
+ value_default="0.05"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name="Big_Brow"
+ value_min="-.3"
+ value_max="2">
+ name="Nose_Big_Out"
+ value_min="-0.8"
+ value_max="2.5">
+ name="Bulbous_Nose"
+ value_min="-.5"
+ value_max="1.5">
-
+
+ name="Crooked_Nose"
+ value_min="-2"
+ value_max="2">
-
+
+ name="Tall_Lips"
+ value_min="-1"
+ value_max="2">
-
+
+ name="Mouth_Height"
+ value_min="-2"
+ value_max="2">
-
+
-
-
+ name="Lip_Cleft_Deep"
+ value_min="-.5"
+ value_max="1.2">
+
+
-
+ name="Wide_Lip_Cleft"
+ value_min="-.8"
+ value_max="1.5">
+
-
+
+ name="Shift_Mouth"
+ value_min="-2"
+ value_max="2"
+ value_default="0">
-
+
-
+ name="Big_Ears"
+ value_min="-1"
+ value_max="2">
+
-
+
-
+ name="Ears_Out"
+ value_min="-.5"
+ value_max="1.5">
+
-
-
-
+
+ name="Pointy_Ears"
+ value_min="-.4"
+ value_max="3">
-
+
-
-
+
+ name="Jaw_Jut"
+ value_min="-2"
+ value_max="2">
-
+
+ name="Wide_Eyes"
+ value_min="-1.5"
+ value_max="2">
-
-
+
+ name="Eyelid_Corner_Up"
+ value_min="-1.3"
+ value_max="1.2">
-
+
+ name="Puffy_Lower_Lids"
+ value_min="-.3"
+ value_max="2.5">
+ name="Low_Septum_Nose"
+ value_min="-1"
+ value_max="1.5"
+ value_default="0.5">
+ id="5"
+ group="0"
+ name="Cleft_Chin"
+ label="Chin Cleft"
+ wearable="shape"
+ edit_group="shape_chin"
+ edit_group_order="6"
+ label_min="Round"
+ label_max="Cleft"
+ value_min="-.1"
+ value_max="1"
+ camera_elevation="0"
+ camera_distance=".28"
+ camera_angle="-20">
+ name="Weak_Chin"
+ value_min="-.5"
+ value_max=".5">
+ name="Double_Chin"
+ value_min="-.5"
+ value_max="1.5">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ name="Sunken_Cheeks"
+ value_min="-1.5"
+ value_max="3">
+ name="Noble_Nose_Bridge"
+ value_min="-.5"
+ value_max="1.5">
+ id="20758"
+ group="1"
+ name="Lower_Bridge_Nose"
+ value_min="-1.5"
+ value_max="1.5">
+ camera_distance=".4"
+ camera_angle="0">
+ edit_group="shape_chin"
+ edit_group_order="7"
+ label_min="Round"
+ label_max="Cleft"
+ value_min="0"
+ value_max="1.5"
+ camera_elevation="0"
+ camera_distance=".28"
+ camera_angle="-20">
+ name="High_Cheek_Bones"
+ value_min="-.5"
+ value_max="1">
+
+ camera_distance=".3">
+ name="Square_Jaw"
+ value_min="-.5"
+ value_max="1">
+ id="20018"
+ group="1"
+ name="Puffy_Upper_Cheeks"
+ value_min="-1.5"
+ value_max="2.5">
+ id="20019"
+ group="1"
+ name="Upturned_Nose_Tip"
+ value_min="-1.5"
+ value_max="1">
-
-
+
+ id="20021"
+ group="1"
+ name="Upper_Eyelid_Fold"
+ value_min="-0.2"
+ value_max="1.3">
+ edit_group="shape_ears"
+ edit_group_order="3"
+ label_min="Unattached"
+ label_max="Attached"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".3"
+ camera_angle="45">
+ name="Baggy_Eyes"
+ value_min="-.5"
+ value_max="1.5">
-
+ value_max=".7">
+ name="Wide_Nose_Bridge"
+ value_min="-1.3"
+ value_max="1.2">
+ value_max="2">
+ name="Wide_Upper_Lip"
+ wearable="shape"
+ edit_group="driven"
+ value_min="-.7"
+ value_max="1.3">
+ name="Wide_Lower_Lip"
+ wearable="shape"
+ edit_group="driven"
+ value_min="-.7"
+ value_max="1.3">
+
+
+ name="Lower_Eyebrows"
+ label="Eyebrow Height"
+ show_simple="true"
+ wearable="hair"
+ edit_group="hair_eyebrows"
+ edit_group_order="2.5"
+ label_min="Higher"
+ label_max="Lower"
+ value_min="-2"
+ value_max="2">
+ name="Egg_Head"
+ label="Egg Head"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Chin Heavy"
+ label_max="Forehead Heavy"
+ value_min="-1.3"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
-
+ name="Squash_Stretch_Head"
+ label="Squash/Stretch Head"
+ wearable="shape"
+ edit_group="shape_head"
+ label_min="Squash Head"
+ label_max="Stretch Head"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+
+
+
+ value_max=".7"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+ name="Eye_Spread"
+ wearable="shape"
+ edit_group="shape_eyes"
+ label_min="Eyes Together"
+ label_max="Eyes Spread"
+ value_min="-2"
+ value_max="2">
+ value_max="2">
-
+ value_max="1"
+ camera_elevation=".3">
+
+ id="20880"
+ group="1"
+ name="Eyelid_Inner_Corner_Up"
+ value_min="-1.3"
+ value_max="1.2">
-
-
+
+ value_max="1.4"
+ camera_distance=".3"
+ camera_elevation=".04">
-
+ value_max="1.2"
+ camera_distance=".3"
+ camera_elevation=".04">
+ value_max="1.5"
+ camera_distance=".3"
+ camera_elevation=".04">
-
-
-
-
-
-
-
+ value_max="1.5"
+ camera_distance=".3"
+ camera_elevation=".04">
+
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Shear Left"
+ label_max="Shear Right"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
-
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
+
+
+
+ id="664"
+ group="0"
+ name="Pop_Eye"
+ wearable="shape"
+ label="Eye Pop"
+ edit_group="shape_eyes"
+ edit_group_order="8"
+ label_min="Pop Right Eye"
+ label_max="Pop Left Eye"
+ value_min="-1.3"
+ value_max="1.3"
+ value_default="0"
+ camera_elevation=".1"
+ camera_distance=".35">
+
+
+
+
-
-
-
-
-
-
-
-
+ label="Eye Size"
+ edit_group="shape_eyes"
+ label_min="Beady Eyes"
+ label_max="Anime Eyes"
+ show_simple="true"
+ value_min="-2"
+ value_max="2"
+ value_default="0">
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+ value_max="1">
+
-
-
-
-
-
-
-
-
-
-
+ value_max="1">
+
-
-
-
-
-
-
-
-
-
-
-
-
+ value_max="1">
+
-
-
-
-
+ value_max="1">
+ value_max="1">
-
-
-
+ name="Express_Shrug_Emote"
+ value_min="0"
+ value_max="1">
+
+ id="306"
+ group="1"
+ name="Express_Kiss"
+ value_min="0"
+ value_max="1">
-
+
+ id="307"
+ group="1"
+ name="Express_Bored_Emote"
+ value_min="0"
+ value_max="1">
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+ value_min="0"
+ value_max="1">
+ name="Old"
+ value_min="0"
+ value_max="1">
+
+ name="Surprised_Eyebrows"
+ value_min="0"
+ value_max="1">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reference="avatar_head.llm">
+ reference="avatar_head.llm">
+ reference="avatar_head.llm">
+ reference="avatar_head.llm">
-
-
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Shear Left"
+ label_max="Shear Right"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
-
-
-
-
+ label="Shear Face"
+ edit_group="shape_head"
+ label_min="Flat Head"
+ label_max="Long Head"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04">
+
-
-
-
+ label="Eye Pop"
+ edit_group="shape_eyes"
+ edit_group_order="8"
+ label_min="Pop Right Eye"
+ label_max="Pop Left Eye"
+ value_min="-2"
+ value_max="2"
+ value_default="0"
+ camera_distance=".5"
+ camera_elevation=".04"
+ camera_angle="-20">
+
-
-
-
-
-
-
+ edit_group="shape_head"
+ label_min="Chin Heavy"
+ label_max="Forehead Heavy"
+ value_min="-1.3"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+
-
-
-
-
-
-
+ edit_group="shape_head"
+ label_min="Squash Head"
+ label_max="Stretch Head"
+ value_min="-.5"
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance=".5"
+ camera_angle="20">
+
+
+
+
+
-
-
-
-
-
-
+ label="Eyelash Length"
+ edit_group="shape_eyes"
+ edit_group_order="7"
+ label_min="Short"
+ label_max="Long"
+ value_min="-.3"
+ value_max="1.5"
+ camera_elevation=".1"
+ camera_distance=".30"
+ camera_angle="-20">
+
+ name="Head_Eyes_Big"
+ wearable="shape"
+ label="Eye Size"
+ edit_group="shape_eyes"
+ label_min="Beady Eyes"
+ label_max="Anime Eyes"
+ value_min="-2"
+ value_max="2"
+ show_simple="true"
+ value_default="0">
+ name="Bug_Eyed_Head"
+ wearable="shape"
+ label="Eye Depth"
+ edit_group="shape_eyes"
+ edit_group_order="4.5"
+ label_min="Sunken Eyes"
+ label_max="Bug Eyes"
+ value_min="-2"
+ value_max="2"
+ value_default="0">
+ shared="1"
+ id="20021"
+ group="1"
+ name="Upper_Eyelid_Fold"
+ value_min="-0.2"
+ value_max="1.3">
+ name="Wide_Eyes"
+ value_min="-1.5"
+ value_max="2">
+ name="Eyelid_Corner_Up"
+ value_min="-1.3"
+ value_max="1.2">
+
+
+
+
+
+ value_max="1">
+ value_max="1">
+ value_max="1">
-
-
-
-
+ shared="1"
+ id="304"
+ group="1"
+ name="Express_Embarrassed_Emote"
+ value_min="0"
+ value_max="1">
+
+ value_max="1">
+ value_max="1">
+ value_max="1">
+ value_max="1">
-
-
-
-
-
-
-
+
-
-
-
-
+ name="Express_Afraid_Emote"
+ value_min="0"
+ value_max="1">
+
+ shared="1"
+ id="312"
+ group="1"
+ name="Express_Cry_Emote"
+ value_min="0"
+ value_max="1">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ name="Express_Toothsmile"
+ value_min="0"
+ value_max="1">
-
-
-
-
-
-
-
+ name="Express_Smile"
+ value_min="0"
+ value_max="1">
+
+ name="Old"
+ value_min="0"
+ value_max="1">
-
-
-
-
+
+ name="Blink_Left"
+ value_min="0"
+ value_max="1">
+ name="Blink_Right"
+ value_min="0"
+ value_max="1">
+
-
+ type="upperBodyMesh"
+ lod="0"
+ file_name="avatar_upper_body.llm"
+ min_pixel_width="320">
+
-
+ edit_group="driven"
+ value_min="0"
+ value_max="1">
+
+
+
+
-
-
-
-
-
-
-
+ value_max="1"
+ camera_elevation=".1"
+ camera_distance="1"
+ camera_angle="15">
+
+
+
+
-
+ value_max="1"
+ camera_elevation="0"
+ camera_distance=".28">
+
+
+
+
-
+ value_max="1"
+ camera_elevation="0"
+ camera_distance=".28">
+
+
+
+
-
+ value_max="1.4"
+ camera_elevation=".3"
+ camera_distance="1.2">
+
+
+
+
+
+
+
+
-
-
-
-
-
+ value_max="1.4"
+ camera_elevation=".3"
+ camera_distance="1.2">
+
+
+
+
+
+
+
+
-
+ value_max="1.3"
+ camera_elevation=".3"
+ camera_distance="1.2">
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+ value_max="1.3"
+ camera_elevation=".3"
+ camera_distance="1.2">
+
+
+
+
+
+
+
+
+
+
+
-
+ camera_elevation=".3">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ id="840"
+ group="0"
+ name="Shirtsleeve_flair"
+ label="Sleeve Looseness"
+ show_simple="true"
+ wearable="shirt"
+ edit_group="shirt"
+ edit_group_order="6"
+ clothing_morph="true"
+ label_min="Tight Sleeves"
+ label_max="Loose Sleeves"
+ value_min="0"
+ value_max="1.5"
+ camera_distance="1.8"
+ camera_angle="30"
+ camera_elevation="-.3">
-
-
+ value_max="2">
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ sex="female"
+ name="Breast_Female_Cleavage"
+ label="Breast Cleavage"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="8"
+ label_min="Separate"
+ label_max="Join"
+ value_default="0"
+ value_min="-.3"
+ value_max="1.3"
+ camera_elevation=".3"
+ camera_distance=".8">
+
+
+
+
-
+
-
-
-
+ sex="male"
+ name="Chest_Male_No_Pecs"
+ label="Pectorals"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="5"
+ label_min="Big Pectorals"
+ label_max="Sunken Chest"
+ value_default="0"
+ value_min="-0.5"
+ value_max="1.1"
+ camera_elevation=".3"
+ camera_distance="1.2">
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ value_max="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ value_max="1">
+
+
-
-
+
+
-
-
+ value_max="1">
+
+
-
-
+
+
-
-
+ value_max="1">
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+ value_max="1">
+
+
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
-
-
+
-
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+ value_max="1">
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
+
-
+
+
+
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
-
+
-
-
-
-
+
-
-
-
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
+
-
+
+
+
+
-
+
-
+
+
-
+
+
-
+
+
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
-
+
-
+
-
+
+
+
-
+
+
+
+
+
-
+
+
+
-
+
-
+
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ color="0, 0, 0, 255" />
+ color="255, 0, 0, 255" />
-
+ value_default="1">
+
+ color="0, 0, 0, 255" />
+ color="0, 255, 0, 255" />
-
+ value_default="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name="head bump definition"
+ render_pass="bump">
+
+
+
+
+ value_max="1">
+ domain="0" />
+
+
+
+
+
+
+
+
+
+
+
+
+ value_max="1">
+ color="0, 0, 0, 0" />
-
+ color="0, 0, 0, 128" />
+
+
+
-
-
+
+
-
-
-
+
+
+color="255, 255, 255, 0" />
+
-
+ color="255, 255, 255, 64" />
+
+
+
+
+
-
+
+
+ color="198, 71, 71, 0" />
-
+ color="198, 71, 71, 255" />
+
+
+
-
+
+
+
+
+
+ color="220, 115, 115, 0" />
-
+
+ name="wrinkles_shading"
+ render_pass="bump"
+ fixed_color="0,0,0,100">
+
+
+
+
+
+
+
+
+
+
+
+
+ tga_file="eyebrows_alpha.tga"
+ domain="0.1" />
-
-
-
-
-
-
-
-
-
-
-
-
+ color="255,255,255,0" />
+ color="255,255,255,255" />
-
-
-
-
-
-
-
-
-
+ value_max="1"
+ value_default="0.5">
-
-
-
-
+ color="255,255,255,0" />
+ color="255,255,255,255" />
-
-
-
-
-
-
-
-
-
-
+ name="lipstick">
+ value_default=".25"
+ camera_distance=".25">
+ color="245,161,177,200" />
-
-
+ color="216,37,67,200" />
-
-
+ color="178,48,76,200" />
-
-
+ color="68,0,11,200" />
-
-
+ color="252,207,184,200" />
-
-
+ color="241,136,106,200" />
-
+
+
-
+
-
-
-
-
-
-
+
+
+
+ value_max=".9"
+ value_default="0.0"
+ camera_distance=".25">
+ tga_file="lipstick_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
-
-
-
-
-
-
-
-
-
-
+ name="lipgloss"
+ fixed_color="255,255,255,190">
-
-
-
-
-
+ value_max="1"
+ camera_distance=".25">
+
-
+ name="blush">
+
+
+
+ value_max="1"
+ value_default=".5"
+ camera_distance=".3"
+ camera_elevation=".07"
+ camera_angle="20">
+ color="253,162,193,200" />
-
-
-
+ color="247,131,152,200" />
-
-
-
+
-
-
-
-
-
+
-
-
+
-
-
+ color="195,128,122,200" />
+ color="148,103,100,200" />
+
+
-
+ value_default=".5"
+ camera_distance=".3"
+ camera_elevation=".07"
+ camera_angle="20">
+
+ color="255,255,255,0" />
+ color="255,255,255,255" />
+
+
+ camera_distance=".3"
+ camera_elevation=".14">
+ color="252,247,246,255" />
-
-
+ color="255,206,206,255" />
-
+
+
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
-
+
-
-
+
-
-
+ color="223,227,213,255" />
-
-
+ color="96,116,87,255" />
-
-
+ color="88,143,107,255" />
-
-
+ color="194,231,223,255" />
-
-
+ color="207,227,234,255" />
-
-
+ color="41,171,212,255" />
-
-
-
+
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_default=".6"
+ camera_distance=".3"
+ camera_elevation=".14">
+
+
+
+
+
-
-
+ value_max=".7"
+ camera_distance=".3"
+ camera_elevation=".14">
+ domain="0.05" />
+
+
+ camera_distance=".3"
+ camera_elevation=".14">
+ color="252,247,246,255" />
+ color="255,206,206,255" />
+ color="233,135,149,255" />
+ color="220,168,192,255" />
+ color="228,203,232,255" />
+ color="255,234,195,255" />
+ color="230,157,101,255" />
+ color="255,147,86,255" />
-
-
-
+ color="228,110,89,255" />
-
-
+
-
-
-
+
-
-
-
-
+
-
-
+
-
-
+ color="194,231,223,255" />
-
-
+ color="207,227,234,255" />
-
-
+ color="41,171,212,255" />
+ color="180,137,130,255" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_default=".7"
+ camera_distance=".3"
+ camera_elevation=".14">
+
+ color="255,255,255,0" />
+ color="255,255,255,255" />
+ value_default="0"
+ camera_distance=".3"
+ camera_elevation=".14">
+ tga_file="eyeshadow_inner_alpha.tga"
+ skip_if_zero="true"
+ domain="0.2" />
+
+
+ value_default="0.0"
+ camera_distance=".3"
+ camera_elevation=".14">
+ tga_file="eyeliner_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
-
-
-
-
+ camera_distance=".3"
+ camera_elevation=".14">
+ color="24,98,40,250" />
+
+ color="9,100,127,250" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name="Sideburns bump"
+ value_min="0"
+ value_max="1">
+ domain="0.05" />
+ domain="0.1" />
+ domain="0.03" />
+
+
+
+
+
+
+
+
+ name="facialhair"
+ global_color="hair_color">
+
+ tga_file="head_hair.tga"
+ file_is_mask="false" />
+ value_max="1">
+ tga_file="facehair_sideburns_alpha.tga"
+ skip_if_zero="true"
+ domain="0.05" />
+ tga_file="facehair_soulpatch_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
+ tga_file="facehair_chincurtains_alpha.tga"
+ skip_if_zero="true"
+ domain="0.03" />
+
+
+
+
+
+
+
+
+ name="head_bodypaint">
-
+ local_texture="head_bodypaint" />
+
+
+
+
+
-
+ local_texture="head_alpha" />
+
+
+
+ value_default="1">
+ color="0, 0, 0, 255" />
+ color="255, 0, 0, 255" />
-
-
+ value_max="1"
+ value_default="1">
+
+
-
-
+
+
-
-
+ value_max="1"
+ value_default="1">
+
+
-
-
+
+
-
+
+ name="head_universal_tattoo">
-
+ local_texture="head_universal_tattoo" />
@@ -7626,11 +10109,11 @@ render_pass="bump">
@@ -7644,11 +10127,11 @@ render_pass="bump">
@@ -7661,260 +10144,324 @@ render_pass="bump">
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+ value_max="1">
+ domain="0" />
+
+
+
+
+
+
+
+
+
+
+
+
-
+ value_max="1">
+
+
+
+
+
+ name="highlight">
+ tga_file="upperbody_highlights_alpha.tga"
+ file_is_mask="TRUE" />
-
+
+
+
+
+
+
+
+
+
+
+
+ tga_file="upperbodyfreckles_alpha.tga"
+ skip_if_zero="true"
+ domain="0.6" />
+
+
+
+
-
+ value_max="1"
+ value_default="1">
+
+
+
+
+
-
+ value_max="1"
+ value_default="1">
+
+
+
+
+
-
+ value_max="1"
+ value_default="1">
+
+
+
+
+
-
+
+ name="upper_universal_tattoo">
-
-
-
-
+ local_texture="upper_universal_tattoo" />
+ id="1232"
+ group="1"
+ edit_group="colorpicker_driven"
+ wearable="universal"
+ name="tattoo_upper_universal_red"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+ color="0, 0, 0, 255" />
+ color="255, 0, 0, 255" />
-
+ value_max="1"
+ value_default="1">
+
+
+
+
+
-
+ value_max="1"
+ value_default="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ value_max="1"
+ value_default=".8">
+ value_max="1"
+ value_default=".8">
+ domain="0.05" />
+ value_max="1"
+ value_default=".8">
+ domain="0.05" />
+ name="upper_undershirt">
+ local_texture="upper_undershirt" />
@@ -7928,11 +10475,11 @@ render_pass="bump">
@@ -7946,11 +10493,11 @@ render_pass="bump">
@@ -7964,320 +10511,185 @@ render_pass="bump">
+ wearable="undershirt"
+ edit_group="driven"
+ name="Sleeve Length"
+ value_min=".01"
+ value_max="1"
+ value_default=".4">
+ value_max="1"
+ value_default=".8">
+ value_max="1"
+ value_default=".8">
+ value_default=".8">
+ domain="0.05" />
+
+
+ value_default="0.0"
+ camera_distance="1.6"
+ camera_elevation="-.4"
+ camera_angle="70">
+ tga_file="nailpolish_alpha.tga"
+ skip_if_zero="true"
+ domain="0.1" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ value_max="1"
+ camera_distance="1.6"
+ camera_elevation="-.4"
+ camera_angle="70">
-
-
-
-
-
-
-
-
+ color="255,187,200,255" />
-
-
+ color="194,102,127,255" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ color="227,34,99,255" />
-
-
+ color="168,41,60,255" />
-
-
+ color="97,28,59,255" />
-
-
+ color="234,115,93,255" />
-
-
+ color="142,58,47,255" />
-
-
+ color="114,30,46,255" />
+ color="14,14,14,255" />
-
+ value_default=".8">
+ value_default="1">
+ tga_file="gloves_fingers_alpha.tga"
+ multiply_blend="true"
+ domain="0.01" />
+ name="upper_gloves">
+ local_texture="upper_gloves" />
@@ -8291,11 +10703,11 @@ render_pass="bump">
@@ -8309,11 +10721,11 @@ render_pass="bump">
@@ -8327,168 +10739,282 @@ render_pass="bump">
+ value_default=".8">
+ value_default="1">
+ tga_file="gloves_fingers_alpha.tga"
+ multiply_blend="true"
+ domain="0.01" />
+ name="upper_clothes_shadow">
+ local_texture="upper_shirt" />
-
-
-
+ value_default="0">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name="upper_shirt base bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
+ local_texture="upper_shirt"
+ local_texture_alpha_only="true" />
-
-
+ value_max="0.85">
+
+
-
-
+
+
-
-
+ value_max="1">
+
+
-
-
+
+
+
+
+
+
+
+
+ value_default="0">
+ color="255, 255, 255, 0" />
+ color="255, 255, 255, 255" />
+ value_max="0.85">
-
-
-
+
+
+
+ value_max="1">
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
+
+
+
+
+ name="upper_clothes">
+ local_texture="upper_shirt" />
@@ -8502,11 +11028,11 @@ render_pass="bump">
@@ -8520,11 +11046,11 @@ render_pass="bump">
@@ -8538,127 +11064,166 @@ render_pass="bump">
+ value_max="0.85"
+ value_default=".7">
-
-
-
-
-
-
-
-
-
+ value_default=".8">
+
+ name="Collar Front Height Cloth"
+ value_min="0"
+ value_max="1"
+ value_default=".8">
+ multiply_blend="true"
+ tga_file="shirt_collar_alpha.tga"
+ domain="0.05" />
+ name="Collar Back Height Cloth"
+ value_min="0"
+ value_max="1"
+ value_default=".8">
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
+
+
+
+
+
+
+
+
+
+
+
+
+ tga_file="bump_shirt_wrinkles.tga" />
+
+ id="875"
+ group="1"
+ wearable="jacket"
+ name="jacket upper Wrinkles"
+ value_min="0"
+ value_max="1"
+ value_default="0">
@@ -8669,43 +11234,89 @@ render_pass="bump">
+
+
+
+
+
+
+
+
+
+
+
+
+ name="upper_jacket">
+ local_texture="upper_jacket" />
@@ -8719,11 +11330,11 @@ render_pass="bump">
@@ -8737,15 +11348,15 @@ render_pass="bump">
-
+ id="833"
+ group="1"
+ edit_group="colorpicker_driven"
+ wearable="jacket"
+ name="upper_jacket_blue"
+ value_min="0"
+ value_max="1"
+ value_default="1">
+
@@ -8755,140 +11366,222 @@ render_pass="bump">
+
+
+
+
+ value_max="1">
+ value_max="1">
+ multiply_blend="true"
+ tga_file="shirt_collar_back_alpha.tga"
+ domain="0.05" />
-
-
-
-
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+ value_max="1"
+ value_default=".8"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation=".2">
+
+
+
+
+
+
+
+
+
+
+ tga_file="bump_lowerbody_base.tga"
+ file_is_mask="FALSE" />
+
+
+
+
+
+
-
+ tga_file="body_skingrain.tga" />
+
+
+
+
+ value_max="1">
+ color="0, 0, 0, 0" />
+ color="0, 0, 0, 128" />
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tga_file="bodyfreckles_alpha.tga"
+ skip_if_zero="true"
+ domain="0.6" />
+ name="lower_tattoo">
+ local_texture="lower_tattoo" />
@@ -8902,11 +11595,11 @@ render_pass="bump">
@@ -8920,11 +11613,11 @@ render_pass="bump">
@@ -8937,101 +11630,114 @@ render_pass="bump">
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
+ value_default="1">
+
+
+
+
+
-
-
-
-
+
+
+
-
+
+
+
-
-
-
-
-
+ name="lower_underpants bump"
+ render_pass="bump"
+ fixed_color="128,128,128,255">
-
+ local_texture="lower_underpants"
+ local_texture_alpha_only="true" />
-
-
-
+
+
+
-
+
+
+
+
-
-
+ name="lower_underpants">
+ local_texture="lower_underpants" />
@@ -9045,11 +11751,11 @@ render_pass="bump">
@@ -9063,11 +11769,11 @@ render_pass="bump">
@@ -9079,123 +11785,2167 @@ render_pass="bump">
color="0, 0, 255, 255" />
-
-
+ value_default=".3"
+ camera_distance="1.2"
+ camera_angle="30"
+ camera_elevation="-.3">
+ tga_file="pants_length_alpha.tga"
+ domain="0.01" />
+ value_default=".8">
+ tga_file="pants_waist_alpha.tga"
+ domain="0.05" />
+
+
+
+
+ value_default="0.35">
+ tga_file="shoe_height_alpha.tga"
+ domain="0.01" />
+
+
+
+
-
-
+ value_default="1">
+
+
+
+
+
+
+ value_default="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tga_file="shoe_height_alpha.tga"
+ domain="0.01" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
max1="1"
max2="1"
min2="1" />
+
+
+
+
@@ -9631,8 +14395,8 @@ render_pass="bump">
edit_group="shape_mouth"
edit_group_order="3.2"
name="Lip Ratio"
- label="Lip Ratio"
- show_simple="true"
+ label="Lip Ratio"
+ show_simple="true"
label_min="More Upper Lip"
label_max="More Lower Lip"
value_min="0"
@@ -9655,6 +14419,21 @@ render_pass="bump">
max1="1"
max2="1"
min2="1" />
+
+
+
+
+
@@ -9680,6 +14459,10 @@ render_pass="bump">
+
+
+
@@ -9890,6 +14673,10 @@ render_pass="bump">
max1="1"
max2="1"
min2="1" />
+
+
+
@@ -10362,6 +15149,21 @@ render_pass="bump">
max1="1"
max2="1"
min2="1" />
+
+
+
+
+
@@ -10388,6 +15190,14 @@ render_pass="bump">
+
+
+
@@ -10414,6 +15224,10 @@ render_pass="bump">
+
+
+
@@ -10444,7 +15258,7 @@ render_pass="bump">
min2=".5" />
min1=".5"
max1="1"
max2="1"
+ min2="1" />
+
+
+
+
+
+
+
+
+
+
+
+
@@ -10636,7 +15483,7 @@ render_pass="bump">
edit_group="shape_head"
edit_group_order="1"
name="Head Size"
- label="Head Size"
+ label="Head Size"
label_min="Small Head"
label_max="Big Head"
show_simple="true"
@@ -10670,16 +15517,17 @@ render_pass="bump">
edit_group="shape_eyes"
edit_group_order="1"
name="Eye Size"
- label="Eye Size"
+ label="Eye Size"
label_min="Beady Eyes"
label_max="Anime Eyes"
value_min="0"
value_max="1"
value_default=".5"
- show_simple="true"
+ show_simple="true"
camera_elevation=".1"
camera_distance=".35">
+
@@ -10697,6 +15545,10 @@ render_pass="bump">
+
+
+
@@ -10967,19 +15819,44 @@ render_pass="bump">
min2=".3" />
+ id="151"
+ min1=".3"
+ max1="1"
+ max2="1"
+ min2="1" />
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
@@ -11580,6 +16461,8 @@ render_pass="bump">
+
@@ -11603,6 +16486,8 @@ render_pass="bump">
+
@@ -11625,13 +16510,15 @@ render_pass="bump">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bin/openmetaverse_data/avatar_skeleton.xml b/bin/openmetaverse_data/avatar_skeleton.xml
index 6b07bbc1..2241a125 100644
--- a/bin/openmetaverse_data/avatar_skeleton.xml
+++ b/bin/openmetaverse_data/avatar_skeleton.xml
@@ -1,81 +1,232 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bin/prebuild.exe b/bin/prebuild.exe
new file mode 100644
index 00000000..aada172a
Binary files /dev/null and b/bin/prebuild.exe differ
diff --git a/bin/prebuild.runtimeconfig.json b/bin/prebuild.runtimeconfig.json
new file mode 100644
index 00000000..418df653
--- /dev/null
+++ b/bin/prebuild.runtimeconfig.json
@@ -0,0 +1,12 @@
+{
+ "runtimeOptions": {
+ "tfm": "net6.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "6.0.0"
+ },
+ "configProperties": {
+ "System.Runtime.TieredCompilation": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/zlib.net.dll b/bin/zlib.net.dll
deleted file mode 100755
index 9d156547..00000000
Binary files a/bin/zlib.net.dll and /dev/null differ
diff --git a/openjpeg-dotnet/DllOpenJPEG.sln b/openjpeg-dotnet/DllOpenJPEG.sln
index b6c741d4..e2956d1a 100644
--- a/openjpeg-dotnet/DllOpenJPEG.sln
+++ b/openjpeg-dotnet/DllOpenJPEG.sln
@@ -1,7 +1,9 @@
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllOpenJPEG", "DllOpenJPEG.vcproj", "{89AC992C-5E2C-4E6B-A453-61C1DF446216}"
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27130.2003
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DllOpenJPEG", "DllOpenJPEG.vcxproj", "{89AC992C-5E2C-4E6B-A453-61C1DF446216}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -23,4 +25,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DCB4E0B5-36BA-489A-BC3E-27426CD34B43}
+ EndGlobalSection
EndGlobal