Added read support for Instance Attributes.

This isn't 100% finished yet. I intend to add some better API for reading specific attributes, as well as write support (of course!)
This commit is contained in:
CloneTrooper1019
2019-10-31 21:40:31 -05:00
parent fd8598c1b5
commit e14b092aa7
30 changed files with 580 additions and 95 deletions

View File

@ -26,6 +26,9 @@ namespace RobloxFiles.DataTypes
private const string DefaultName = "Medium stone grey";
private const int DefaultNumber = 194;
public static implicit operator int(BrickColor color) => color.Number;
public static implicit operator BrickColor(int number) => FromNumber(number);
internal BrickColor(int number, uint rgb, string name)
{
uint r = (rgb / 65536) % 256;
@ -43,6 +46,7 @@ namespace RobloxFiles.DataTypes
ByNumber = BrickColors.ColorMap.ToDictionary(brickColor => brickColor.Number);
ByPalette = BrickColors.PaletteMap.Select(number => ByNumber[number]).ToList();
}
public static BrickColor FromName(string name)
{

View File

@ -1,4 +1,5 @@
using System;
using RobloxFiles.Enums;
namespace RobloxFiles.DataTypes
{
@ -121,6 +122,50 @@ namespace RobloxFiles.DataTypes
m31 = comp[9]; m32 = comp[10]; m33 = comp[11];
}
private void initFromMatrix(Vector3 pos, Vector3 vX, Vector3 vY, Vector3 vZ = null)
{
if (vZ == null)
vZ = vX.Cross(vY);
m14 = pos.X; m24 = pos.Y; m34 = pos.Z;
m11 = vX.X; m12 = vX.Y; m13 = vX.Z;
m21 = vY.X; m22 = vY.Y; m23 = vY.Z;
m31 = vZ.X; m32 = vZ.Y; m33 = vZ.Z;
}
public CFrame(Vector3 pos, Vector3 vX, Vector3 vY, Vector3 vZ = null)
{
initFromMatrix(pos, vX, vY, vZ);
}
internal CFrame(Attribute attr)
{
Vector3 pos = new Vector3(attr);
byte rawOrientId = attr.readByte();
if (rawOrientId > 0)
{
// Make sure this value is in a safe range.
int orientId = (rawOrientId - 1) % 36;
NormalId xColumn = (NormalId)(orientId / 6);
Vector3 vX = Vector3.FromNormalId(xColumn);
NormalId yColumn = (NormalId)(orientId % 6);
Vector3 vY = Vector3.FromNormalId(yColumn);
initFromMatrix(pos, vX, vY);
}
else
{
Vector3 vX = new Vector3(attr),
vY = new Vector3(attr),
vZ = new Vector3(attr);
initFromMatrix(pos, vX, vY, vZ);
}
}
public static CFrame operator +(CFrame a, Vector3 b)
{
float[] ac = a.GetComponents();

View File

@ -5,6 +5,7 @@ namespace RobloxFiles.DataTypes
public class Color3
{
public readonly float R, G, B;
public override string ToString() => $"{R}, {G}, {B}";
public Color3(float r = 0, float g = 0, float b = 0)
{
@ -13,9 +14,11 @@ namespace RobloxFiles.DataTypes
B = b;
}
public override string ToString()
internal Color3(Attribute attr)
{
return string.Join(", ", R, G, B);
R = attr.readFloat();
G = attr.readFloat();
B = attr.readFloat();
}
public static Color3 FromRGB(uint r = 0, uint g = 0, uint b = 0)

View File

@ -7,6 +7,7 @@
public class Color3uint8
{
public readonly byte R, G, B;
public override string ToString() => $"{R}, {G}, {B}";
public Color3uint8(byte r = 0, byte g = 0, byte b = 0)
{
@ -15,11 +16,6 @@
B = b;
}
public override string ToString()
{
return string.Join(", ", R, G, B);
}
public static implicit operator Color3(Color3uint8 color)
{
float r = color.R / 255f;

View File

@ -6,6 +6,11 @@ namespace RobloxFiles.DataTypes
{
public readonly ColorSequenceKeypoint[] Keypoints;
public override string ToString()
{
return string.Join<ColorSequenceKeypoint>(" ", Keypoints);
}
public ColorSequence(Color3 c) : this(c, c)
{
}
@ -42,10 +47,16 @@ namespace RobloxFiles.DataTypes
Keypoints = keypoints;
}
public override string ToString()
public ColorSequence(Attribute attr)
{
return string.Join<ColorSequenceKeypoint>(" ", Keypoints);
int numKeys = attr.readInt();
var keypoints = new ColorSequenceKeypoint[numKeys];
for (int i = 0; i < numKeys; i++)
keypoints[i] = new ColorSequenceKeypoint(attr);
Keypoints = keypoints;
}
}
}

View File

@ -6,6 +6,11 @@
public readonly Color3 Value;
public readonly int Envelope;
public override string ToString()
{
return $"{Time} {Value.R} {Value.G} {Value.B} {Envelope}";
}
public ColorSequenceKeypoint(float time, Color3 value, int envelope = 0)
{
Time = time;
@ -13,9 +18,11 @@
Envelope = envelope;
}
public override string ToString()
internal ColorSequenceKeypoint(Attribute attr)
{
return string.Join(" ", Time, Value.R, Value.G, Value.B, Envelope);
Envelope = attr.readInt();
Time = attr.readFloat();
Value = new Color3(attr);
}
}
}

View File

@ -7,11 +7,7 @@
public class Content
{
public readonly string Url;
public override string ToString()
{
return Url;
}
public override string ToString() => Url;
public Content(string url)
{

View File

@ -7,24 +7,39 @@ namespace RobloxFiles.DataTypes
public readonly float Min;
public readonly float Max;
public override string ToString() => $"{Min} {Max}";
public NumberRange(float num)
{
Min = num;
Max = num;
}
private static void checkRange(float min, float max)
{
if (max - min >= 0)
return;
throw new Exception("NumberRange: invalid range");
}
public NumberRange(float min = 0, float max = 0)
{
if (max - min < 0)
throw new Exception("NumberRange: invalid range");
checkRange(min, max);
Min = min;
Max = max;
}
public override string ToString()
internal NumberRange(Attribute attr)
{
return string.Join(" ", Min, Max);
float min = attr.readFloat();
float max = attr.readFloat();
checkRange(min, max);
Min = min;
Max = max;
}
}
}

View File

@ -6,6 +6,11 @@ namespace RobloxFiles.DataTypes
{
public readonly NumberSequenceKeypoint[] Keypoints;
public override string ToString()
{
return string.Join<NumberSequenceKeypoint>(" ", Keypoints);
}
public NumberSequence(float n)
{
NumberSequenceKeypoint a = new NumberSequenceKeypoint(0, n);
@ -47,9 +52,15 @@ namespace RobloxFiles.DataTypes
Keypoints = keypoints;
}
public override string ToString()
public NumberSequence(Attribute attr)
{
return string.Join<NumberSequenceKeypoint>(" ", Keypoints);
int numKeys = attr.readInt();
var keypoints = new NumberSequenceKeypoint[numKeys];
for (int i = 0; i < numKeys; i++)
keypoints[i] = new NumberSequenceKeypoint(attr);
Keypoints = keypoints;
}
}
}

