0.522.0.5220281 (+ Font Type Support & Bug Fixes)
This commit is contained in:
parent
cff4b1ad5c
commit
f8c914dd0b
BinaryFormat/Chunks
DataTypes
Generated
Interfaces
Plugins
RobloxFileFormat.csprojTokens
Tree
UnitTest/Files
XmlFormat
@ -662,6 +662,23 @@ namespace RobloxFiles.BinaryFormat.Chunks
|
||||
|
||||
break;
|
||||
}
|
||||
case PropertyType.FontFace:
|
||||
{
|
||||
readProperties(i =>
|
||||
{
|
||||
string family = reader.ReadString();
|
||||
|
||||
if (family.EndsWith(".otf") || family.EndsWith(".ttf"))
|
||||
return new FontFace(family);
|
||||
|
||||
var weight = (FontWeight)reader.ReadUInt16();
|
||||
var style = (FontStyle)reader.ReadByte();
|
||||
|
||||
return new FontFace(family, weight, style);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RobloxFile.LogError($"Unhandled property type: {Type} in {this}!");
|
||||
@ -1283,6 +1300,27 @@ namespace RobloxFiles.BinaryFormat.Chunks
|
||||
|
||||
break;
|
||||
}
|
||||
case PropertyType.FontFace:
|
||||
{
|
||||
props.ForEach(prop =>
|
||||
{
|
||||
var font = prop.CastValue<FontFace>();
|
||||
|
||||
string family = font.Family;
|
||||
writer.WriteString(font.Family);
|
||||
|
||||
if (family.EndsWith(".otf") || family.EndsWith(".ttf"))
|
||||
return;
|
||||
|
||||
var weight = (ushort)font.Weight;
|
||||
writer.Write(weight);
|
||||
|
||||
var style = (byte)font.Style;
|
||||
writer.Write(style);
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RobloxFile.LogError($"Unhandled property type: {Type} in {this}!");
|
||||
|
@ -1,12 +1,11 @@
|
||||
using System;
|
||||
using System.Diagnostics.Contracts;
|
||||
using RobloxFiles.Enums;
|
||||
|
||||
namespace RobloxFiles.DataTypes
|
||||
{
|
||||
public class CFrame
|
||||
{
|
||||
private float m14, m24, m34;
|
||||
private readonly float m14, m24, m34;
|
||||
|
||||
private readonly float m11 = 1, m12, m13;
|
||||
private readonly float m21, m22 = 1, m23;
|
||||
@ -18,28 +17,23 @@ namespace RobloxFiles.DataTypes
|
||||
public float Y => m24;
|
||||
public float Z => m34;
|
||||
|
||||
public Vector3 Position
|
||||
{
|
||||
get => new Vector3(X, Y, Z);
|
||||
public Vector3 Position => new Vector3(m41, m42, m43);
|
||||
public CFrame Rotation => (this - Position);
|
||||
|
||||
set
|
||||
{
|
||||
Contract.Requires(value != null);
|
||||
public Vector3 XVector => new Vector3(m11, m21, m31);
|
||||
public Vector3 YVector => new Vector3(m12, m22, m32);
|
||||
public Vector3 ZVector => new Vector3(m13, m23, m33);
|
||||
|
||||
m14 = value.X;
|
||||
m24 = value.Y;
|
||||
m34 = value.Z;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 RightVector => new Vector3( m11, m21, m31);
|
||||
public Vector3 UpVector => new Vector3( m12, m22, m32);
|
||||
public Vector3 LookVector => new Vector3(-m13, -m23, -m33);
|
||||
public Vector3 RightVector => XVector;
|
||||
public Vector3 UpVector => YVector;
|
||||
public Vector3 LookVector => -ZVector;
|
||||
|
||||
public Vector3 ColumnX => new Vector3(m11, m12, m13);
|
||||
public Vector3 ColumnY => new Vector3(m21, m22, m23);
|
||||
public Vector3 ColumnZ => new Vector3(m31, m32, m33);
|
||||
|
||||
public static readonly CFrame Identity = new CFrame();
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var components = GetComponents();
|
||||
@ -96,23 +90,20 @@ namespace RobloxFiles.DataTypes
|
||||
|
||||
public CFrame(Vector3 eye, Vector3 look)
|
||||
{
|
||||
Vector3 zAxis = (eye - look).Unit;
|
||||
Vector3 xAxis = Vector3.Up.Cross(zAxis);
|
||||
Vector3 yAxis = zAxis.Cross(xAxis);
|
||||
Vector3 zAxis = (eye - look).Unit,
|
||||
xAxis = Vector3.Up.Cross(zAxis),
|
||||
yAxis = zAxis.Cross(xAxis);
|
||||
|
||||
if (xAxis.Magnitude == 0)
|
||||
{
|
||||
xAxis = Vector3.z;
|
||||
yAxis = Vector3.x;
|
||||
zAxis = Vector3.y;
|
||||
|
||||
if (zAxis.Y < 0)
|
||||
{
|
||||
xAxis = new Vector3(0, 0, -1);
|
||||
yAxis = new Vector3(1, 0, 0);
|
||||
zAxis = new Vector3(0, -1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
xAxis = new Vector3(0, 0, 1);
|
||||
yAxis = new Vector3(1, 0, 0);
|
||||
zAxis = new Vector3(0, 1, 0);
|
||||
xAxis = -xAxis;
|
||||
zAxis = -zAxis;
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,9 +114,9 @@ namespace RobloxFiles.DataTypes
|
||||
|
||||
public CFrame(float nx, float ny, float nz, float i, float j, float k, float w)
|
||||
{
|
||||
float ii = i * i;
|
||||
float jj = j * j;
|
||||
float kk = k * k;
|
||||
float ii = i * i,
|
||||
jj = j * j,
|
||||
kk = k * k;
|
||||
|
||||
m14 = nx;
|
||||
m24 = ny;
|
||||
@ -308,18 +299,18 @@ namespace RobloxFiles.DataTypes
|
||||
|
||||
public static CFrame FromAxisAngle(Vector3 axis, float theta)
|
||||
{
|
||||
Vector3 u = VectorAxisAngle(axis, Vector3.Up, theta);
|
||||
Vector3 b = VectorAxisAngle(axis, Vector3.Back, theta);
|
||||
Vector3 r = VectorAxisAngle(axis, Vector3.Right, theta);
|
||||
Vector3 r = VectorAxisAngle(axis, Vector3.x, theta),
|
||||
u = VectorAxisAngle(axis, Vector3.y, theta),
|
||||
b = VectorAxisAngle(axis, Vector3.z, theta);
|
||||
|
||||
return new CFrame(0, 0, 0, r.X, u.X, b.X, r.Y, u.Y, b.Y, r.Z, u.Z, b.Z);
|
||||
}
|
||||
|
||||
public static CFrame FromEulerAnglesXYZ(float x, float y, float z)
|
||||
{
|
||||
CFrame cfx = FromAxisAngle(Vector3.Right, x),
|
||||
cfy = FromAxisAngle(Vector3.Up, y),
|
||||
cfz = FromAxisAngle(Vector3.Back, z);
|
||||
CFrame cfx = FromAxisAngle(Vector3.x, x),
|
||||
cfy = FromAxisAngle(Vector3.y, y),
|
||||
cfz = FromAxisAngle(Vector3.z, z);
|
||||
|
||||
return cfx * cfy * cfz;
|
||||
}
|
||||
@ -386,7 +377,13 @@ namespace RobloxFiles.DataTypes
|
||||
|
||||
public float[] GetComponents()
|
||||
{
|
||||
return new float[] { m14, m24, m34, m11, m12, m13, m21, m22, m23, m31, m32, m33 };
|
||||
return new float[]
|
||||
{
|
||||
m14, m24, m34,
|
||||
m11, m12, m13,
|
||||
m21, m22, m23,
|
||||
m31, m32, m33
|
||||
};
|
||||
}
|
||||
|
||||
public EulerAngles ToEulerAngles() => new EulerAngles
|
||||
@ -411,28 +408,27 @@ namespace RobloxFiles.DataTypes
|
||||
|
||||
public bool IsAxisAligned()
|
||||
{
|
||||
float[] matrix = GetComponents();
|
||||
|
||||
byte sum0 = 0,
|
||||
sum1 = 0;
|
||||
|
||||
for (int i = 3; i < 12; i++)
|
||||
var tests = new float[3]
|
||||
{
|
||||
float t = Math.Abs(matrix[i]);
|
||||
XVector.Dot(Vector3.x),
|
||||
YVector.Dot(Vector3.y),
|
||||
ZVector.Dot(Vector3.z)
|
||||
};
|
||||
|
||||
if (t.FuzzyEquals(1, 1e-8f))
|
||||
{
|
||||
// Approximately ±1
|
||||
sum1++;
|
||||
}
|
||||
else if (t.FuzzyEquals(0, 1e-8f))
|
||||
{
|
||||
// Approximately ±0
|
||||
sum0++;
|
||||
}
|
||||
foreach (var test in tests)
|
||||
{
|
||||
float dot = Math.Abs(test);
|
||||
|
||||
if (dot.FuzzyEquals(1))
|
||||
continue;
|
||||
|
||||
if (dot.FuzzyEquals(0))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return (sum0 == 6 && sum1 == 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsLegalOrientId(int orientId)
|
||||
@ -450,7 +446,6 @@ namespace RobloxFiles.DataTypes
|
||||
|
||||
int xNormal = ColumnX.ToNormalId();
|
||||
int yNormal = ColumnY.ToNormalId();
|
||||
|
||||
int orientId = (6 * xNormal) + yNormal;
|
||||
|
||||
if (!IsLegalOrientId(orientId))
|
||||
|
52
DataTypes/FontFace.cs
Normal file
52
DataTypes/FontFace.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using RobloxFiles.Enums;
|
||||
|
||||
namespace RobloxFiles.DataTypes
|
||||
{
|
||||
// Implementation of Roblox's Font datatype.
|
||||
// Renamed to FontFace to avoid disambiguation with System.Font and the Font enum.
|
||||
|
||||
public class FontFace
|
||||
{
|
||||
public readonly Content Family = "rbxasset://fonts/families/LegacyArial.json";
|
||||
public readonly FontWeight Weight = FontWeight.Regular;
|
||||
public readonly FontStyle Style = FontStyle.Normal;
|
||||
|
||||
public FontFace(Content family, FontWeight weight = FontWeight.Regular, FontStyle style = FontStyle.Normal)
|
||||
{
|
||||
Family = family;
|
||||
Weight = weight;
|
||||
Style = style;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Font {{ Family = {Family}, Weight = {Weight}, Style = {Style}}}";
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = Family.GetHashCode()
|
||||
^ Weight.GetHashCode()
|
||||
^ Style.GetHashCode();
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is FontFace font))
|
||||
return false;
|
||||
|
||||
if (Family != font.Family)
|
||||
return false;
|
||||
|
||||
if (Weight != font.Weight)
|
||||
return false;
|
||||
|
||||
if (Style != font.Style)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,8 +12,8 @@
|
||||
|
||||
public Rect(Vector2 min = null, Vector2 max = null)
|
||||
{
|
||||
Min = min ?? Vector2.Zero;
|
||||
Max = max ?? Vector2.Zero;
|
||||
Min = min ?? Vector2.zero;
|
||||
Max = max ?? Vector2.zero;
|
||||
}
|
||||
|
||||
public Rect(float minX, float minY, float maxX, float maxY)
|
||||
|
@ -1,28 +1,14 @@
|
||||
using System;
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
using System;
|
||||
|
||||
namespace RobloxFiles.DataTypes
|
||||
{
|
||||
|
||||
public class Vector2
|
||||
{
|
||||
public readonly float X, Y;
|
||||
public override string ToString() => $"{X}, {Y}";
|
||||
|
||||
public float Magnitude
|
||||
{
|
||||
get
|
||||
{
|
||||
float product = Dot(this);
|
||||
double magnitude = Math.Sqrt(product);
|
||||
|
||||
return (float)magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 Unit
|
||||
{
|
||||
get { return this / Magnitude; }
|
||||
}
|
||||
|
||||
public Vector2(float x = 0, float y = 0)
|
||||
{
|
||||
X = x;
|
||||
@ -34,18 +20,21 @@ namespace RobloxFiles.DataTypes
|
||||
X = coords.Length > 0 ? coords[0] : 0;
|
||||
Y = coords.Length > 1 ? coords[1] : 0;
|
||||
}
|
||||
|
||||
public float Magnitude => (float)Math.Sqrt(X*X + Y*Y);
|
||||
public Vector2 Unit => this / Magnitude;
|
||||
|
||||
private delegate Vector2 Operator(Vector2 a, Vector2 b);
|
||||
|
||||
private static Vector2 UpcastFloatOp(Vector2 vec, float num, Operator upcast)
|
||||
{
|
||||
Vector2 numVec = new Vector2(num, num);
|
||||
var numVec = new Vector2(num, num);
|
||||
return upcast(vec, numVec);
|
||||
}
|
||||
|
||||
private static Vector2 UpcastFloatOp(float num, Vector2 vec, Operator upcast)
|
||||
{
|
||||
Vector2 numVec = new Vector2(num, num);
|
||||
var numVec = new Vector2(num, num);
|
||||
return upcast(numVec, vec);
|
||||
}
|
||||
|
||||
@ -70,29 +59,17 @@ namespace RobloxFiles.DataTypes
|
||||
public static Vector2 operator /(Vector2 v, float n) => UpcastFloatOp(v, n, div);
|
||||
public static Vector2 operator /(float n, Vector2 v) => UpcastFloatOp(n, v, div);
|
||||
|
||||
public static Vector2 operator -(Vector2 v)
|
||||
{
|
||||
return new Vector2(-v.X, -v.Y);
|
||||
}
|
||||
public static Vector2 operator -(Vector2 v) => new Vector2(-v.X, -v.Y);
|
||||
|
||||
public static Vector2 Zero => new Vector2(0, 0);
|
||||
public static Vector2 zero => new Vector2(0, 0);
|
||||
public static Vector2 one => new Vector2(1, 1);
|
||||
|
||||
public float Dot(Vector2 other)
|
||||
{
|
||||
float dotX = X * other.X;
|
||||
float dotY = Y * other.Y;
|
||||
|
||||
return dotX + dotY;
|
||||
}
|
||||
|
||||
public Vector2 Cross(Vector2 other)
|
||||
{
|
||||
float crossX = X * other.Y;
|
||||
float crossY = Y * other.X;
|
||||
|
||||
return new Vector2(crossX, crossY);
|
||||
}
|
||||
public static Vector2 x => new Vector2(1, 0);
|
||||
public static Vector2 y => new Vector2(0, 1);
|
||||
|
||||
public float Dot(Vector2 other) => (X * other.X) + (Y * other.Y);
|
||||
public Vector2 Cross(Vector2 other) => new Vector2(X * other.Y, Y * other.X);
|
||||
|
||||
public Vector2 Lerp(Vector2 other, float t)
|
||||
{
|
||||
return this + (other - this) * t;
|
||||
|
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using RobloxFiles.Enums;
|
||||
|
||||
namespace RobloxFiles.DataTypes
|
||||
@ -19,7 +18,7 @@ namespace RobloxFiles.DataTypes
|
||||
return (float)magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Vector3 Unit
|
||||
{
|
||||
get { return this / Magnitude; }
|
||||
@ -60,7 +59,7 @@ namespace RobloxFiles.DataTypes
|
||||
}
|
||||
|
||||
private delegate Vector3 Operator(Vector3 a, Vector3 b);
|
||||
|
||||
|
||||
private static Vector3 UpcastFloatOp(Vector3 vec, float num, Operator upcast)
|
||||
{
|
||||
Vector3 numVec = new Vector3(num, num, num);
|
||||
@ -73,36 +72,39 @@ namespace RobloxFiles.DataTypes
|
||||
return upcast(numVec, vec);
|
||||
}
|
||||
|
||||
private static readonly Operator add = new Operator((a, b) => new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z));
|
||||
private static readonly Operator sub = new Operator((a, b) => new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z));
|
||||
private static readonly Operator mul = new Operator((a, b) => new Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z));
|
||||
private static readonly Operator div = new Operator((a, b) => new Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z));
|
||||
private static readonly Operator add = (a, b) => new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
||||
private static readonly Operator sub = (a, b) => new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
|
||||
private static readonly Operator mul = (a, b) => new Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
|
||||
private static readonly Operator div = (a, b) => new Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
|
||||
|
||||
public static Vector3 operator +(Vector3 a, Vector3 b) => add(a, b);
|
||||
public static Vector3 operator +(Vector3 v, float n) => UpcastFloatOp(v, n, add);
|
||||
public static Vector3 operator +(float n, Vector3 v) => UpcastFloatOp(n, v, add);
|
||||
public static Vector3 operator +(Vector3 v, float n) => UpcastFloatOp(v, n, add);
|
||||
public static Vector3 operator +(float n, Vector3 v) => UpcastFloatOp(n, v, add);
|
||||
|
||||
public static Vector3 operator -(Vector3 a, Vector3 b) => sub(a, b);
|
||||
public static Vector3 operator -(Vector3 v, float n) => UpcastFloatOp(v, n, sub);
|
||||
public static Vector3 operator -(float n, Vector3 v) => UpcastFloatOp(n, v, sub);
|
||||
public static Vector3 operator -(Vector3 v, float n) => UpcastFloatOp(v, n, sub);
|
||||
public static Vector3 operator -(float n, Vector3 v) => UpcastFloatOp(n, v, sub);
|
||||
|
||||
public static Vector3 operator *(Vector3 a, Vector3 b) => mul(a, b);
|
||||
public static Vector3 operator *(Vector3 v, float n) => UpcastFloatOp(v, n, mul);
|
||||
public static Vector3 operator *(float n, Vector3 v) => UpcastFloatOp(n, v, mul);
|
||||
public static Vector3 operator *(Vector3 v, float n) => UpcastFloatOp(v, n, mul);
|
||||
public static Vector3 operator *(float n, Vector3 v) => UpcastFloatOp(n, v, mul);
|
||||
|
||||
public static Vector3 operator /(Vector3 a, Vector3 b) => div(a, b);
|
||||
public static Vector3 operator /(Vector3 v, float n) => UpcastFloatOp(v, n, div);
|
||||
public static Vector3 operator /(float n, Vector3 v) => UpcastFloatOp(n, v, div);
|
||||
public static Vector3 operator /(Vector3 v, float n) => UpcastFloatOp(v, n, div);
|
||||
public static Vector3 operator /(float n, Vector3 v) => UpcastFloatOp(n, v, div);
|
||||
|
||||
public static Vector3 operator -(Vector3 v)
|
||||
{
|
||||
return new Vector3(-v.X, -v.Y, -v.Z);
|
||||
}
|
||||
public static Vector3 operator -(Vector3 v) => new Vector3(-v.X, -v.Y, -v.Z);
|
||||
|
||||
public static readonly Vector3 zero = new Vector3(0, 0, 0);
|
||||
public static readonly Vector3 one = new Vector3(1, 1, 1);
|
||||
|
||||
public static readonly Vector3 Zero = new Vector3(0, 0, 0);
|
||||
public static readonly Vector3 Right = new Vector3(1, 0, 0);
|
||||
public static readonly Vector3 Up = new Vector3(0, 1, 0);
|
||||
public static readonly Vector3 Back = new Vector3(0, 0, 1);
|
||||
public static readonly Vector3 x = new Vector3(1, 0, 0);
|
||||
public static readonly Vector3 y = new Vector3(0, 1, 0);
|
||||
public static readonly Vector3 z = new Vector3(0, 0, 1);
|
||||
|
||||
public static Vector3 Right => x;
|
||||
public static Vector3 Up => y;
|
||||
public static Vector3 Back => z;
|
||||
|
||||
public float Dot(Vector3 other)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
// Auto-generated list of Roblox enums.
|
||||
// Updated as of 0.514.0.5140398
|
||||
// Updated as of 0.522.0.5220281
|
||||
|
||||
namespace RobloxFiles.Enums
|
||||
{
|
||||
@ -332,7 +332,8 @@ namespace RobloxFiles.Enums
|
||||
Sarpanch,
|
||||
SpecialElite,
|
||||
TitilliumWeb,
|
||||
Ubuntu
|
||||
Ubuntu,
|
||||
Unknown = 100
|
||||
}
|
||||
|
||||
public enum FontSize
|
||||
@ -354,6 +355,25 @@ namespace RobloxFiles.Enums
|
||||
Size96
|
||||
}
|
||||
|
||||
public enum FontStyle
|
||||
{
|
||||
Normal,
|
||||
Italic
|
||||
}
|
||||
|
||||
public enum FontWeight
|
||||
{
|
||||
Thin = 100,
|
||||
ExtraLight = 200,
|
||||
Light = 300,
|
||||
Regular = 400,
|
||||
Medium = 500,
|
||||
SemiBold = 600,
|
||||
Bold = 700,
|
||||
ExtraBold = 800,
|
||||
Heavy = 900
|
||||
}
|
||||
|
||||
public enum FormFactor
|
||||
{
|
||||
Symmetric,
|
||||
@ -1061,7 +1081,8 @@ namespace RobloxFiles.Enums
|
||||
{
|
||||
Default,
|
||||
Immediate,
|
||||
Deferred
|
||||
Deferred,
|
||||
AncestryDeferred
|
||||
}
|
||||
|
||||
public enum SizeConstraint
|
||||
@ -1158,6 +1179,13 @@ namespace RobloxFiles.Enums
|
||||
Other
|
||||
}
|
||||
|
||||
public enum TerrainFace
|
||||
{
|
||||
Top,
|
||||
Side,
|
||||
Bottom
|
||||
}
|
||||
|
||||
public enum TextTruncate
|
||||
{
|
||||
None,
|
||||
|
@ -6,7 +6,7 @@ namespace RobloxFiles.Tokens
|
||||
{
|
||||
string XmlPropertyToken { get; }
|
||||
|
||||
bool ReadProperty(Property prop, XmlNode token);
|
||||
bool ReadProperty(Property prop, XmlNode node);
|
||||
void WriteProperty(Property prop, XmlDocument doc, XmlNode node);
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -1,43 +1,67 @@
|
||||
--!strict
|
||||
local Format = {}
|
||||
|
||||
function Format.Null(value)
|
||||
type IFlags = { [string]: boolean }
|
||||
type IEnum = { GetEnumItems: (IEnum) -> {EnumItem} }
|
||||
|
||||
type IAxes =
|
||||
{
|
||||
X: boolean;
|
||||
Y: boolean;
|
||||
Z: boolean;
|
||||
}
|
||||
|
||||
type IFaces =
|
||||
{
|
||||
Left: boolean;
|
||||
Right: boolean;
|
||||
|
||||
Top: boolean;
|
||||
Bottom: boolean;
|
||||
|
||||
Front: boolean;
|
||||
Back: boolean;
|
||||
}
|
||||
|
||||
function Format.Null(value: any): nil
|
||||
return nil
|
||||
end
|
||||
|
||||
function Format.Bytes(value)
|
||||
function Format.Bytes(value: string): string
|
||||
if #value > 0 then
|
||||
local fmt = "Convert.FromBase64String(%q)"
|
||||
return fmt:format(value)
|
||||
else
|
||||
return "Array.Empty<byte>()"
|
||||
return string.format("Convert.FromBase64String(%q)", value)
|
||||
end
|
||||
|
||||
return "Array.Empty<byte>()"
|
||||
end
|
||||
|
||||
function Format.Bool(value)
|
||||
function Format.Bool(value: boolean?): string?
|
||||
if value then
|
||||
return "true"
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Format.String(value)
|
||||
function Format.String(value: string): string
|
||||
return string.format("%q", value)
|
||||
end
|
||||
|
||||
function Format.Int(value, default)
|
||||
if value == 2147483647 then
|
||||
function Format.Int(value: number): string
|
||||
if value == 2^31-1 then
|
||||
return "int.MaxValue"
|
||||
elseif value == -2147483648 then
|
||||
elseif value == -2^31 then
|
||||
return "int.MinValue"
|
||||
elseif value ~= 0 or default then
|
||||
else
|
||||
return string.format("%i", value)
|
||||
end
|
||||
end
|
||||
|
||||
function Format.Number(value, default)
|
||||
function Format.Number(value: number): string
|
||||
local int = math.floor(value)
|
||||
|
||||
if math.abs(value - int) < 0.001 then
|
||||
return Format.Int(int, default)
|
||||
return Format.Int(int)
|
||||
end
|
||||
|
||||
local result = string.format("%.5f", value)
|
||||
@ -46,12 +70,10 @@ function Format.Number(value, default)
|
||||
return result
|
||||
end
|
||||
|
||||
function Format.Double(value, default)
|
||||
local result = Format.Number(value, default)
|
||||
function Format.Double(value: number): string
|
||||
local result = Format.Number(value)
|
||||
|
||||
if not result then
|
||||
return nil
|
||||
elseif result == "inf" then
|
||||
if result == "inf" then
|
||||
return "double.MaxValue"
|
||||
elseif result == "-inf" then
|
||||
return "double.MinValue"
|
||||
@ -60,12 +82,10 @@ function Format.Double(value, default)
|
||||
end
|
||||
end
|
||||
|
||||
function Format.Float(value, default)
|
||||
local result = Format.Number(value, default)
|
||||
function Format.Float(value: number): string
|
||||
local result = Format.Number(value)
|
||||
|
||||
if not result then
|
||||
return nil
|
||||
elseif result == "inf" then
|
||||
if result == "inf" then
|
||||
return "float.MaxValue"
|
||||
elseif result == "-inf" then
|
||||
return "float.MinValue"
|
||||
@ -78,44 +98,44 @@ function Format.Float(value, default)
|
||||
end
|
||||
end
|
||||
|
||||
function Format.Flags(flag, enum)
|
||||
function Format.Flags(flags: IFlags, enum: IEnum): string
|
||||
local value = 0
|
||||
|
||||
for _,item in pairs(enum:GetEnumItems()) do
|
||||
if flag[item.Name] then
|
||||
if flags[item.Name] then
|
||||
value += (2 ^ item.Value)
|
||||
end
|
||||
end
|
||||
|
||||
return value
|
||||
return tostring(value)
|
||||
end
|
||||
|
||||
function Format.Axes(axes)
|
||||
function Format.Axes(axes: IAxes): string
|
||||
return "(Axes)" .. Format.Flags(axes, Enum.Axis)
|
||||
end
|
||||
|
||||
function Format.Faces(faces)
|
||||
function Format.Faces(faces: IFaces): string
|
||||
return "(Faces)" .. Format.Flags(faces, Enum.NormalId)
|
||||
end
|
||||
|
||||
function Format.EnumItem(item)
|
||||
function Format.EnumItem(item: EnumItem): string
|
||||
local enum = tostring(item.EnumType)
|
||||
return enum .. '.' .. item.Name
|
||||
end
|
||||
|
||||
function Format.BrickColor(brickColor)
|
||||
function Format.BrickColor(brickColor: BrickColor): string
|
||||
local fmt = "BrickColor.FromNumber(%i)"
|
||||
return fmt:format(brickColor.Number)
|
||||
end
|
||||
|
||||
function Format.Color3(color)
|
||||
function Format.Color3(color: Color3): string
|
||||
if color == Color3.new() then
|
||||
return "new Color3()"
|
||||
end
|
||||
|
||||
local r = Format.Float(color.R, true)
|
||||
local g = Format.Float(color.G, true)
|
||||
local b = Format.Float(color.B, true)
|
||||
local r = Format.Float(color.R)
|
||||
local g = Format.Float(color.G)
|
||||
local b = Format.Float(color.B)
|
||||
|
||||
local fmt = "%s(%s, %s, %s)";
|
||||
local constructor = "new Color3";
|
||||
@ -131,159 +151,176 @@ function Format.Color3(color)
|
||||
return fmt:format(constructor, r, g, b)
|
||||
end
|
||||
|
||||
function Format.UDim(udim)
|
||||
function Format.UDim(udim: UDim): string
|
||||
if udim == UDim.new() then
|
||||
return "new UDim()"
|
||||
end
|
||||
|
||||
local scale = Format.Float(udim.Scale, true)
|
||||
local offset = Format.Int(udim.Offset, true)
|
||||
local scale = Format.Float(udim.Scale)
|
||||
local offset = Format.Int(udim.Offset)
|
||||
|
||||
local fmt = "new UDim(%s, %s)"
|
||||
return fmt:format(scale, offset)
|
||||
end
|
||||
|
||||
function Format.UDim2(udim2)
|
||||
function Format.UDim2(udim2: UDim2): string
|
||||
if udim2 == UDim2.new() then
|
||||
return "new UDim2()"
|
||||
end
|
||||
|
||||
local xScale = Format.Float(udim2.X.Scale, true)
|
||||
local yScale = Format.Float(udim2.Y.Scale, true)
|
||||
local xScale = Format.Float(udim2.X.Scale)
|
||||
local yScale = Format.Float(udim2.Y.Scale)
|
||||
|
||||
local xOffset = Format.Int(udim2.X.Offset, true)
|
||||
local yOffset = Format.Int(udim2.Y.Offset, true)
|
||||
local xOffset = Format.Int(udim2.X.Offset)
|
||||
local yOffset = Format.Int(udim2.Y.Offset)
|
||||
|
||||
local fmt = "new UDim2(%s, %s, %s, %s)"
|
||||
return fmt:format(xScale, xOffset, yScale, yOffset)
|
||||
end
|
||||
|
||||
function Format.Vector2(v2)
|
||||
function Format.Vector2(v2: Vector2): string
|
||||
if v2.Magnitude < 0.001 then
|
||||
return "new Vector2()"
|
||||
end
|
||||
|
||||
local x = Format.Float(v2.X, true)
|
||||
local y = Format.Float(v2.Y, true)
|
||||
local x = Format.Float(v2.X)
|
||||
local y = Format.Float(v2.Y)
|
||||
|
||||
local fmt = "new Vector2(%s, %s)"
|
||||
return fmt:format(x, y)
|
||||
end
|
||||
|
||||
function Format.Vector3(v3)
|
||||
function Format.Vector3(v3: Vector3): string
|
||||
if v3.Magnitude < 0.001 then
|
||||
return "new Vector3()"
|
||||
end
|
||||
|
||||
local x = Format.Float(v3.X, true)
|
||||
local y = Format.Float(v3.Y, true)
|
||||
local z = Format.Float(v3.Z, true)
|
||||
local x = Format.Float(v3.X)
|
||||
local y = Format.Float(v3.Y)
|
||||
local z = Format.Float(v3.Z)
|
||||
|
||||
local fmt = "new Vector3(%s, %s, %s)"
|
||||
return fmt:format(x, y, z)
|
||||
end
|
||||
|
||||
function Format.CFrame(cf)
|
||||
local blankCF = CFrame.new()
|
||||
|
||||
if cf == blankCF then
|
||||
function Format.CFrame(cf: CFrame): string
|
||||
if cf == CFrame.identity then
|
||||
return "new CFrame()"
|
||||
end
|
||||
|
||||
local rot = cf - cf.p
|
||||
|
||||
if rot == blankCF then
|
||||
local fmt = "new CFrame(%s, %s, %s)"
|
||||
if cf.Rotation == CFrame.identity then
|
||||
local x = Format.Float(cf.X)
|
||||
local y = Format.Float(cf.Y)
|
||||
local z = Format.Float(cf.Z)
|
||||
|
||||
local x = Format.Float(cf.X, true)
|
||||
local y = Format.Float(cf.Y, true)
|
||||
local z = Format.Float(cf.Z, true)
|
||||
|
||||
return fmt:format(x, y, z)
|
||||
return string.format("new CFrame(%s, %s, %s)", x, y, z)
|
||||
else
|
||||
local comp = { cf:GetComponents() }
|
||||
local matrix = ""
|
||||
|
||||
for i = 1,12 do
|
||||
comp[i] = Format.Float(comp[i], true)
|
||||
for i = 1, 12 do
|
||||
local sep = (if i > 1 then ", " else "")
|
||||
matrix ..= sep .. Format.Float(comp[i])
|
||||
end
|
||||
|
||||
local fmt = "new CFrame(%s)"
|
||||
local matrix = table.concat(comp, ", ")
|
||||
|
||||
return fmt:format(matrix)
|
||||
return string.format("new CFrame(%s)", matrix)
|
||||
end
|
||||
end
|
||||
|
||||
function Format.NumberRange(nr)
|
||||
function Format.NumberRange(nr: NumberRange): string
|
||||
local min = nr.Min
|
||||
local max = nr.Max
|
||||
|
||||
local fmt = "new NumberRange(%s)"
|
||||
local value = Format.Float(min, true)
|
||||
local value = Format.Float(min)
|
||||
|
||||
if min ~= max then
|
||||
value = value .. ", " .. Format.Float(max, true)
|
||||
value = value .. ", " .. Format.Float(max)
|
||||
end
|
||||
|
||||
return fmt:format(value)
|
||||
end
|
||||
|
||||
function Format.Ray(ray)
|
||||
function Format.Ray(ray: Ray): string
|
||||
if ray == Ray.new() then
|
||||
return "new Ray()"
|
||||
end
|
||||
|
||||
local fmt = "new Ray(%s, %s)"
|
||||
|
||||
local origin = Format.Vector3(ray.Origin)
|
||||
local direction = Format.Vector3(ray.Direction)
|
||||
|
||||
local fmt = "new Ray(%s, %s)"
|
||||
return fmt:format(origin, direction)
|
||||
end
|
||||
|
||||
function Format.Rect(rect)
|
||||
function Format.Rect(rect: Rect): string
|
||||
local min: any = rect.Min
|
||||
local max: any = rect.Max
|
||||
|
||||
if min == max and min == Vector2.zero then
|
||||
return "new Rect()"
|
||||
end
|
||||
|
||||
min = Format.Vector2(min)
|
||||
max = Format.Vector2(max)
|
||||
|
||||
local fmt = "new Rect(%s, %s)"
|
||||
|
||||
local min = Format.Vector2(rect.Min)
|
||||
local max = Format.Vector2(rect.Max)
|
||||
|
||||
return fmt:format(min, max)
|
||||
end
|
||||
|
||||
function Format.ColorSequence(cs)
|
||||
function Format.ColorSequence(cs: ColorSequence): string
|
||||
local csKey = cs.Keypoints[1]
|
||||
|
||||
local fmt = "new ColorSequence(%s)"
|
||||
local value = tostring(csKey.Value)
|
||||
|
||||
local fmt = "new ColorSequence(%s)"
|
||||
return fmt:format(value)
|
||||
end
|
||||
|
||||
function Format.NumberSequence(ns)
|
||||
function Format.NumberSequence(ns: NumberSequence): string
|
||||
local nsKey = ns.Keypoints[1]
|
||||
|
||||
local fmt = "new NumberSequence(%s)"
|
||||
local value = Format.Float(nsKey.Value, true)
|
||||
|
||||
local value = Format.Float(nsKey.Value)
|
||||
return fmt:format(value)
|
||||
end
|
||||
|
||||
function Format.Vector3int16(v3)
|
||||
function Format.Vector3int16(v3: Vector3int16): string
|
||||
if v3 == Vector3int16.new() then
|
||||
return "new Vector3int16()"
|
||||
end
|
||||
|
||||
local x = Format.Int(v3.X, true)
|
||||
local y = Format.Int(v3.Y, true)
|
||||
local z = Format.Int(v3.Z, true)
|
||||
local x = Format.Int(v3.X)
|
||||
local y = Format.Int(v3.Y)
|
||||
local z = Format.Int(v3.Z)
|
||||
|
||||
local fmt = "new Vector3int16(%s, %s, %s)"
|
||||
return fmt:format(x, y, z)
|
||||
end
|
||||
|
||||
function Format.SharedString(str)
|
||||
function Format.SharedString(str: string): string
|
||||
local fmt = "SharedString.FromBase64(%q)"
|
||||
return fmt:format(str)
|
||||
end
|
||||
|
||||
function Format.FontFace(font: Font): string
|
||||
local family = string.format("%q", font.Family)
|
||||
local args = { family }
|
||||
|
||||
local style = font.Style
|
||||
local weight = font.Weight
|
||||
|
||||
if style ~= Enum.FontStyle.Normal then
|
||||
table.insert(args, "FontStyle." .. style.Name)
|
||||
end
|
||||
|
||||
if #args > 1 or weight ~= Enum.FontWeight.Regular then
|
||||
table.insert(args, "FontWeight." .. weight.Name)
|
||||
end
|
||||
|
||||
local fmt = "new FontFace(%s)"
|
||||
local argStr = table.concat(args, ", ")
|
||||
|
||||
return fmt:format(argStr)
|
||||
end
|
||||
|
||||
return Format
|
@ -63,6 +63,29 @@ local GuiTextMixIn =
|
||||
|
||||
return
|
||||
{
|
||||
AnimationRigData =
|
||||
{
|
||||
Add =
|
||||
{
|
||||
label = "BinaryString";
|
||||
name = "BinaryString";
|
||||
parent = "BinaryString";
|
||||
postTransform = "BinaryString";
|
||||
preTransform = "BinaryString";
|
||||
transform = "BinaryString";
|
||||
};
|
||||
|
||||
Defaults =
|
||||
{
|
||||
label = "AQAAAAEAAAAAAAAA";
|
||||
name = "AQAAAAEAAAAAAAAA";
|
||||
parent = "AQAAAAEAAAAAAA==";
|
||||
postTransform = "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=";
|
||||
preTransform = "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=";
|
||||
transform = "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=";
|
||||
}
|
||||
};
|
||||
|
||||
BallSocketConstraint =
|
||||
{
|
||||
-- Why does this even exist?
|
||||
@ -73,13 +96,21 @@ return
|
||||
{
|
||||
Add =
|
||||
{
|
||||
MaterialVariantSerialized = "string";
|
||||
MaterialVariant = "string";
|
||||
Color3uint8 = "Color3uint8";
|
||||
size = "Vector3";
|
||||
};
|
||||
|
||||
Redirect =
|
||||
{
|
||||
Position = "CFrame.Position";
|
||||
Position =
|
||||
{
|
||||
Get = "CFrame.Position";
|
||||
Set = "CFrame = new CFrame(value) * CFrame.Rotation";
|
||||
};
|
||||
|
||||
MaterialVariant = "MaterialVariantSerialized";
|
||||
BrickColor = UseColor3("Color");
|
||||
Color = "Color3uint8";
|
||||
Size = "size";
|
||||
@ -88,6 +119,7 @@ return
|
||||
Defaults =
|
||||
{
|
||||
Color3uint8 = Color3.fromRGB(163, 162, 165);
|
||||
MaterialVariantSerialized = "";
|
||||
size = Vector3.new(4, 1.2, 2);
|
||||
};
|
||||
};
|
||||
@ -200,6 +232,12 @@ return
|
||||
Size = "size_xml";
|
||||
};
|
||||
};
|
||||
|
||||
FloatCurve =
|
||||
{
|
||||
Add = { ValuesAndTimes = "BinaryString" };
|
||||
Defaults = { ValuesAndTimes = "AAAAAAEAAAAKAAAAAAAAFkUAAAAA" };
|
||||
};
|
||||
|
||||
FormFactorPart =
|
||||
{
|
||||
@ -244,6 +282,15 @@ return
|
||||
Transparency = "BackgroundTransparency";
|
||||
}
|
||||
};
|
||||
|
||||
HiddenSurfaceRemovalAsset =
|
||||
{
|
||||
Add =
|
||||
{
|
||||
HSRData = "BinaryString";
|
||||
HSRMeshIdData = "BinaryString";
|
||||
}
|
||||
};
|
||||
|
||||
HttpService =
|
||||
{
|
||||
@ -355,6 +402,60 @@ return
|
||||
Source = "ProtectedString";
|
||||
};
|
||||
};
|
||||
|
||||
MarkerCurve =
|
||||
{
|
||||
Add = { ValuesAndTimes = "BinaryString" };
|
||||
Defaults = { ValuesAndTimes = "AAAAAAEAAAAKAAAAAAAAFkUAAAAA" };
|
||||
};
|
||||
|
||||
MaterialService =
|
||||
{
|
||||
Defaults =
|
||||
{
|
||||
AsphaltName = "Asphalt";
|
||||
BasaltName = "Basalt";
|
||||
BrickName = "Brick";
|
||||
CobblestoneName = "Cobblestone";
|
||||
ConcreteName = "Concrete";
|
||||
CorrodedMetalName = "CorrodedMetal";
|
||||
CrackedLavaName = "CrackedLava";
|
||||
DiamondPlateName = "DiamondPlate";
|
||||
FabricName = "Fabric";
|
||||
FoilName = "Foil";
|
||||
GlacierName = "Glacier";
|
||||
GraniteName = "Granite";
|
||||
GrassName = "Grass";
|
||||
GroundName = "Ground";
|
||||
IceName = "Ice";
|
||||
LeafyGrassName = "LeafyGrass";
|
||||
LimestoneName = "Limestone";
|
||||
MarbleName = "Marble";
|
||||
MetalName = "Metal";
|
||||
MudName = "Mud";
|
||||
PavementName = "Pavement";
|
||||
PebbleName = "Pebble";
|
||||
PlasticName = "Plastic";
|
||||
RockName = "Rock";
|
||||
SaltName = "Salt";
|
||||
SandName = "Sand";
|
||||
SandstoneName = "Sandstone";
|
||||
SlateName = "Slate";
|
||||
SmoothPlasticName = "SmoothPlastic";
|
||||
SnowName = "Snow";
|
||||
WoodName = "Wood";
|
||||
WoodPlanksName = "WoodPlanks";
|
||||
}
|
||||
};
|
||||
|
||||
MaterialVariant =
|
||||
{
|
||||
Add =
|
||||
{
|
||||
TexturePack0 = "Content";
|
||||
TexturePack1 = "Content";
|
||||
}
|
||||
};
|
||||
|
||||
MeshPart =
|
||||
{
|
||||
@ -457,6 +558,12 @@ return
|
||||
LuobuWhitelisted = TryGetEnumItem("TriStateBoolean", "Unknown");
|
||||
};
|
||||
};
|
||||
|
||||
RotationCurve =
|
||||
{
|
||||
Add = { ValuesAndTimes = "BinaryString" };
|
||||
Defaults = { ValuesAndTimes = "AAAAAAEAAAAKAAAAAAAAFkUAAAAA" };
|
||||
};
|
||||
|
||||
SelectionBox =
|
||||
{
|
||||
@ -604,6 +711,11 @@ return
|
||||
MaterialColors = "AAAAAAAAan8/P39rf2Y/ilY+j35fi21PZmxvZbDqw8faiVpHOi4kHh4lZlw76JxKc3trhHtagcLgc4RKxr21zq2UlJSM";
|
||||
};
|
||||
};
|
||||
|
||||
TerrainDetail =
|
||||
{
|
||||
Add = { TexturePack1 = "Content"; }
|
||||
};
|
||||
|
||||
TerrainRegion =
|
||||
{
|
||||
|
@ -2,6 +2,7 @@ local Selection = game:GetService("Selection")
|
||||
local HttpService = game:GetService("HttpService")
|
||||
local StarterPlayer = game:GetService("StarterPlayer")
|
||||
local StudioService = game:GetService("StudioService")
|
||||
local TextChatService = game:GetService("TextChatService")
|
||||
|
||||
local classes = {}
|
||||
local outStream = ""
|
||||
@ -14,12 +15,16 @@ local singletons =
|
||||
ParabolaAdornment = Instance.new("BoxHandleAdornment"); -- close enough
|
||||
StarterPlayerScripts = StarterPlayer:WaitForChild("StarterPlayerScripts");
|
||||
StarterCharacterScripts = StarterPlayer:WaitForChild("StarterCharacterScripts");
|
||||
ChatWindowConfiguration = TextChatService:WaitForChild("ChatWindowConfiguration");
|
||||
ChatInputBarConfiguration = TextChatService:WaitForChild("ChatInputBarConfiguration");
|
||||
}
|
||||
|
||||
local exceptionClasses =
|
||||
{
|
||||
PackageLink = true;
|
||||
ScriptDebugger = true;
|
||||
ChatWindowConfiguration = true;
|
||||
ChatInputBarConfiguration = true;
|
||||
}
|
||||
|
||||
local numberTypes =
|
||||
@ -205,7 +210,10 @@ end
|
||||
-- Formatting
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local formatting = require(script.Formatting)
|
||||
type FormatFunc = (any) -> string;
|
||||
type Format = { [string]: FormatFunc }
|
||||
|
||||
local formatting: Format = require(script.Formatting)
|
||||
|
||||
local formatLinks =
|
||||
{
|
||||
@ -227,7 +235,7 @@ local formatLinks =
|
||||
["ProtectedString"] = "String";
|
||||
}
|
||||
|
||||
local function getFormatFunction(valueType)
|
||||
local function getFormatFunction(valueType: string): FormatFunc?
|
||||
if not formatting[valueType] then
|
||||
valueType = formatLinks[valueType]
|
||||
end
|
||||
@ -307,6 +315,8 @@ local function generateClasses()
|
||||
{
|
||||
Axis = true;
|
||||
FontSize = true;
|
||||
FontStyle = true;
|
||||
FontWeight = true;
|
||||
}
|
||||
|
||||
for _,class in ipairs(apiDump.Classes) do
|
||||
@ -323,7 +333,9 @@ local function generateClasses()
|
||||
|
||||
if classTags.Service then
|
||||
pcall(function ()
|
||||
class.Object = game:GetService(className)
|
||||
if not className:find("Network") then
|
||||
class.Object = game:GetService(className)
|
||||
end
|
||||
end)
|
||||
elseif not classTags.NotCreatable then
|
||||
pcall(function ()
|
||||
@ -364,10 +376,6 @@ local function generateClasses()
|
||||
writeLine("using RobloxFiles.Utility;")
|
||||
writeLine()
|
||||
|
||||
-- writeLine("#pragma warning disable CA1041 // Provide ObsoleteAttribute message")
|
||||
-- writeLine("#pragma warning disable CA1051 // Do not declare visible instance fields")
|
||||
-- writeLine("#pragma warning disable CA1707 // Identifiers should not contain underscores")
|
||||
-- writeLine("#pragma warning disable CA1716 // Identifiers should not match keywords")
|
||||
writeLine("#pragma warning disable IDE1006 // Naming Styles")
|
||||
writeLine()
|
||||
|
||||
@ -468,7 +476,10 @@ local function generateClasses()
|
||||
local propTags = getTags(prop)
|
||||
|
||||
local serial = prop.Serialization
|
||||
local valueType = prop.ValueType.Name
|
||||
local typeData = prop.ValueType
|
||||
|
||||
local category = typeData.Category
|
||||
local valueType = typeData.Name
|
||||
|
||||
local redirect = redirectProps[propName]
|
||||
local couldSave = (serial.CanSave or propTags.Deprecated or redirect)
|
||||
@ -489,6 +500,8 @@ local function generateClasses()
|
||||
valueType = "long"
|
||||
elseif valueType == "BinaryString" then
|
||||
valueType = "byte[]"
|
||||
elseif valueType == "Font" and category ~= "Enum" then
|
||||
valueType = "FontFace"
|
||||
end
|
||||
|
||||
local first = name:sub(1, 1)
|
||||
@ -567,33 +580,29 @@ local function generateClasses()
|
||||
end)
|
||||
end
|
||||
|
||||
local typeData = prop.ValueType
|
||||
local category = typeData.Category
|
||||
|
||||
if not gotValue and category ~= "Class" then
|
||||
-- Fallback to implicit defaults
|
||||
local typeName = typeData.Name
|
||||
|
||||
if numberTypes[typeName] then
|
||||
|
||||
if numberTypes[valueType] then
|
||||
value = 0
|
||||
gotValue = true
|
||||
elseif stringTypes[typeName] then
|
||||
elseif stringTypes[valueType] then
|
||||
value = ""
|
||||
gotValue = true
|
||||
elseif typeName == "SharedString" then
|
||||
elseif valueType == "SharedString" then
|
||||
value = "yuZpQdnvvUBOTYh1jqZ2cA=="
|
||||
gotValue = true
|
||||
elseif category == "DataType" then
|
||||
local DataType = env[typeName]
|
||||
local DataType = env[valueType]
|
||||
|
||||
if DataType and typeof(DataType) == "table" and not rawget(env, typeName) then
|
||||
if DataType and typeof(DataType) == "table" and not rawget(env, valueType) then
|
||||
pcall(function ()
|
||||
value = DataType.new()
|
||||
gotValue = true
|
||||
end)
|
||||
end
|
||||
elseif category == "Enum" then
|
||||
local enum = Enum[typeName]
|
||||
local enum = Enum[valueType]
|
||||
local lowestId = math.huge
|
||||
local lowest
|
||||
|
||||
@ -623,7 +632,8 @@ local function generateClasses()
|
||||
end
|
||||
|
||||
if gotValue then
|
||||
local formatFunc = getFormatFunction(valueType)
|
||||
local formatKey = if category == "Enum" then "Enum" else valueType
|
||||
local formatFunc = getFormatFunction(formatKey)
|
||||
|
||||
if not formatFunc then
|
||||
local literal = typeof(value)
|
||||
@ -636,10 +646,12 @@ local function generateClasses()
|
||||
|
||||
local result
|
||||
|
||||
if typeof(formatFunc) == "string" then
|
||||
result = formatFunc
|
||||
else
|
||||
result = formatFunc(value)
|
||||
if formatFunc then
|
||||
if typeof(formatFunc) == "string" then
|
||||
result = formatFunc
|
||||
else
|
||||
result = formatFunc(value)
|
||||
end
|
||||
end
|
||||
|
||||
if result ~= nil then
|
||||
|
@ -77,6 +77,7 @@
|
||||
<Compile Include="DataTypes\Content.cs" />
|
||||
<Compile Include="DataTypes\EulerAngles.cs" />
|
||||
<Compile Include="DataTypes\Faces.cs" />
|
||||
<Compile Include="DataTypes\FontFace.cs" />
|
||||
<Compile Include="DataTypes\NumberRange.cs" />
|
||||
<Compile Include="DataTypes\NumberSequence.cs" />
|
||||
<Compile Include="DataTypes\NumberSequenceKeypoint.cs" />
|
||||
@ -115,6 +116,7 @@
|
||||
<Compile Include="Tokens\Enum.cs" />
|
||||
<Compile Include="Tokens\Faces.cs" />
|
||||
<Compile Include="Tokens\Float.cs" />
|
||||
<Compile Include="Tokens\Font.cs" />
|
||||
<Compile Include="Tokens\Int.cs" />
|
||||
<Compile Include="Tokens\Int64.cs" />
|
||||
<Compile Include="Tokens\NumberRange.cs" />
|
||||
|
89
Tokens/Font.cs
Normal file
89
Tokens/Font.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
using RobloxFiles.Enums;
|
||||
using RobloxFiles.DataTypes;
|
||||
|
||||
namespace RobloxFiles.Tokens
|
||||
{
|
||||
public class FontToken : IXmlPropertyToken, IAttributeToken<FontFace>
|
||||
{
|
||||
public string XmlPropertyToken => "Font";
|
||||
public AttributeType AttributeType => AttributeType.FontFace;
|
||||
|
||||
public bool ReadProperty(Property prop, XmlNode node)
|
||||
{
|
||||
try
|
||||
{
|
||||
var familyNode = node["Family"];
|
||||
var family = familyNode.InnerText;
|
||||
|
||||
var weightNode = node["Weight"];
|
||||
var weight = (FontWeight)uint.Parse(weightNode.InnerText);
|
||||
|
||||
var styleNode = node["Style"];
|
||||
Enum.TryParse(styleNode.InnerText, out FontStyle style);
|
||||
|
||||
prop.Value = new FontFace(family, weight, style);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteProperty(Property prop, XmlDocument doc, XmlNode node)
|
||||
{
|
||||
FontFace font = prop.CastValue<FontFace>();
|
||||
var weight = (uint)font.Weight;
|
||||
|
||||
string family = font.Family;
|
||||
string contentType = "null";
|
||||
|
||||
if (family.Length > 0)
|
||||
contentType = "url";
|
||||
|
||||
var contentNode = doc.CreateElement(contentType);
|
||||
contentNode.InnerText = family;
|
||||
|
||||
var familyNode = doc.CreateElement("Family");
|
||||
familyNode.AppendChild(contentNode);
|
||||
node.AppendChild(familyNode);
|
||||
|
||||
var weightNode = doc.CreateElement("Weight");
|
||||
weightNode.InnerText = $"{weight}";
|
||||
node.AppendChild(weightNode);
|
||||
|
||||
var styleNode = doc.CreateElement("Style");
|
||||
styleNode.InnerText = $"{font.Style}";
|
||||
node.AppendChild(styleNode);
|
||||
}
|
||||
|
||||
public FontFace ReadAttribute(RbxAttribute attribute)
|
||||
{
|
||||
var weight = (FontStyle)attribute.ReadShort();
|
||||
var style = (FontWeight)attribute.ReadByte();
|
||||
|
||||
var family = attribute.ReadString();
|
||||
_ = attribute.ReadInt(); // Reserved
|
||||
|
||||
return new FontFace(family, style, weight);
|
||||
}
|
||||
|
||||
public void WriteAttribute(RbxAttribute attribute, FontFace value)
|
||||
{
|
||||
var weight = (short)value.Weight;
|
||||
var style = (byte)value.Style;
|
||||
|
||||
var family = value.Family;
|
||||
var writer = attribute.Writer;
|
||||
|
||||
writer.Write(weight);
|
||||
writer.Write(style);
|
||||
|
||||
attribute.WriteString(family);
|
||||
attribute.WriteInt(0); // Reserved
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,8 @@ namespace RobloxFiles
|
||||
Rect = 28,
|
||||
// PhysicalProperties = 29
|
||||
// Region3 = 31,
|
||||
// Region3int16 = 32
|
||||
// Region3int16 = 32,
|
||||
FontFace = 33
|
||||
}
|
||||
|
||||
public class RbxAttribute : IDisposable
|
||||
|
@ -688,6 +688,8 @@ namespace RobloxFiles
|
||||
|
||||
if (fieldType.IsEnum)
|
||||
xmlToken = "token";
|
||||
else if (propType == PropertyType.Ref)
|
||||
xmlToken = "Ref";
|
||||
|
||||
switch (xmlToken)
|
||||
{
|
||||
@ -723,6 +725,11 @@ namespace RobloxFiles
|
||||
xmlToken = "CoordinateFrame";
|
||||
break;
|
||||
}
|
||||
case "FontFace":
|
||||
{
|
||||
xmlToken = "Font";
|
||||
break;
|
||||
}
|
||||
case "Optional`1":
|
||||
{
|
||||
// TODO: If more optional types are added,
|
||||
|
@ -41,7 +41,8 @@ namespace RobloxFiles
|
||||
SharedString,
|
||||
ProtectedString,
|
||||
OptionalCFrame,
|
||||
UniqueId
|
||||
UniqueId,
|
||||
FontFace
|
||||
}
|
||||
|
||||
public class Property
|
||||
@ -72,29 +73,30 @@ namespace RobloxFiles
|
||||
{ typeof(double), PropertyType.Double },
|
||||
{ typeof(string), PropertyType.String },
|
||||
|
||||
{ typeof(Ray), PropertyType.Ray },
|
||||
{ typeof(Rect), PropertyType.Rect },
|
||||
{ typeof(UDim), PropertyType.UDim },
|
||||
{ typeof(UDim2), PropertyType.UDim2 },
|
||||
{ typeof(CFrame), PropertyType.CFrame },
|
||||
{ typeof(Color3), PropertyType.Color3 },
|
||||
{ typeof(Content), PropertyType.String },
|
||||
{ typeof(Vector2), PropertyType.Vector2 },
|
||||
{ typeof(Vector3), PropertyType.Vector3 },
|
||||
{ typeof(Ray), PropertyType.Ray },
|
||||
{ typeof(Rect), PropertyType.Rect },
|
||||
{ typeof(UDim), PropertyType.UDim },
|
||||
{ typeof(UDim2), PropertyType.UDim2 },
|
||||
{ typeof(CFrame), PropertyType.CFrame },
|
||||
{ typeof(Color3), PropertyType.Color3 },
|
||||
{ typeof(Content), PropertyType.String },
|
||||
{ typeof(Vector2), PropertyType.Vector2 },
|
||||
{ typeof(Vector3), PropertyType.Vector3 },
|
||||
{ typeof(FontFace), PropertyType.FontFace },
|
||||
|
||||
{ typeof(BrickColor), PropertyType.BrickColor },
|
||||
{ typeof(Quaternion), PropertyType.Quaternion },
|
||||
{ typeof(Color3uint8), PropertyType.Color3uint8 },
|
||||
{ typeof(NumberRange), PropertyType.NumberRange },
|
||||
{ typeof(SharedString), PropertyType.SharedString },
|
||||
{ typeof(Vector3int16), PropertyType.Vector3int16 },
|
||||
{ typeof(BrickColor), PropertyType.BrickColor },
|
||||
{ typeof(Quaternion), PropertyType.Quaternion },
|
||||
{ typeof(Color3uint8), PropertyType.Color3uint8 },
|
||||
{ typeof(NumberRange), PropertyType.NumberRange },
|
||||
{ typeof(SharedString), PropertyType.SharedString },
|
||||
{ typeof(Vector3int16), PropertyType.Vector3int16 },
|
||||
|
||||
{ typeof(ColorSequence), PropertyType.ColorSequence },
|
||||
{ typeof(NumberSequence), PropertyType.NumberSequence },
|
||||
{ typeof(Optional<CFrame>), PropertyType.OptionalCFrame },
|
||||
{ typeof(ColorSequence), PropertyType.ColorSequence },
|
||||
{ typeof(NumberSequence), PropertyType.NumberSequence },
|
||||
{ typeof(Optional<CFrame>), PropertyType.OptionalCFrame },
|
||||
|
||||
{ typeof(ProtectedString), PropertyType.String },
|
||||
{ typeof(PhysicalProperties), PropertyType.PhysicalProperties },
|
||||
{ typeof(ProtectedString), PropertyType.String },
|
||||
{ typeof(PhysicalProperties), PropertyType.PhysicalProperties },
|
||||
};
|
||||
|
||||
private void ImproviseRawBuffer()
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -66,6 +66,11 @@ namespace RobloxFiles.XmlFormat
|
||||
|
||||
switch (prop.Type)
|
||||
{
|
||||
case PropertyType.Ref:
|
||||
{
|
||||
propType = "Ref";
|
||||
break;
|
||||
}
|
||||
case PropertyType.CFrame:
|
||||
case PropertyType.Quaternion:
|
||||
{
|
||||
@ -106,6 +111,9 @@ namespace RobloxFiles.XmlFormat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prop.Type == PropertyType.Ref)
|
||||
propType = "Ref";
|
||||
|
||||
IXmlPropertyToken handler = XmlPropertyTokens.GetHandler(propType);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user