View File

@ -6,6 +6,11 @@
public readonly float Value;
public readonly float Envelope;
public override string ToString()
{
return $"{Time} {Value} {Envelope}";
}
public NumberSequenceKeypoint(float time, float value, float envelope = 0)
{
Time = time;
@ -13,9 +18,11 @@
Envelope = envelope;
}
public override string ToString()
internal NumberSequenceKeypoint(Attribute attr)
{
return string.Join(" ", Time, Value, Envelope);
Envelope = attr.readFloat();
Time = attr.readFloat();
Value = attr.readFloat();
}
}
}

View File

@ -12,6 +12,11 @@ namespace RobloxFiles.DataTypes
public readonly float FrictionWeight = 1.0f;
public readonly float ElasticityWeight = 1.0f;
public override string ToString()
{
return $"{Density}, {Friction}, {Elasticity}, {FrictionWeight}, {ElasticityWeight}";
}
public PhysicalProperties(Material material)
{
if (MaterialInfo.FrictionWeightMap.ContainsKey(material))
@ -32,9 +37,14 @@ namespace RobloxFiles.DataTypes
ElasticityWeight = elasticityWeight;
}
public override string ToString()
internal PhysicalProperties(Attribute attr)
{
return string.Join(", ", Density, Friction, Elasticity, FrictionWeight, ElasticityWeight);
Density = attr.readFloat();
Friction = attr.readFloat();
Elasticity = attr.readFloat();
FrictionWeight = attr.readFloat();
ElasticityWeight = attr.readFloat();
}
}
}

View File

@ -7,11 +7,7 @@
public class ProtectedString
{
public readonly string ProtectedValue;
public override string ToString()
{
return ProtectedValue;
}
public override string ToString() => ProtectedValue;
public ProtectedString(string value)
{

View File

@ -9,6 +9,7 @@ namespace RobloxFiles.DataTypes
public class Quaternion
{
public readonly float X, Y, Z, W;
public override string ToString() => $"{X}, {Y}, {Z}, {W}";
public float Magnitude
{
@ -20,12 +21,7 @@ namespace RobloxFiles.DataTypes
return (float)magnitude;
}
}
public override string ToString()
{
return string.Join(", ", X, Y, Z, W);
}
public Quaternion(float x, float y, float z, float w)
{
X = x;

View File

@ -5,6 +5,8 @@
public readonly Vector3 Origin;
public readonly Vector3 Direction;
public override string ToString() => $"{{{Origin}}}, {{{Direction}}}";
public Ray Unit
{
get
@ -26,9 +28,10 @@
Direction = direction ?? new Vector3();
}
public override string ToString()
internal Ray(Attribute attr)
{
return '{' + Origin.ToString() + "}, {" + Direction.ToString() + '}';
Origin = new Vector3(attr);
Direction = new Vector3(attr);
}
public Vector3 ClosestPoint(Vector3 point)

View File

@ -8,6 +8,8 @@
public float Width => (Max - Min).X;
public float Height => (Max - Min).Y;
public override string ToString() => $"{Min}, {Max}";
public Rect(Vector2 min = null, Vector2 max = null)
{
Min = min ?? Vector2.Zero;
@ -20,9 +22,10 @@
Max = new Vector2(maxX, maxY);
}
public override string ToString()
internal Rect(Attribute attr)
{
return string.Join(", ", Min, Max);
Min = new Vector2(attr);
Max = new Vector2(attr);
}
}
}

View File

@ -4,37 +4,39 @@ namespace RobloxFiles.DataTypes
{
public class Region3
{
public readonly CFrame CFrame;
public readonly Vector3 Size;
public readonly Vector3 Min, Max;
public Region3(Vector3 a, Vector3 b)
public Vector3 Size => (Max - Min);
public CFrame CFrame => new CFrame((Min + Max) / 2);
public override string ToString() => $"{CFrame}; {Size}";
public Region3(Vector3 min, Vector3 max)
{
CFrame = new CFrame((a + b) / 2);
Size = b - a;
Min = min;
Max = max;
}
public override string ToString()
internal Region3(Attribute attr)
{
return CFrame + "; " + Size;
Min = new Vector3(attr);
Max = new Vector3(attr);
}
public Region3 ExpandToGrid(float resolution)
{
Vector3 min = (CFrame - (Size / 2)).Position / resolution;
Vector3 max = (CFrame + (Size / 2)).Position / resolution;
Vector3 emin = new Vector3
(
(float)Math.Floor(min.X) * resolution,
(float)Math.Floor(min.Y) * resolution,
(float)Math.Floor(min.Z) * resolution
(float)Math.Floor(Min.X) * resolution,
(float)Math.Floor(Min.Y) * resolution,
(float)Math.Floor(Min.Z) * resolution
);
Vector3 emax = new Vector3
(
(float)Math.Floor(max.X) * resolution,
(float)Math.Floor(max.Y) * resolution,
(float)Math.Floor(max.Z) * resolution
(float)Math.Floor(Max.X) * resolution,
(float)Math.Floor(Max.Y) * resolution,
(float)Math.Floor(Max.Z) * resolution
);
return new Region3(emin, emax);

View File

@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RobloxFiles.DataTypes
namespace RobloxFiles.DataTypes
{
public struct Region3int16
public class Region3int16
{
public readonly Vector3int16 Min, Max;
public override string ToString() => $"{Min}; {Max}";
public Region3int16(Vector3int16 min = null, Vector3int16 max = null)
{
@ -16,9 +11,10 @@ namespace RobloxFiles.DataTypes
Max = max ?? new Vector3int16();
}
public override string ToString()
internal Region3int16(Attribute attr)
{
return string.Join("; ", Min, Max);
Min = new Vector3int16(attr);
Max = new Vector3int16(attr);
}
}
}

View File

@ -5,12 +5,20 @@
public readonly float Scale;
public readonly int Offset;
public override string ToString() => $"{Scale}, {Offset}";
public UDim(float scale = 0, int offset = 0)
{
Scale = scale;
Offset = offset;
}
internal UDim(Attribute attr)
{
Scale = attr.readFloat();
Offset = attr.readInt();
}
public static UDim operator+(UDim a, UDim b)
{
return new UDim(a.Scale + b.Scale, a.Offset + b.Offset);
@ -20,10 +28,5 @@
{
return new UDim(a.Scale - b.Scale, a.Offset - b.Offset);
}
public override string ToString()
{
return string.Join(", ", Scale, Offset);
}
}
}

View File

@ -3,6 +3,7 @@
public class UDim2
{
public readonly UDim X, Y;
public override string ToString() => $"{{{X}}},{{{Y}}}";
public UDim Width => X;
public UDim Height => Y;
@ -19,11 +20,12 @@
Y = y;
}
public override string ToString()
internal UDim2(Attribute attr)
{
return '{' + X.ToString() + "},{" + Y.ToString() + '}';
X = new UDim(attr);
Y = new UDim(attr);
}
public UDim2 Lerp(UDim2 other, float alpha)
{
float scaleX = X.Scale + ((other.X.Scale - X.Scale) * alpha);

View File

@ -5,7 +5,8 @@ namespace RobloxFiles.DataTypes
public class Vector2
{
public readonly float X, Y;
public override string ToString() => $"{X}, {Y}";
public float Magnitude
{
get
@ -34,6 +35,12 @@ namespace RobloxFiles.DataTypes
Y = coords.Length > 1 ? coords[1] : 0;
}
internal Vector2(Attribute attr)
{
X = attr.readFloat();
Y = attr.readFloat();
}
private delegate Vector2 Operator(Vector2 a, Vector2 b);
private static Vector2 upcastFloatOp(Vector2 vec, float num, Operator upcast)
@ -76,11 +83,6 @@ namespace RobloxFiles.DataTypes
public static Vector2 Zero => new Vector2(0, 0);
public override string ToString()
{
return string.Join(", ", X, Y);
}
public float Dot(Vector2 other)
{
float dotX = X * other.X;

69
DataTypes/Vector2int16.cs Normal file
View File

@ -0,0 +1,69 @@
using System;
namespace RobloxFiles.DataTypes
{
public class Vector2int16
{
public readonly short X, Y;
public override string ToString() => $"{X}, {Y}";
public Vector2int16(short x = 0, short y = 0)
{
X = x;
Y = y;
}
public Vector2int16(int x = 0, int y = 0)
{
X = (short)x;
Y = (short)y;
}
internal Vector2int16(Attribute attr)
{
X = attr.readShort();
Y = attr.readShort();
}
private delegate Vector2int16 Operator(Vector2int16 a, Vector2int16 b);
private static Vector2int16 upcastShortOp(Vector2int16 vec, short num, Operator upcast)
{
Vector2int16 numVec = new Vector2int16(num, num);
return upcast(vec, numVec);
}
private static Vector2int16 upcastShortOp(short num, Vector2int16 vec, Operator upcast)
{
Vector2int16 numVec = new Vector2int16(num, num);
return upcast(numVec, vec);
}
private static Operator add = new Operator((a, b) => new Vector2int16(a.X + b.X, a.Y + b.Y));
private static Operator sub = new Operator((a, b) => new Vector2int16(a.X - b.X, a.Y - b.Y));
private static Operator mul = new Operator((a, b) => new Vector2int16(a.X * b.X, a.Y * b.Y));
private static Operator div = new Operator((a, b) =>
{
if (b.X == 0 || b.Y == 0)
throw new DivideByZeroException();
return new Vector2int16(a.X / b.X, a.Y / b.Y);
});
public static Vector2int16 operator +(Vector2int16 a, Vector2int16 b) => add(a, b);
public static Vector2int16 operator +(Vector2int16 v, short n) => upcastShortOp(v, n, add);
public static Vector2int16 operator +(short n, Vector2int16 v) => upcastShortOp(n, v, add);
public static Vector2int16 operator -(Vector2int16 a, Vector2int16 b) => sub(a, b);
public static Vector2int16 operator -(Vector2int16 v, short n) => upcastShortOp(v, n, sub);
public static Vector2int16 operator -(short n, Vector2int16 v) => upcastShortOp(n, v, sub);
public static Vector2int16 operator *(Vector2int16 a, Vector2int16 b) => mul(a, b);
public static Vector2int16 operator *(Vector2int16 v, short n) => upcastShortOp(v, n, mul);
public static Vector2int16 operator *(short n, Vector2int16 v) => upcastShortOp(n, v, mul);
public static Vector2int16 operator /(Vector2int16 a, Vector2int16 b) => div(a, b);
public static Vector2int16 operator /(Vector2int16 v, short n) => upcastShortOp(v, n, div);
public static Vector2int16 operator /(short n, Vector2int16 v) => upcastShortOp(n, v, div);
}
}

View File

@ -6,6 +6,7 @@ namespace RobloxFiles.DataTypes
public class Vector3
{
public readonly float X, Y, Z;
public override string ToString() => $"{X}, {Y}, {Z}";
public float Magnitude
{
@ -37,6 +38,13 @@ namespace RobloxFiles.DataTypes
Z = coords.Length > 2 ? coords[2] : 0;
}
internal Vector3(Attribute attr)
{
X = attr.readFloat();
Y = attr.readFloat();
Z = attr.readFloat();
}
public static Vector3 FromAxis(Axis axis)
{
float[] coords = new float[3] { 0f, 0f, 0f };
@ -102,10 +110,7 @@ namespace RobloxFiles.DataTypes
public static Vector3 Up => new Vector3(0, 1, 0);
public static Vector3 Back => new Vector3(0, 0, 1);
public override string ToString()
{
return string.Join(", ", X, Y, Z);
}
public float Dot(Vector3 other)
{

View File

@ -5,12 +5,10 @@ namespace RobloxFiles.DataTypes
public class Vector3int16
{
public readonly short X, Y, Z;
public override string ToString() => $"{X}, {Y}, {Z}";
public Vector3int16()
public Vector3int16() : this(0, 0, 0)
{
X = 0;
Y = 0;
Z = 0;
}
public Vector3int16(short x = 0, short y = 0, short z = 0)
@ -27,9 +25,11 @@ namespace RobloxFiles.DataTypes
Z = (short)z;
}
public override string ToString()
internal Vector3int16(Attribute attr)
{
return string.Join(", ", X, Y, Z);
X = attr.readShort();
Y = attr.readShort();
Z = attr.readShort();
}
private delegate Vector3int16 Operator(Vector3int16 a, Vector3int16 b);