Initial commit.
There's a lot of code at play here, so I haven't tested it yet. A good chunk of the components are available though.
This commit is contained in:
parent
b4825c146f
commit
9cfd5b2211
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
bin/*
|
||||
obj/*
|
||||
packages/*
|
||||
.vs/*
|
||||
*.suo
|
||||
*.ide
|
124
BinaryFormat/BinaryFile.cs
Normal file
124
BinaryFormat/BinaryFile.cs
Normal file
@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Roblox.BinaryFormat.Chunks;
|
||||
|
||||
namespace Roblox.BinaryFormat
|
||||
{
|
||||
public class RobloxBinaryFile : RobloxFile
|
||||
{
|
||||
public const string FileSignature = "<roblox!\x89\xff\x0d\x0a\x1a\x0a";
|
||||
public readonly List<RobloxBinaryChunk> BinaryChunks = new List<RobloxBinaryChunk>();
|
||||
|
||||
public readonly PRNT ParentIds;
|
||||
public readonly META Metadata;
|
||||
|
||||
public readonly Dictionary<int, INST> INSTs = new Dictionary<int, INST>();
|
||||
public readonly List<PROP> PROPs = new List<PROP>();
|
||||
|
||||
public readonly RobloxInstance[] Instances;
|
||||
|
||||
public readonly ushort Version;
|
||||
public readonly uint NumTypes;
|
||||
public readonly uint NumInstances;
|
||||
public readonly long Reserved;
|
||||
|
||||
public RobloxBinaryFile(byte[] contents)
|
||||
{
|
||||
using (MemoryStream file = new MemoryStream(contents))
|
||||
using (RobloxBinaryReader reader = new RobloxBinaryReader(file))
|
||||
{
|
||||
byte[] binSignature = reader.ReadBytes(14);
|
||||
string signature = Encoding.UTF7.GetString(binSignature);
|
||||
|
||||
if (signature != FileSignature)
|
||||
throw new InvalidDataException("Signature does not match RobloxBinaryFile.FileSignature!");
|
||||
|
||||
Version = reader.ReadUInt16();
|
||||
NumTypes = reader.ReadUInt32();
|
||||
NumInstances = reader.ReadUInt32();
|
||||
Reserved = reader.ReadInt64();
|
||||
|
||||
// Begin reading the file chunks.
|
||||
bool reading = true;
|
||||
Instances = new RobloxInstance[NumInstances];
|
||||
BinaryChunks = new List<RobloxBinaryChunk>();
|
||||
|
||||
while (reading)
|
||||
{
|
||||
try
|
||||
{
|
||||
RobloxBinaryChunk chunk = new RobloxBinaryChunk(reader);
|
||||
BinaryChunks.Add(chunk);
|
||||
|
||||
switch (chunk.ChunkType)
|
||||
{
|
||||
case "INST":
|
||||
INST inst = new INST(chunk);
|
||||
INSTs.Add(inst.TypeIndex, inst);
|
||||
break;
|
||||
case "PROP":
|
||||
PROP prop = new PROP(chunk);
|
||||
PROPs.Add(prop);
|
||||
break;
|
||||
case "PRNT":
|
||||
PRNT prnt = new PRNT(chunk);
|
||||
ParentIds = prnt;
|
||||
break;
|
||||
case "META":
|
||||
META meta = new META(chunk);
|
||||
Metadata = meta;
|
||||
break;
|
||||
case "END\0":
|
||||
reading = false;
|
||||
break;
|
||||
default:
|
||||
BinaryChunks.Remove(chunk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
throw new Exception("Unexpected end of file!");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (INST chunk in INSTs.Values)
|
||||
{
|
||||
foreach (int id in chunk.InstanceIds)
|
||||
{
|
||||
RobloxInstance inst = new RobloxInstance();
|
||||
inst.ClassName = chunk.TypeName;
|
||||
Instances[id] = inst;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (PROP prop in PROPs)
|
||||
{
|
||||
INST chunk = INSTs[prop.Index];
|
||||
prop.ReadPropertyValues(chunk, Instances);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ParentIds.NumRelations; i++)
|
||||
{
|
||||
int childId = ParentIds.ChildrenIds[i];
|
||||
int parentId = ParentIds.ParentIds[i];
|
||||
|
||||
RobloxInstance child = Instances[childId];
|
||||
|
||||
if (parentId >= 0)
|
||||
{
|
||||
var parent = Instances[parentId];
|
||||
child.Parent = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
Trunk.Add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
BinaryFormat/Chunk.cs
Normal file
57
BinaryFormat/Chunk.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using LZ4;
|
||||
|
||||
namespace Roblox.BinaryFormat
|
||||
{
|
||||
public class RobloxBinaryChunk
|
||||
{
|
||||
public readonly string ChunkType;
|
||||
|
||||
public readonly int CompressedSize;
|
||||
public readonly byte[] CompressedData;
|
||||
|
||||
public readonly int Size;
|
||||
public readonly int Reserved;
|
||||
public readonly byte[] Data;
|
||||
|
||||
public bool HasCompressedData => (CompressedSize > 0);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ChunkType + " Chunk [" + Size + ']';
|
||||
}
|
||||
|
||||
public RobloxBinaryReader GetReader(string chunkType)
|
||||
{
|
||||
if (ChunkType == chunkType)
|
||||
{
|
||||
MemoryStream buffer = new MemoryStream(Data);
|
||||
return new RobloxBinaryReader(buffer);
|
||||
}
|
||||
|
||||
throw new Exception("Expected " + chunkType + " ChunkType from the input RobloxBinaryChunk");
|
||||
}
|
||||
|
||||
public RobloxBinaryChunk(RobloxBinaryReader reader)
|
||||
{
|
||||
byte[] bChunkType = reader.ReadBytes(4);
|
||||
ChunkType = Encoding.ASCII.GetString(bChunkType);
|
||||
|
||||
CompressedSize = reader.ReadInt32();
|
||||
Size = reader.ReadInt32();
|
||||
Reserved = reader.ReadInt32();
|
||||
|
||||
if (HasCompressedData)
|
||||
{
|
||||
CompressedData = reader.ReadBytes(CompressedSize);
|
||||
Data = LZ4Codec.Decode(CompressedData, 0, CompressedSize, Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = reader.ReadBytes(Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
BinaryFormat/ChunkTypes/INST.cs
Normal file
36
BinaryFormat/ChunkTypes/INST.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Roblox.BinaryFormat.Chunks
|
||||
{
|
||||
public class INST
|
||||
{
|
||||
public readonly int TypeIndex;
|
||||
public readonly string TypeName;
|
||||
public readonly bool IsService;
|
||||
public readonly int NumInstances;
|
||||
public readonly int[] InstanceIds;
|
||||
|
||||
public Dictionary<string, PROP> Properties;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return TypeName;
|
||||
}
|
||||
|
||||
public INST(RobloxBinaryChunk chunk)
|
||||
{
|
||||
using (RobloxBinaryReader reader = chunk.GetReader("INST"))
|
||||
{
|
||||
TypeIndex = reader.ReadInt32();
|
||||
TypeName = reader.ReadString();
|
||||
IsService = reader.ReadBoolean();
|
||||
|
||||
NumInstances = reader.ReadInt32();
|
||||
InstanceIds = reader.ReadInstanceIds(NumInstances);
|
||||
}
|
||||
|
||||
Properties = new Dictionary<string, PROP>();
|
||||
}
|
||||
}
|
||||
}
|
27
BinaryFormat/ChunkTypes/META.cs
Normal file
27
BinaryFormat/ChunkTypes/META.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Roblox.BinaryFormat.Chunks
|
||||
{
|
||||
public class META
|
||||
{
|
||||
public int NumEntries;
|
||||
public Dictionary<string, string> Entries;
|
||||
|
||||
public META(RobloxBinaryChunk chunk)
|
||||
{
|
||||
using (RobloxBinaryReader reader = chunk.GetReader("META"))
|
||||
{
|
||||
NumEntries = reader.ReadInt32();
|
||||
Entries = new Dictionary<string, string>(NumEntries);
|
||||
|
||||
for (int i = 0; i < NumEntries; i++)
|
||||
{
|
||||
string key = reader.ReadString();
|
||||
string value = reader.ReadString();
|
||||
Entries.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
BinaryFormat/ChunkTypes/PRNT.cs
Normal file
23
BinaryFormat/ChunkTypes/PRNT.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace Roblox.BinaryFormat.Chunks
|
||||
{
|
||||
public class PRNT
|
||||
{
|
||||
public readonly byte Format;
|
||||
public readonly int NumRelations;
|
||||
|
||||
public readonly int[] ChildrenIds;
|
||||
public readonly int[] ParentIds;
|
||||
|
||||
public PRNT(RobloxBinaryChunk chunk)
|
||||
{
|
||||
using (RobloxBinaryReader reader = chunk.GetReader("PRNT"))
|
||||
{
|
||||
Format = reader.ReadByte();
|
||||
NumRelations = reader.ReadInt32();
|
||||
|
||||
ChildrenIds = reader.ReadInstanceIds(NumRelations);
|
||||
ParentIds = reader.ReadInstanceIds(NumRelations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
422
BinaryFormat/ChunkTypes/PROP.cs
Normal file
422
BinaryFormat/ChunkTypes/PROP.cs
Normal file
@ -0,0 +1,422 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using Roblox.Enums;
|
||||
using Roblox.DataTypes;
|
||||
using Roblox.DataTypes.Utility;
|
||||
|
||||
namespace Roblox.BinaryFormat.Chunks
|
||||
{
|
||||
public class PROP
|
||||
{
|
||||
public int Index { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
|
||||
public readonly PropertyType Type;
|
||||
public RobloxProperty[] Properties => props;
|
||||
|
||||
private RobloxBinaryReader reader;
|
||||
private RobloxProperty[] props;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
Type PropertyType = typeof(PropertyType);
|
||||
return '[' + Enum.GetName(PropertyType, Type) + "] " + Name;
|
||||
}
|
||||
|
||||
public PROP(RobloxBinaryChunk chunk)
|
||||
{
|
||||
reader = chunk.GetReader("PROP");
|
||||
|
||||
Index = reader.ReadInt32();
|
||||
Name = reader.ReadString();
|
||||
|
||||
try
|
||||
{
|
||||
byte propType = reader.ReadByte();
|
||||
Type = (PropertyType)propType;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Type = PropertyType.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadPropertyValues(INST instChunk, RobloxInstance[] instMap)
|
||||
{
|
||||
int[] ids = instChunk.InstanceIds;
|
||||
int instCount = ids.Length;
|
||||
|
||||
props = new RobloxProperty[instCount];
|
||||
|
||||
for (int i = 0; i < instCount; i++)
|
||||
{
|
||||
RobloxProperty prop = new RobloxProperty();
|
||||
prop.Name = Name;
|
||||
prop.Type = Type;
|
||||
|
||||
Properties[i] = prop;
|
||||
instMap[ids[i]].Properties.Add(prop);
|
||||
}
|
||||
|
||||
// Setup some short-hand functions for frequently used actions.
|
||||
var readInstanceInts = new Func<int[]>(() => reader.ReadInts(instCount));
|
||||
var readInstanceFloats = new Func<float[]>(() => reader.ReadFloats(instCount));
|
||||
|
||||
var loadProperties = new Action<Func<int, object>>(read =>
|
||||
{
|
||||
for (int i = 0; i < instCount; i++)
|
||||
{
|
||||
object result = read(i);
|
||||
props[i].Value = result;
|
||||
}
|
||||
});
|
||||
|
||||
// Process the property data based on the property type.
|
||||
switch (Type)
|
||||
{
|
||||
case PropertyType.String:
|
||||
loadProperties(i => reader.ReadString());
|
||||
break;
|
||||
case PropertyType.Bool:
|
||||
loadProperties(i => reader.ReadBoolean());
|
||||
break;
|
||||
case PropertyType.Int:
|
||||
int[] ints = readInstanceInts();
|
||||
loadProperties(i => ints[i]);
|
||||
break;
|
||||
case PropertyType.Float:
|
||||
float[] floats = readInstanceFloats();
|
||||
loadProperties(i => floats[i]);
|
||||
break;
|
||||
case PropertyType.Double:
|
||||
loadProperties(i => reader.ReadDouble());
|
||||
break;
|
||||
case PropertyType.UDim:
|
||||
float[] scales = readInstanceFloats();
|
||||
int[] offsets = readInstanceInts();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float scale = scales[i];
|
||||
int offset = offsets[i];
|
||||
return new UDim(scale, offset);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.UDim2:
|
||||
float[] scalesX = readInstanceFloats(), scalesY = readInstanceFloats();
|
||||
int[] offsetsX = readInstanceInts(), offsetsY = readInstanceInts();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float scaleX = scalesX[i], scaleY = scalesY[i];
|
||||
int offsetX = offsetsX[i], offsetY = offsetsY[i];
|
||||
return new UDim2(scaleX, offsetX, scaleY, offsetY);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Ray:
|
||||
loadProperties(i =>
|
||||
{
|
||||
float[] rawOrigin = reader.ReadFloats(3);
|
||||
Vector3 origin = new Vector3(rawOrigin);
|
||||
|
||||
float[] rawDirection = reader.ReadFloats(3);
|
||||
Vector3 direction = new Vector3(rawDirection);
|
||||
|
||||
return new Ray(origin, direction);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Faces:
|
||||
loadProperties(i =>
|
||||
{
|
||||
byte faces = reader.ReadByte();
|
||||
return (Faces)faces;
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Axes:
|
||||
loadProperties(i =>
|
||||
{
|
||||
byte axes = reader.ReadByte();
|
||||
return (Axes)axes;
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.BrickColor:
|
||||
int[] brickColors = readInstanceInts();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
int number = brickColors[i];
|
||||
return BrickColor.New(number);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Color3:
|
||||
float[] color3_R = readInstanceFloats(),
|
||||
color3_G = readInstanceFloats(),
|
||||
color3_B = readInstanceFloats();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float r = color3_R[i],
|
||||
g = color3_G[i],
|
||||
b = color3_B[i];
|
||||
|
||||
return new Color3(r, g, b);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Vector2:
|
||||
float[] vector2_X = readInstanceFloats(),
|
||||
vector2_Y = readInstanceFloats();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float x = vector2_X[i],
|
||||
y = vector2_Y[i];
|
||||
|
||||
return new Vector2(x, y);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Vector3:
|
||||
float[] vector3_X = readInstanceFloats(),
|
||||
vector3_Y = readInstanceFloats(),
|
||||
vector3_Z = readInstanceFloats();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float x = vector3_X[i],
|
||||
y = vector3_Y[i],
|
||||
z = vector3_Z[i];
|
||||
|
||||
return new Vector3(x, y, z);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.CFrame:
|
||||
case PropertyType.Quaternion:
|
||||
// Temporarily load the rotation matrices into their properties.
|
||||
// We'll update them to CFrames once we iterate over the position data.
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
byte orientId = reader.ReadByte();
|
||||
|
||||
if (orientId > 0)
|
||||
{
|
||||
NormalId normX = (NormalId)((orientId - 1) / 6);
|
||||
Vector3 R0 = Vector3.FromNormalId(normX);
|
||||
|
||||
NormalId normY = (NormalId)((orientId - 1) % 6);
|
||||
Vector3 R1 = Vector3.FromNormalId(normY);
|
||||
|
||||
// Compute R2 using the cross product of R0 and R1.
|
||||
Vector3 R2 = R0.Cross(R1);
|
||||
|
||||
// Generate the rotation matrix and return it.
|
||||
return new float[9]
|
||||
{
|
||||
R0.X, R0.Y, R0.Z,
|
||||
R1.X, R1.Y, R1.Z,
|
||||
R2.X, R2.Y, R2.Z,
|
||||
};
|
||||
}
|
||||
else if (Type == PropertyType.Quaternion)
|
||||
{
|
||||
float qx = reader.ReadSingle(),
|
||||
qy = reader.ReadSingle(),
|
||||
qz = reader.ReadSingle(),
|
||||
qw = reader.ReadSingle();
|
||||
|
||||
Quaternion quat = new Quaternion(qx, qy, qz, qw);
|
||||
var rotation = quat.ToCFrame();
|
||||
|
||||
return rotation.GetComponents();
|
||||
}
|
||||
else
|
||||
{
|
||||
float[] matrix = new float[9];
|
||||
|
||||
for (int m = 0; m < 9; m++)
|
||||
{
|
||||
float value = reader.ReadSingle();
|
||||
matrix[m] = value;
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
});
|
||||
|
||||
float[] cframe_X = readInstanceFloats(),
|
||||
cframe_Y = readInstanceFloats(),
|
||||
cframe_Z = readInstanceFloats();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float[] matrix = props[i].Value as float[];
|
||||
|
||||
float x = cframe_X[i],
|
||||
y = cframe_Y[i],
|
||||
z = cframe_Z[i];
|
||||
|
||||
float[] position = new float[3] { x, y, z };
|
||||
float[] components = position.Concat(matrix).ToArray();
|
||||
|
||||
return new CFrame(components);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Enum:
|
||||
uint[] enums = reader.ReadInterwovenValues(instCount, BitConverter.ToUInt32);
|
||||
loadProperties(i => enums[i]);
|
||||
break;
|
||||
case PropertyType.Ref:
|
||||
int[] instIds = reader.ReadInstanceIds(instCount);
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
int instId = instIds[i];
|
||||
return instId >= 0 ? instMap[instId] : null;
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Vector3int16:
|
||||
loadProperties(i =>
|
||||
{
|
||||
short x = reader.ReadInt16(),
|
||||
y = reader.ReadInt16(),
|
||||
z = reader.ReadInt16();
|
||||
|
||||
return new Vector3int16(x, y, z);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.NumberSequence:
|
||||
loadProperties(i =>
|
||||
{
|
||||
int keys = reader.ReadInt32();
|
||||
var keypoints = new NumberSequenceKeypoint[keys];
|
||||
|
||||
for (int key = 0; key < keys; key++)
|
||||
{
|
||||
float time = reader.ReadSingle(),
|
||||
value = reader.ReadSingle(),
|
||||
envelope = reader.ReadSingle();
|
||||
|
||||
keypoints[key] = new NumberSequenceKeypoint(time, value, envelope);
|
||||
}
|
||||
|
||||
return new NumberSequence(keypoints);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.ColorSequence:
|
||||
loadProperties(i =>
|
||||
{
|
||||
int keys = reader.ReadInt32();
|
||||
var keypoints = new ColorSequenceKeypoint[keys];
|
||||
|
||||
for (int key = 0; key < keys; key++)
|
||||
{
|
||||
float time = reader.ReadSingle(),
|
||||
R = reader.ReadSingle(),
|
||||
G = reader.ReadSingle(),
|
||||
B = reader.ReadSingle(),
|
||||
envelope = reader.ReadSingle(); // unused, but still written
|
||||
|
||||
keypoints[key] = new ColorSequenceKeypoint(time, new Color3(R, G, B));
|
||||
}
|
||||
|
||||
return new ColorSequence(keypoints);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.NumberRange:
|
||||
loadProperties(i =>
|
||||
{
|
||||
float min = reader.ReadSingle();
|
||||
float max = reader.ReadSingle();
|
||||
|
||||
return new NumberRange(min, max);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Rect:
|
||||
float[] Rect_X0 = readInstanceFloats(),
|
||||
Rect_Y0 = readInstanceFloats(),
|
||||
Rect_X1 = readInstanceFloats(),
|
||||
Rect_Y1 = readInstanceFloats();
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
float x0 = Rect_X0[i],
|
||||
y0 = Rect_Y0[i],
|
||||
x1 = Rect_X1[i],
|
||||
y1 = Rect_Y1[i];
|
||||
|
||||
return new Rect(x0, y0, x1, y1);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.PhysicalProperties:
|
||||
loadProperties(i =>
|
||||
{
|
||||
bool custom = reader.ReadBoolean();
|
||||
|
||||
if (custom)
|
||||
{
|
||||
float density = reader.ReadSingle(),
|
||||
friction = reader.ReadSingle(),
|
||||
elasticity = reader.ReadSingle(),
|
||||
frictionWeight = reader.ReadSingle(),
|
||||
elasticityWeight = reader.ReadSingle();
|
||||
|
||||
return new PhysicalProperties
|
||||
(
|
||||
density,
|
||||
friction,
|
||||
elasticity,
|
||||
frictionWeight,
|
||||
elasticityWeight
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Color3uint8:
|
||||
byte[] color3uint8_R = reader.ReadBytes(instCount),
|
||||
color3uint8_G = reader.ReadBytes(instCount),
|
||||
color3uint8_B = reader.ReadBytes(instCount);
|
||||
|
||||
loadProperties(i =>
|
||||
{
|
||||
byte r = color3uint8_R[i],
|
||||
g = color3uint8_G[i],
|
||||
b = color3uint8_B[i];
|
||||
|
||||
return Color3.fromRGB(r, g, b);
|
||||
});
|
||||
|
||||
break;
|
||||
case PropertyType.Int64:
|
||||
long[] int64s = reader.ReadInterwovenValues(instCount, (buffer, start) =>
|
||||
{
|
||||
long result = BitConverter.ToInt64(buffer, start);
|
||||
return (long)((ulong)result >> 1) ^ (-(result & 1));
|
||||
});
|
||||
|
||||
loadProperties(i => int64s[i]);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
BinaryFormat/Reader.cs
Normal file
77
BinaryFormat/Reader.cs
Normal file
@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Roblox.DataTypes;
|
||||
|
||||
namespace Roblox.BinaryFormat
|
||||
{
|
||||
public class RobloxBinaryReader : BinaryReader
|
||||
{
|
||||
public RobloxBinaryReader(Stream stream) : base(stream) { }
|
||||
|
||||
public T[] ReadInterwovenValues<T>(int count, Func<byte[], int, T> decode) where T : struct
|
||||
{
|
||||
int bufferSize = Marshal.SizeOf<T>();
|
||||
|
||||
byte[] interwoven = ReadBytes(count * bufferSize);
|
||||
T[] values = new T[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
long unwind = 0;
|
||||
|
||||
for (int weave = 0; weave < bufferSize; weave++)
|
||||
{
|
||||
long splice = interwoven[(weave * count) + i];
|
||||
int strand = (bufferSize - weave - 1) * 8;
|
||||
unwind |= (splice << strand);
|
||||
}
|
||||
|
||||
byte[] buffer = BitConverter.GetBytes(unwind);
|
||||
values[i] = decode(buffer, 0);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public int[] ReadInts(int count)
|
||||
{
|
||||
return ReadInterwovenValues(count, (buffer, start) =>
|
||||
{
|
||||
int value = BitConverter.ToInt32(buffer, start);
|
||||
return (value >> 1) ^ (-(value & 1));
|
||||
});
|
||||
}
|
||||
|
||||
public float[] ReadFloats(int count)
|
||||
{
|
||||
return ReadInterwovenValues(count, (buffer, start) =>
|
||||
{
|
||||
uint u = BitConverter.ToUInt32(buffer, start);
|
||||
uint i = (u >> 1) | (u << 31);
|
||||
|
||||
byte[] b = BitConverter.GetBytes(i);
|
||||
return BitConverter.ToSingle(b, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public int[] ReadInstanceIds(int count)
|
||||
{
|
||||
int[] values = ReadInts(count);
|
||||
|
||||
for (int i = 1; i < count; ++i)
|
||||
values[i] += values[i - 1];
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public override string ReadString()
|
||||
{
|
||||
int length = ReadInt32();
|
||||
byte[] buffer = ReadBytes(length);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
}
|
||||
}
|
2116
Core/Enums.cs
Normal file
2116
Core/Enums.cs
Normal file
File diff suppressed because it is too large
Load Diff
91
Core/Instance.cs
Normal file
91
Core/Instance.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Roblox
|
||||
{
|
||||
public class RobloxInstance
|
||||
{
|
||||
private List<RobloxInstance> _children = new List<RobloxInstance>();
|
||||
private RobloxInstance _parent;
|
||||
|
||||
public string ClassName;
|
||||
public List<RobloxProperty> Properties = new List<RobloxProperty>();
|
||||
|
||||
public bool IsAncestorOf(RobloxInstance other)
|
||||
{
|
||||
while (other != null)
|
||||
{
|
||||
if (other == this)
|
||||
return true;
|
||||
|
||||
other = other.Parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsDescendantOf(RobloxInstance other)
|
||||
{
|
||||
return other.IsAncestorOf(this);
|
||||
}
|
||||
|
||||
public RobloxInstance Parent
|
||||
{
|
||||
get { return _parent; }
|
||||
set
|
||||
{
|
||||
if (IsAncestorOf(value))
|
||||
throw new Exception("Parent would result in circular reference.");
|
||||
|
||||
if (Parent == this)
|
||||
throw new Exception("Attempt to set parent to self");
|
||||
|
||||
if (_parent != null)
|
||||
_parent._children.Remove(this);
|
||||
|
||||
value._children.Add(this);
|
||||
_parent = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlyCollection<RobloxInstance> Children
|
||||
{
|
||||
get { return _children.AsReadOnly(); }
|
||||
}
|
||||
|
||||
public object ReadProperty(string propertyName)
|
||||
{
|
||||
RobloxProperty property = Properties
|
||||
.Where((prop) => prop.Name == propertyName)
|
||||
.First();
|
||||
|
||||
return property.Value;
|
||||
}
|
||||
|
||||
public bool TryReadProperty<T>(string propertyName, out T value)
|
||||
{
|
||||
try
|
||||
{
|
||||
object result = ReadProperty(propertyName);
|
||||
value = (T)result;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
value = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var name = "";
|
||||
TryReadProperty("Name", out name);
|
||||
|
||||
return '[' + ClassName + ']' + name;
|
||||
}
|
||||
}
|
||||
}
|
62
Core/Property.cs
Normal file
62
Core/Property.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roblox
|
||||
{
|
||||
public enum PropertyType
|
||||
{
|
||||
Unknown,
|
||||
String,
|
||||
Bool,
|
||||
Int,
|
||||
Float,
|
||||
Double,
|
||||
UDim,
|
||||
UDim2,
|
||||
Ray,
|
||||
Faces,
|
||||
Axes,
|
||||
BrickColor,
|
||||
Color3,
|
||||
Vector2,
|
||||
Vector3,
|
||||
Vector2int16,
|
||||
CFrame,
|
||||
Quaternion,
|
||||
Enum,
|
||||
Ref,
|
||||
Vector3int16,
|
||||
NumberSequence,
|
||||
ColorSequence,
|
||||
NumberRange,
|
||||
Rect,
|
||||
PhysicalProperties,
|
||||
Color3uint8,
|
||||
Int64
|
||||
}
|
||||
|
||||
public class RobloxProperty
|
||||
{
|
||||
public string Name;
|
||||
public PropertyType Type;
|
||||
public object Value;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
Type PropertyType = typeof(PropertyType);
|
||||
|
||||
string typeName = Enum.GetName(PropertyType, Type);
|
||||
string valueLabel;
|
||||
|
||||
if (Value != null)
|
||||
valueLabel = Value.ToString();
|
||||
else
|
||||
valueLabel = "?";
|
||||
|
||||
return string.Join(" ", typeName, Name, '=', valueLabel);
|
||||
}
|
||||
}
|
||||
}
|
13
Core/RobloxFile.cs
Normal file
13
Core/RobloxFile.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roblox
|
||||
{
|
||||
public class RobloxFile
|
||||
{
|
||||
public List<RobloxInstance> Trunk { get; private set; }
|
||||
}
|
||||
}
|
13
DataTypes/Axes.cs
Normal file
13
DataTypes/Axes.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using Roblox.Enums;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
[Flags]
|
||||
public enum Axes
|
||||
{
|
||||
X = 0 << Axis.X,
|
||||
Y = 0 << Axis.Y,
|
||||
Z = 0 << Axis.Z,
|
||||
}
|
||||
}
|
118
DataTypes/BrickColor.cs
Normal file
118
DataTypes/BrickColor.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Roblox.DataTypes.Utility;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public class BrickColor
|
||||
{
|
||||
public readonly int Number;
|
||||
public readonly string Name;
|
||||
public readonly Color3 Color;
|
||||
|
||||
public float R => Color.R;
|
||||
public float G => Color.G;
|
||||
public float B => Color.B;
|
||||
|
||||
public override string ToString() => Name;
|
||||
|
||||
private static List<BrickColor> ByPalette;
|
||||
private static Dictionary<int, BrickColor> ByNumber;
|
||||
private static Dictionary<string, BrickColor> ByName;
|
||||
|
||||
private static Random RNG = new Random();
|
||||
|
||||
private const string DefaultName = "Medium stone grey";
|
||||
private const int DefaultNumber = 194;
|
||||
|
||||
internal BrickColor(int number, int rgb, string name)
|
||||
{
|
||||
int r = (rgb / 65536) % 256;
|
||||
int g = (rgb / 256) % 256;
|
||||
int b = rgb % 256;
|
||||
|
||||
Name = name;
|
||||
Number = number;
|
||||
|
||||
Color = Color3.fromRGB(r, g, b);
|
||||
}
|
||||
|
||||
static BrickColor()
|
||||
{
|
||||
ByName = BrickColors.ColorMap.ToDictionary(brickColor => brickColor.Name);
|
||||
ByNumber = BrickColors.ColorMap.ToDictionary(brickColor => brickColor.Number);
|
||||
ByPalette = BrickColors.PaletteMap.Select(number => ByNumber[number]).ToList();
|
||||
}
|
||||
|
||||
public static BrickColor New(string name)
|
||||
{
|
||||
if (!ByName.ContainsKey(name))
|
||||
name = DefaultName;
|
||||
|
||||
return ByName[name];
|
||||
}
|
||||
|
||||
public static BrickColor New(int number)
|
||||
{
|
||||
if (!ByNumber.ContainsKey(number))
|
||||
number = DefaultNumber;
|
||||
|
||||
return ByNumber[number];
|
||||
}
|
||||
|
||||
public static BrickColor New(Color3 color)
|
||||
{
|
||||
return New(color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static BrickColor New(float r = 0, float g = 0, float b = 0)
|
||||
{
|
||||
BrickColor bestMatch = New(-1);
|
||||
float closest = float.MaxValue;
|
||||
|
||||
foreach (BrickColor brickColor in BrickColors.ColorMap)
|
||||
{
|
||||
float dist = Math.Abs(brickColor.R - r)
|
||||
+ Math.Abs(brickColor.G - g)
|
||||
+ Math.Abs(brickColor.B - b);
|
||||
|
||||
if (dist < closest)
|
||||
{
|
||||
// Return this BrickColor if its an exact match.
|
||||
if (dist == 0.0f)
|
||||
return brickColor;
|
||||
|
||||
bestMatch = brickColor;
|
||||
closest = dist;
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
public static BrickColor Random()
|
||||
{
|
||||
int index = RNG.Next(ByPalette.Count);
|
||||
return ByPalette[index];
|
||||
}
|
||||
|
||||
public static BrickColor Palette(int index)
|
||||
{
|
||||
if (index < 0 || index >= ByPalette.Count)
|
||||
throw new Exception("Palette index was out of range.");
|
||||
|
||||
return ByPalette[index];
|
||||
}
|
||||
|
||||
public static BrickColor White() => New("White");
|
||||
public static BrickColor Gray() => New("Medium stone grey");
|
||||
public static BrickColor DarkGray() => New("Dark stone grey");
|
||||
public static BrickColor Black() => New("Black");
|
||||
public static BrickColor Red() => New("Bright red");
|
||||
public static BrickColor Yellow() => New("Bright yellow");
|
||||
public static BrickColor Green() => New("Dark green");
|
||||
public static BrickColor Blue() => New("Bright blue");
|
||||
}
|
||||
}
|
331
DataTypes/CFrame.cs
Normal file
331
DataTypes/CFrame.cs
Normal file
@ -0,0 +1,331 @@
|
||||
using System;
|
||||
using Roblox.DataTypes.Utility;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public class CFrame
|
||||
{
|
||||
private float m11 = 1, m12 = 0, m13 = 0, m14 = 0;
|
||||
private float m21 = 0, m22 = 1, m23 = 0, m24 = 0;
|
||||
private float m31 = 0, m32 = 0, m33 = 1, m34 = 0;
|
||||
private const float m41 = 0, m42 = 0, m43 = 0, m44 = 1;
|
||||
|
||||
public float X => m14;
|
||||
public float Y => m24;
|
||||
public float Z => m34;
|
||||
|
||||
public Vector3 Position => new Vector3(X, Y, Z);
|
||||
|
||||
public Vector3 LookVector => new Vector3(-m13, -m23, -m33);
|
||||
public Vector3 RightVector => new Vector3( m11, m21, m31);
|
||||
public Vector3 UpVector => new Vector3( m12, m22, m32);
|
||||
|
||||
public CFrame(Vector3 pos)
|
||||
{
|
||||
m14 = pos.X;
|
||||
m24 = pos.Y;
|
||||
m34 = pos.Z;
|
||||
}
|
||||
|
||||
public CFrame(Vector3 eye, Vector3 look)
|
||||
{
|
||||
Vector3 zAxis = (eye - look).Unit;
|
||||
Vector3 xAxis = Vector3.Up.Cross(zAxis);
|
||||
Vector3 yAxis = zAxis.Cross(xAxis);
|
||||
|
||||
if (xAxis.Magnitude == 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
m11 = xAxis.X; m12 = yAxis.X; m13 = zAxis.X; m14 = eye.X;
|
||||
m21 = xAxis.Y; m22 = yAxis.Y; m23 = zAxis.Y; m24 = eye.Y;
|
||||
m31 = xAxis.Z; m32 = yAxis.Z; m33 = zAxis.Z; m34 = eye.Z;
|
||||
}
|
||||
|
||||
public CFrame(float nx = 0, float ny = 0, float nz = 0)
|
||||
{
|
||||
m14 = nx;
|
||||
m24 = ny;
|
||||
m34 = nz;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
m14 = nx;
|
||||
m24 = ny;
|
||||
m34 = nz;
|
||||
|
||||
m11 = 1 - 2 * jj - 2 * kk;
|
||||
m12 = 2 * (i * j - k * w);
|
||||
m13 = 2 * (i * k + j * w);
|
||||
|
||||
m21 = 2 * (i * j + k * w);
|
||||
m22 = 1 - 2 * ii - 2 * kk;
|
||||
m23 = 2 * (j * k - i * w);
|
||||
|
||||
m31 = 2 * (i * k - j * w);
|
||||
m32 = 2 * (j * k + i * w);
|
||||
m33 = 1 - 2 * ii - 2 * jj;
|
||||
}
|
||||
|
||||
public CFrame(float n14, float n24, float n34, float n11, float n12, float n13, float n21, float n22, float n23, float n31, float n32, float n33)
|
||||
{
|
||||
m14 = n14; m24 = n24; m34 = n34;
|
||||
m11 = n11; m12 = n12; m13 = n13;
|
||||
m21 = n21; m22 = n22; m23 = n23;
|
||||
m31 = n31; m32 = n32; m33 = n33;
|
||||
}
|
||||
|
||||
public CFrame(params float[] comp)
|
||||
{
|
||||
if (comp.Length < 12)
|
||||
throw new Exception("There should be 12 floats provided to construct CFrame with an array of floats");
|
||||
|
||||
m14 = comp[0]; m24 = comp[1]; m34 = comp[2];
|
||||
m11 = comp[3]; m12 = comp[4]; m13 = comp[5];
|
||||
m21 = comp[6]; m22 = comp[7]; m23 = comp[8];
|
||||
m31 = comp[9]; m32 = comp[10]; m33 = comp[11];
|
||||
}
|
||||
|
||||
public static CFrame operator +(CFrame a, Vector3 b)
|
||||
{
|
||||
float[] ac = a.GetComponents();
|
||||
|
||||
float x = ac[0], y = ac[1], z = ac[2],
|
||||
m11 = ac[3], m12 = ac[4], m13 = ac[5],
|
||||
m21 = ac[6], m22 = ac[7], m23 = ac[8],
|
||||
m31 = ac[9], m32 = ac[10], m33 = ac[11];
|
||||
|
||||
return new CFrame(x + b.X, y + b.Y, z + b.Z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
|
||||
}
|
||||
|
||||
public static CFrame operator -(CFrame a, Vector3 b)
|
||||
{
|
||||
float[] ac = a.GetComponents();
|
||||
|
||||
float x = ac[0], y = ac[1], z = ac[2],
|
||||
m11 = ac[3], m12 = ac[4], m13 = ac[5],
|
||||
m21 = ac[6], m22 = ac[7], m23 = ac[8],
|
||||
m31 = ac[9], m32 = ac[10], m33 = ac[11];
|
||||
|
||||
return new CFrame(x - b.X, y - b.Y, z - b.Z, m11, m12, m13, m21, m22, m23, m31, m32, m33);
|
||||
}
|
||||
|
||||
public static Vector3 operator *(CFrame a, Vector3 b)
|
||||
{
|
||||
float[] ac = a.GetComponents();
|
||||
float x = ac[0], y = ac[1], z = ac[2],
|
||||
m11 = ac[3], m12 = ac[4], m13 = ac[5],
|
||||
m21 = ac[6], m22 = ac[7], m23 = ac[8],
|
||||
m31 = ac[9], m32 = ac[10], m33 = ac[11];
|
||||
|
||||
Vector3 right = new Vector3(m11, m21, m31);
|
||||
Vector3 up = new Vector3(m12, m22, m32);
|
||||
Vector3 back = new Vector3(m13, m23, m33);
|
||||
return a.Position + b.X * right + b.Y * up + b.Z * back;
|
||||
}
|
||||
|
||||
public static CFrame operator *(CFrame a, CFrame b)
|
||||
{
|
||||
float[] ac = a.GetComponents();
|
||||
float[] bc = b.GetComponents();
|
||||
|
||||
float a14 = ac[0], a24 = ac[1], a34 = ac[2],
|
||||
a11 = ac[3], a12 = ac[4], a13 = ac[5],
|
||||
a21 = ac[6], a22 = ac[7], a23 = ac[8],
|
||||
a31 = ac[9], a32 = ac[10], a33 = ac[11];
|
||||
|
||||
float b14 = bc[0], b24 = bc[1], b34 = bc[2],
|
||||
b11 = bc[3], b12 = bc[4], b13 = bc[5],
|
||||
b21 = bc[6], b22 = bc[7], b23 = bc[8],
|
||||
b31 = bc[9], b32 = bc[10], b33 = bc[11];
|
||||
|
||||
float n11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * m41;
|
||||
float n12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * m42;
|
||||
float n13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * m43;
|
||||
float n14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * m44;
|
||||
|
||||
float n21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * m41;
|
||||
float n22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * m42;
|
||||
float n23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * m43;
|
||||
float n24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * m44;
|
||||
|
||||
float n31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * m41;
|
||||
float n32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * m42;
|
||||
float n33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * m43;
|
||||
float n34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * m44;
|
||||
|
||||
float n41 = 0 * b11 + m42 * b21 + m43 * b31 + m44 * m41;
|
||||
float n42 = 0 * b12 + m42 * b22 + m43 * b32 + m44 * m42;
|
||||
float n43 = 0 * b13 + m42 * b23 + m43 * b33 + m44 * m43;
|
||||
float n44 = 0 * b14 + m42 * b24 + m43 * b34 + m44 * m44;
|
||||
|
||||
return new CFrame(n14, n24, n34, n11, n12, n13, n21, n22, n23, n31, n32, n33);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", GetComponents());
|
||||
}
|
||||
|
||||
private static Vector3 VectorAxisAngle(Vector3 vec, Vector3 axis, float theta)
|
||||
{
|
||||
Vector3 unit = vec.Unit;
|
||||
|
||||
float cosAng = (float)Math.Cos(theta);
|
||||
float sinAng = (float)Math.Sin(theta);
|
||||
|
||||
return axis * cosAng + axis.Dot(unit) * unit *
|
||||
(1 - cosAng) + unit.Cross(axis) * sinAng;
|
||||
}
|
||||
|
||||
public CFrame Inverse()
|
||||
{
|
||||
float[] ac = GetComponents();
|
||||
|
||||
float a14 = ac[0], a24 = ac[1], a34 = ac[2],
|
||||
a11 = ac[3], a12 = ac[4], a13 = ac[5],
|
||||
a21 = ac[6], a22 = ac[7], a23 = ac[8],
|
||||
a31 = ac[9], a32 = ac[10], a33 = ac[11];
|
||||
|
||||
float det = ( a11 * a22 * a33 * m44 + a11 * a23 * a34 * m42 + a11 * a24 * a32 * m43
|
||||
+ a12 * a21 * a34 * m43 + a12 * a23 * a31 * m44 + a12 * a24 * a33 * m41
|
||||
+ a13 * a21 * a32 * m44 + a13 * a22 * a34 * m41 + a13 * a24 * a31 * m42
|
||||
+ a14 * a21 * a33 * m42 + a14 * a22 * a31 * m43 + a14 * a23 * a32 * m41
|
||||
- a11 * a22 * a34 * m43 - a11 * a23 * a32 * m44 - a11 * a24 * a33 * m42
|
||||
- a12 * a21 * a33 * m44 - a12 * a23 * a34 * m41 - a12 * a24 * a31 * m43
|
||||
- a13 * a21 * a34 * m42 - a13 * a22 * a31 * m44 - a13 * a24 * a32 * m41
|
||||
- a14 * a21 * a32 * m43 - a14 * a22 * a33 * m41 - a14 * a23 * a31 * m42 );
|
||||
|
||||
if (det == 0)
|
||||
return this;
|
||||
|
||||
float b11 = (a22 * a33 * m44 + a23 * a34 * m42 + a24 * a32 * m43 - a22 * a34 * m43 - a23 * a32 * m44 - a24 * a33 * m42) / det;
|
||||
float b12 = (a12 * a34 * m43 + a13 * a32 * m44 + a14 * a33 * m42 - a12 * a33 * m44 - a13 * a34 * m42 - a14 * a32 * m43) / det;
|
||||
float b13 = (a12 * a23 * m44 + a13 * a24 * m42 + a14 * a22 * m43 - a12 * a24 * m43 - a13 * a22 * m44 - a14 * a23 * m42) / det;
|
||||
float b14 = (a12 * a24 * a33 + a13 * a22 * a34 + a14 * a23 * a32 - a12 * a23 * a34 - a13 * a24 * a32 - a14 * a22 * a33) / det;
|
||||
|
||||
float b21 = (a21 * a34 * m43 + a23 * a31 * m44 + a24 * a33 * m41 - a21 * a33 * m44 - a23 * a34 * m41 - a24 * a31 * m43) / det;
|
||||
float b22 = (a11 * a33 * m44 + a13 * a34 * m41 + a14 * a31 * m43 - a11 * a34 * m43 - a13 * a31 * m44 - a14 * a33 * m41) / det;
|
||||
float b23 = (a11 * a24 * m43 + a13 * a21 * m44 + a14 * a23 * m41 - a11 * a23 * m44 - a13 * a24 * m41 - a14 * a21 * m43) / det;
|
||||
float b24 = (a11 * a23 * a34 + a13 * a24 * a31 + a14 * a21 * a33 - a11 * a24 * a33 - a13 * a21 * a34 - a14 * a23 * a31) / det;
|
||||
|
||||
float b31 = (a21 * a32 * m44 + a22 * a34 * m41 + a24 * a31 * m42 - a21 * a34 * m42 - a22 * a31 * m44 - a24 * a32 * m41) / det;
|
||||
float b32 = (a11 * a34 * m42 + a12 * a31 * m44 + a14 * a32 * m41 - a11 * a32 * m44 - a12 * a34 * m41 - a14 * a31 * m42) / det;
|
||||
float b33 = (a11 * a22 * m44 + a12 * a24 * m41 + a14 * a21 * m42 - a11 * a24 * m42 - a12 * a21 * m44 - a14 * a22 * m41) / det;
|
||||
float b34 = (a11 * a24 * a32 + a12 * a21 * a34 + a14 * a22 * a31 - a11 * a22 * a34 - a12 * a24 * a31 - a14 * a21 * a32) / det;
|
||||
|
||||
float b41 = (a21 * a33 * m42 + a22 * a31 * m43 + a23 * a32 * m41 - a21 * a32 * m43 - a22 * a33 * m41 - a23 * a31 * m42) / det;
|
||||
float b42 = (a11 * a32 * m43 + a12 * a33 * m41 + a13 * a31 * m42 - a11 * a33 * m42 - a12 * a31 * m43 - a13 * a32 * m41) / det;
|
||||
float b43 = (a11 * a23 * m42 + a12 * a21 * m43 + a13 * a22 * m41 - a11 * a22 * m43 - a12 * a23 * m41 - a13 * a21 * m42) / det;
|
||||
float b44 = (a11 * a22 * a33 + a12 * a23 * a31 + a13 * a21 * a32 - a11 * a23 * a32 - a12 * a21 * a33 - a13 * a22 * a31) / det;
|
||||
|
||||
return new CFrame(b14, b24, b34, b11, b12, b13, b21, b22, b23, b31, b32, b33);
|
||||
}
|
||||
|
||||
public static CFrame FromAxisAngle(Vector3 axis, float theta)
|
||||
{
|
||||
Vector3 r = VectorAxisAngle(axis, Vector3.Right, theta);
|
||||
Vector3 u = VectorAxisAngle(axis, Vector3.Up, theta);
|
||||
Vector3 b = VectorAxisAngle(axis, Vector3.Back, 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 Angles(float x, float y, float z)
|
||||
{
|
||||
CFrame cfx = FromAxisAngle(Vector3.Right, x);
|
||||
CFrame cfy = FromAxisAngle(Vector3.Up, y);
|
||||
CFrame cfz = FromAxisAngle(Vector3.Back, z);
|
||||
|
||||
return cfx * cfy * cfz;
|
||||
}
|
||||
|
||||
public static CFrame FromEulerAnglesXYZ(float x, float y, float z)
|
||||
{
|
||||
return Angles(x, y, z);
|
||||
}
|
||||
|
||||
public CFrame Lerp(CFrame other, float t)
|
||||
{
|
||||
if (t == 0.0f)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else if (t == 1.0f)
|
||||
{
|
||||
return other;
|
||||
}
|
||||
else
|
||||
{
|
||||
Quaternion q1 = new Quaternion(this);
|
||||
Quaternion q2 = new Quaternion(other);
|
||||
|
||||
CFrame rot = q1.Slerp(q2, t).ToCFrame();
|
||||
Vector3 pos = Position.Lerp(other.Position, t);
|
||||
|
||||
return new CFrame(pos) * rot;
|
||||
}
|
||||
}
|
||||
|
||||
public CFrame ToWorldSpace(CFrame cf2)
|
||||
{
|
||||
return this * cf2;
|
||||
}
|
||||
|
||||
public CFrame ToObjectSpace(CFrame other)
|
||||
{
|
||||
return Inverse() * other;
|
||||
}
|
||||
|
||||
public Vector3 PointToWorldSpace(Vector3 v)
|
||||
{
|
||||
return this * v;
|
||||
}
|
||||
|
||||
public Vector3 PointToObjectSpace(Vector3 v)
|
||||
{
|
||||
return Inverse() * v;
|
||||
}
|
||||
|
||||
public Vector3 VectorToWorldSpace(Vector3 v)
|
||||
{
|
||||
return (this - Position) * v;
|
||||
}
|
||||
|
||||
public Vector3 VectorToObjectSpace(Vector3 v)
|
||||
{
|
||||
return (this - Position).Inverse() * v;
|
||||
}
|
||||
|
||||
public float[] GetComponents()
|
||||
{
|
||||
return new float[] { m14, m24, m34, m11, m12, m13, m21, m22, m23, m31, m32, m33 };
|
||||
}
|
||||
|
||||
public float[] toEulerAnglesXYZ()
|
||||
{
|
||||
float x = (float)Math.Atan2(-m23, m33);
|
||||
float y = (float)Math.Asin(m13);
|
||||
float z = (float)Math.Atan2(-m12, m11);
|
||||
|
||||
return new float[] { x, y, z };
|
||||
}
|
||||
}
|
||||
}
|
91
DataTypes/Color3.cs
Normal file
91
DataTypes/Color3.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Color3
|
||||
{
|
||||
public readonly float R, G, B;
|
||||
|
||||
public Color3(float r = 0, float g = 0, float b = 0)
|
||||
{
|
||||
R = r;
|
||||
G = g;
|
||||
B = b;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", R, G, B);
|
||||
}
|
||||
|
||||
public static Color3 fromRGB(int r = 0, int g = 0, int b = 0)
|
||||
{
|
||||
return new Color3(r / 255f, g / 255f, b / 255f);
|
||||
}
|
||||
|
||||
public static Color3 fromHSV(float h = 0, float s = 0, float v = 0)
|
||||
{
|
||||
int i = (int)Math.Min(5, Math.Floor(6.0 * h));
|
||||
float f = 6.0f * h - i;
|
||||
|
||||
float m = v * (1.0f - (s));
|
||||
float n = v * (1.0f - (s * f));
|
||||
float k = v * (1.0f - (s * (1 - f)));
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return new Color3(v, k, m);
|
||||
case 1:
|
||||
return new Color3(n, v, m);
|
||||
case 2:
|
||||
return new Color3(m, v, k);
|
||||
case 3:
|
||||
return new Color3(m, n, v);
|
||||
case 4:
|
||||
return new Color3(k, m, v);
|
||||
case 5:
|
||||
return new Color3(v, m, n);
|
||||
default:
|
||||
return new Color3();
|
||||
}
|
||||
}
|
||||
|
||||
public static float[] toHSV(Color3 color)
|
||||
{
|
||||
float val = Math.Max(Math.Max(color.R, color.G), color.B);
|
||||
|
||||
if (Math.Abs(val) < 0.001f)
|
||||
return new float[3] { 0, 0, 0 };
|
||||
|
||||
float hue = Math.Min(Math.Min(color.R, color.G), color.B);
|
||||
float sat = (val - hue) / val;
|
||||
|
||||
if (Math.Abs(sat) >= 0.001f)
|
||||
{
|
||||
Vector3 rgbN = val - new Vector3(color.R, color.G, color.B);
|
||||
rgbN /= (val - hue);
|
||||
|
||||
if (color.R == val)
|
||||
hue = (color.G == hue) ? 5.0f + rgbN.Z : 1.0f - rgbN.Y;
|
||||
else if (color.G == val)
|
||||
hue = (color.B == hue) ? 1.0f + rgbN.X : 3.0f - rgbN.Z;
|
||||
else
|
||||
hue = (color.R == hue) ? 3.0f + rgbN.Y : 5.0f - rgbN.Z;
|
||||
|
||||
hue /= 6.0f;
|
||||
}
|
||||
|
||||
return new float[3] { hue, sat, val };
|
||||
}
|
||||
|
||||
public Color3 Lerp(Color3 other, float alpha)
|
||||
{
|
||||
float r = (R + (other.R - R) * alpha);
|
||||
float g = (G + (other.G - G) * alpha);
|
||||
float b = (B + (other.B - B) * alpha);
|
||||
|
||||
return new Color3(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
52
DataTypes/ColorSequence.cs
Normal file
52
DataTypes/ColorSequence.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct ColorSequence
|
||||
{
|
||||
public readonly ColorSequenceKeypoint[] Keypoints;
|
||||
|
||||
public ColorSequence(Color3 c)
|
||||
{
|
||||
ColorSequenceKeypoint a = new ColorSequenceKeypoint(0, c);
|
||||
ColorSequenceKeypoint b = new ColorSequenceKeypoint(1, c);
|
||||
|
||||
Keypoints = new ColorSequenceKeypoint[2] { a, b };
|
||||
}
|
||||
|
||||
public ColorSequence(Color3 c0, Color3 c1)
|
||||
{
|
||||
ColorSequenceKeypoint a = new ColorSequenceKeypoint(0, c0);
|
||||
ColorSequenceKeypoint b = new ColorSequenceKeypoint(1, c1);
|
||||
|
||||
Keypoints = new ColorSequenceKeypoint[2] { a, b };
|
||||
}
|
||||
|
||||
public ColorSequence(ColorSequenceKeypoint[] keypoints)
|
||||
{
|
||||
int len = keypoints.Length;
|
||||
|
||||
if (len < 2)
|
||||
throw new Exception("ColorSequence: requires at least 2 keypoints");
|
||||
else if (len > 20)
|
||||
throw new Exception("ColorSequence: table is too long.");
|
||||
|
||||
for (int i = 1; i < len; i++)
|
||||
if (keypoints[i-1].Time > keypoints[i].Time)
|
||||
throw new Exception("ColorSequence: all keypoints must be ordered by time");
|
||||
|
||||
if (keypoints[0].Time < 0)
|
||||
throw new Exception("ColorSequence must start at time=0.0");
|
||||
|
||||
if (keypoints[len-1].Time > 1)
|
||||
throw new Exception("ColorSequence must end at time=1.0");
|
||||
|
||||
Keypoints = keypoints;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(" ", Keypoints);
|
||||
}
|
||||
}
|
||||
}
|
19
DataTypes/ColorSequenceKeypoint.cs
Normal file
19
DataTypes/ColorSequenceKeypoint.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct ColorSequenceKeypoint
|
||||
{
|
||||
public readonly float Time;
|
||||
public readonly Color3 Color;
|
||||
|
||||
public ColorSequenceKeypoint(float time, Color3 color)
|
||||
{
|
||||
Time = time;
|
||||
Color = color;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(" ", Time, Color.R, Color.G, Color.B, 0);
|
||||
}
|
||||
}
|
||||
}
|
16
DataTypes/Faces.cs
Normal file
16
DataTypes/Faces.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Roblox.Enums;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
[Flags]
|
||||
public enum Faces
|
||||
{
|
||||
Right = 0 << NormalId.Right,
|
||||
Top = 0 << NormalId.Top,
|
||||
Back = 0 << NormalId.Back,
|
||||
Left = 0 << NormalId.Left,
|
||||
Bottom = 0 << NormalId.Bottom,
|
||||
Front = 0 << NormalId.Front,
|
||||
}
|
||||
}
|
24
DataTypes/NumberRange.cs
Normal file
24
DataTypes/NumberRange.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct NumberRange
|
||||
{
|
||||
public readonly float Min;
|
||||
public readonly float Max;
|
||||
|
||||
public NumberRange(float min, float max)
|
||||
{
|
||||
if (max - min < 0)
|
||||
throw new Exception("NumberRange: invalid range");
|
||||
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(" ", Min, Max);
|
||||
}
|
||||
}
|
||||
}
|
52
DataTypes/NumberSequence.cs
Normal file
52
DataTypes/NumberSequence.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct NumberSequence
|
||||
{
|
||||
public readonly NumberSequenceKeypoint[] Keypoints;
|
||||
|
||||
public NumberSequence(float n)
|
||||
{
|
||||
NumberSequenceKeypoint a = new NumberSequenceKeypoint(0, n);
|
||||
NumberSequenceKeypoint b = new NumberSequenceKeypoint(1, n);
|
||||
|
||||
Keypoints = new NumberSequenceKeypoint[2] { a, b };
|
||||
}
|
||||
|
||||
public NumberSequence(float n0, float n1)
|
||||
{
|
||||
NumberSequenceKeypoint a = new NumberSequenceKeypoint(0, n0);
|
||||
NumberSequenceKeypoint b = new NumberSequenceKeypoint(1, n1);
|
||||
|
||||
Keypoints = new NumberSequenceKeypoint[2] { a, b };
|
||||
}
|
||||
|
||||
public NumberSequence(NumberSequenceKeypoint[] keypoints)
|
||||
{
|
||||
int len = keypoints.Length;
|
||||
|
||||
if (len < 2)
|
||||
throw new Exception("NumberSequence: requires at least 2 keypoints");
|
||||
else if (len > 20)
|
||||
throw new Exception("NumberSequence: table is too long.");
|
||||
|
||||
for (int i = 1; i < len; i++)
|
||||
if (keypoints[i - 1].Time > keypoints[i].Time)
|
||||
throw new Exception("NumberSequence: all keypoints must be ordered by time");
|
||||
|
||||
if (keypoints[0].Time < 0)
|
||||
throw new Exception("NumberSequence must start at time=0.0");
|
||||
|
||||
if (keypoints[len - 1].Time > 1)
|
||||
throw new Exception("NumberSequence must end at time=1.0");
|
||||
|
||||
Keypoints = keypoints;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(" ", Keypoints);
|
||||
}
|
||||
}
|
||||
}
|
21
DataTypes/NumberSequenceKeypoint.cs
Normal file
21
DataTypes/NumberSequenceKeypoint.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct NumberSequenceKeypoint
|
||||
{
|
||||
public readonly float Time;
|
||||
public readonly float Value;
|
||||
public readonly float Envelope;
|
||||
|
||||
public NumberSequenceKeypoint(float time, float value, float envelope = 0)
|
||||
{
|
||||
Time = time;
|
||||
Value = value;
|
||||
Envelope = envelope;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(" ", Time, Value, Envelope);
|
||||
}
|
||||
}
|
||||
}
|
29
DataTypes/PathWaypoint.cs
Normal file
29
DataTypes/PathWaypoint.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Roblox.Enums;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct PathWaypoint
|
||||
{
|
||||
public readonly Vector3 Position;
|
||||
public readonly PathWaypointAction Action;
|
||||
|
||||
public PathWaypoint(Vector3? position)
|
||||
{
|
||||
Position = position ?? Vector3.Zero;
|
||||
Action = PathWaypointAction.Walk;
|
||||
}
|
||||
|
||||
public PathWaypoint(Vector3 position, PathWaypointAction action = PathWaypointAction.Walk)
|
||||
{
|
||||
Position = position;
|
||||
Action = action;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
Type PathWaypointAction = typeof(PathWaypointAction);
|
||||
return '{' + Position + "} " + Enum.GetName(PathWaypointAction, Action);
|
||||
}
|
||||
}
|
||||
}
|
50
DataTypes/PhysicalProperties.cs
Normal file
50
DataTypes/PhysicalProperties.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using Roblox.Enums;
|
||||
using Roblox.DataTypes.Utility;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct PhysicalProperties
|
||||
{
|
||||
public readonly float Density;
|
||||
public readonly float Friction;
|
||||
public readonly float Elasticity;
|
||||
|
||||
public float FrictionWeight;
|
||||
public float ElasticityWeight;
|
||||
|
||||
public PhysicalProperties(Material material)
|
||||
{
|
||||
Density = MaterialInfo.DensityMap[material];
|
||||
Friction = MaterialInfo.FrictionMap[material];
|
||||
Elasticity = MaterialInfo.ElasticityMap[material];
|
||||
|
||||
FrictionWeight = 1;
|
||||
ElasticityWeight = 1;
|
||||
}
|
||||
|
||||
public PhysicalProperties(float density, float friction, float elasticity)
|
||||
{
|
||||
Density = density;
|
||||
Friction = friction;
|
||||
Elasticity = elasticity;
|
||||
|
||||
FrictionWeight = 1;
|
||||
ElasticityWeight = 1;
|
||||
}
|
||||
|
||||
public PhysicalProperties(float density, float friction, float elasticity, float frictionWeight, float elasticityWeight)
|
||||
{
|
||||
Density = density;
|
||||
Friction = friction;
|
||||
Elasticity = elasticity;
|
||||
|
||||
FrictionWeight = frictionWeight;
|
||||
ElasticityWeight = elasticityWeight;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", Density, Friction, Elasticity, FrictionWeight, ElasticityWeight);
|
||||
}
|
||||
}
|
||||
}
|
47
DataTypes/Ray.cs
Normal file
47
DataTypes/Ray.cs
Normal file
@ -0,0 +1,47 @@
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Ray
|
||||
{
|
||||
public readonly Vector3 Origin;
|
||||
public readonly Vector3 Direction;
|
||||
|
||||
public Ray Unit
|
||||
{
|
||||
get
|
||||
{
|
||||
Ray unit;
|
||||
|
||||
if (Direction.Magnitude == 1.0f)
|
||||
unit = this;
|
||||
else
|
||||
unit = new Ray(Origin, Direction.Unit);
|
||||
|
||||
return unit;
|
||||
}
|
||||
}
|
||||
|
||||
public Ray(Vector3 origin, Vector3 direction)
|
||||
{
|
||||
Origin = origin;
|
||||
Direction = direction;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return '{' + Origin + "}, {" + Direction + '}';
|
||||
}
|
||||
|
||||
public Vector3 ClosestPoint(Vector3 point)
|
||||
{
|
||||
Vector3 offset = point - Origin;
|
||||
float diff = offset.Dot(Direction) / Direction.Dot(Direction);
|
||||
return Origin + (diff * Direction);
|
||||
}
|
||||
|
||||
public float Distance(Vector3 point)
|
||||
{
|
||||
Vector3 projected = ClosestPoint(point);
|
||||
return (point - projected).Magnitude;
|
||||
}
|
||||
}
|
||||
}
|
28
DataTypes/Rect.cs
Normal file
28
DataTypes/Rect.cs
Normal file
@ -0,0 +1,28 @@
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Rect
|
||||
{
|
||||
public readonly Vector2 Min;
|
||||
public readonly Vector2 Max;
|
||||
|
||||
public float Width => (Max - Min).X;
|
||||
public float Height => (Max - Min).Y;
|
||||
|
||||
public Rect(Vector2? min, Vector2? max)
|
||||
{
|
||||
Min = min ?? Vector2.Zero;
|
||||
Max = max ?? Vector2.Zero;
|
||||
}
|
||||
|
||||
public Rect(float minX, float minY, float maxX, float maxY)
|
||||
{
|
||||
Min = new Vector2(minX, minY);
|
||||
Max = new Vector2(maxX, maxY);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", Min, Max);
|
||||
}
|
||||
}
|
||||
}
|
43
DataTypes/Region3.cs
Normal file
43
DataTypes/Region3.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Region3
|
||||
{
|
||||
public readonly CFrame CFrame;
|
||||
public readonly Vector3 Size;
|
||||
|
||||
public Region3(Vector3 a, Vector3 b)
|
||||
{
|
||||
CFrame = new CFrame((a + b) / 2);
|
||||
Size = b - a;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return CFrame + "; " + Size;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
Vector3 emax = new Vector3
|
||||
(
|
||||
(float)Math.Floor(max.X) * resolution,
|
||||
(float)Math.Floor(max.Y) * resolution,
|
||||
(float)Math.Floor(max.Z) * resolution
|
||||
);
|
||||
|
||||
return new Region3(emin, emax);
|
||||
}
|
||||
}
|
||||
}
|
24
DataTypes/Region3int16.cs
Normal file
24
DataTypes/Region3int16.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Region3int16
|
||||
{
|
||||
public readonly Vector3int16 Min, Max;
|
||||
|
||||
public Region3int16(Vector3int16? min, Vector3int16? max)
|
||||
{
|
||||
Min = min ?? new Vector3int16();
|
||||
Max = max ?? new Vector3int16();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join("; ", Min, Max);
|
||||
}
|
||||
}
|
||||
}
|
29
DataTypes/UDim.cs
Normal file
29
DataTypes/UDim.cs
Normal file
@ -0,0 +1,29 @@
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct UDim
|
||||
{
|
||||
public readonly float Scale;
|
||||
public readonly int Offset;
|
||||
|
||||
public UDim(float scale = 0, int offset = 0)
|
||||
{
|
||||
Scale = scale;
|
||||
Offset = offset;
|
||||
}
|
||||
|
||||
public static UDim operator+(UDim a, UDim b)
|
||||
{
|
||||
return new UDim(a.Scale + b.Scale, a.Offset + b.Offset);
|
||||
}
|
||||
|
||||
public static UDim operator-(UDim a, UDim b)
|
||||
{
|
||||
return new UDim(a.Scale - b.Scale, a.Offset - b.Offset);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", Scale, Offset);
|
||||
}
|
||||
}
|
||||
}
|
38
DataTypes/UDim2.cs
Normal file
38
DataTypes/UDim2.cs
Normal file
@ -0,0 +1,38 @@
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct UDim2
|
||||
{
|
||||
public readonly UDim X, Y;
|
||||
|
||||
public UDim Width => X;
|
||||
public UDim Height => Y;
|
||||
|
||||
public UDim2(float scaleX, int offsetX, float scaleY, int offsetY)
|
||||
{
|
||||
X = new UDim(scaleX, offsetX);
|
||||
Y = new UDim(scaleY, offsetY);
|
||||
}
|
||||
|
||||
public UDim2(UDim x, UDim y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return '{' + X.ToString() + "},{" + Y.ToString() + '}';
|
||||
}
|
||||
|
||||
public UDim2 Lerp(UDim2 other, float alpha)
|
||||
{
|
||||
float scaleX = X.Scale + ((other.X.Scale - X.Scale) * alpha);
|
||||
int offsetX = X.Offset + (int)((other.X.Offset - X.Offset) * alpha);
|
||||
|
||||
float scaleY = Y.Scale + ((other.Y.Scale - Y.Scale) * alpha);
|
||||
int offsetY = Y.Offset + (int)((other.Y.Offset - Y.Offset) * alpha);
|
||||
|
||||
return new UDim2(scaleX, offsetX, scaleY, offsetY);
|
||||
}
|
||||
}
|
||||
}
|
251
DataTypes/Utility/BrickColors.cs
Normal file
251
DataTypes/Utility/BrickColors.cs
Normal file
@ -0,0 +1,251 @@
|
||||
using System.Collections.Generic;
|
||||
using Roblox.DataTypes;
|
||||
|
||||
namespace Roblox.DataTypes.Utility
|
||||
{
|
||||
public static class BrickColors
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents Roblox's static palette of BrickColors.
|
||||
/// Each int refers to the `Number` identifying a BrickColor.
|
||||
/// It is used by the BrickColor.palette constructor, which
|
||||
/// is in turn used by the BrickColor.random constructor.
|
||||
/// </summary>
|
||||
|
||||
public static readonly int[] PaletteMap = new int[128]
|
||||
{
|
||||
141, 301, 107, 26, 1012, 303, 1011, 304,
|
||||
28, 1018, 302, 305, 306, 307, 308, 1021,
|
||||
309, 310, 1019, 135, 102, 23, 1010, 312,
|
||||
313, 37, 1022, 1020, 1027, 311, 315, 1023,
|
||||
1031, 316, 151, 317, 318, 319, 1024, 314,
|
||||
1013, 1006, 321, 322, 104, 1008, 119, 323,
|
||||
324, 325, 320, 11, 1026, 1016, 1032, 1015,
|
||||
327, 1005, 1009, 29, 328, 1028, 208, 45,
|
||||
329, 330, 331, 1004, 21, 332, 333, 24,
|
||||
334, 226, 1029, 335, 336, 342, 343, 338,
|
||||
1007, 339, 133, 106, 340, 341, 1001, 1,
|
||||
9, 1025, 337, 344, 345, 1014, 105, 346,
|
||||
347, 348, 349, 1030, 125, 101, 350, 192,
|
||||
351, 352, 353, 354, 1002, 5, 18, 217,
|
||||
355, 356, 153, 357, 358, 359, 360, 38,
|
||||
361, 362, 199, 194, 363, 364, 365, 1003,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// This contains a list of all available BrickColors on Roblox.
|
||||
/// </summary>
|
||||
|
||||
public static IReadOnlyCollection<BrickColor> ColorMap = new List<BrickColor>()
|
||||
{
|
||||
new BrickColor( 1, 0xF2F3F3, "White"),
|
||||
new BrickColor( 2, 0xA1A5A2, "Grey"),
|
||||
new BrickColor( 3, 0xF9E999, "Light yellow"),
|
||||
new BrickColor( 5, 0xD7C59A, "Brick yellow"),
|
||||
new BrickColor( 6, 0xC2DAB8, "Light green (Mint)"),
|
||||
new BrickColor( 9, 0xE8BAC8, "Light reddish violet"),
|
||||
new BrickColor( 11, 0x80BBDB, "Pastel Blue"),
|
||||
new BrickColor( 12, 0xCB8442, "Light orange brown"),
|
||||
new BrickColor( 18, 0xCC8E69, "Nougat"),
|
||||
new BrickColor( 21, 0xC4281C, "Bright red"),
|
||||
new BrickColor( 22, 0xC470A0, "Med. reddish violet"),
|
||||
new BrickColor( 23, 0x0D69AC, "Bright blue"),
|
||||
new BrickColor( 24, 0xF5CD30, "Bright yellow"),
|
||||
new BrickColor( 25, 0x624732, "Earth orange"),
|
||||
new BrickColor( 26, 0x1B2A35, "Black"),
|
||||
new BrickColor( 27, 0x6D6E6C, "Dark grey"),
|
||||
new BrickColor( 28, 0x287F47, "Dark green"),
|
||||
new BrickColor( 29, 0xA1C48C, "Medium green"),
|
||||
new BrickColor( 36, 0xF3CF9B, "Lig. Yellowich orange"),
|
||||
new BrickColor( 37, 0x4B974B, "Bright green"),
|
||||
new BrickColor( 38, 0xA05F35, "Dark orange"),
|
||||
new BrickColor( 39, 0xC1CADE, "Light bluish violet"),
|
||||
new BrickColor( 40, 0xECECEC, "Transparent"),
|
||||
new BrickColor( 41, 0xCD544B, "Tr. Red"),
|
||||
new BrickColor( 42, 0xC1DFF0, "Tr. Lg blue"),
|
||||
new BrickColor( 43, 0x7BB6E8, "Tr. Blue"),
|
||||
new BrickColor( 44, 0xF7F18D, "Tr. Yellow"),
|
||||
new BrickColor( 45, 0xB4D2E4, "Light blue"),
|
||||
new BrickColor( 47, 0xD9856C, "Tr. Flu. Reddish orange"),
|
||||
new BrickColor( 48, 0x84B68D, "Tr. Green"),
|
||||
new BrickColor( 49, 0xF8F184, "Tr. Flu. Green"),
|
||||
new BrickColor( 50, 0xECE8DE, "Phosph. White"),
|
||||
new BrickColor( 100, 0xEEC4B6, "Light red"),
|
||||
new BrickColor( 101, 0xDA867A, "Medium red"),
|
||||
new BrickColor( 102, 0x6E99CA, "Medium blue"),
|
||||
new BrickColor( 103, 0xC7C1B7, "Light grey"),
|
||||
new BrickColor( 104, 0x6B327C, "Bright violet"),
|
||||
new BrickColor( 105, 0xE29B40, "Br. yellowish orange"),
|
||||
new BrickColor( 106, 0xDA8541, "Bright orange"),
|
||||
new BrickColor( 107, 0x008F9C, "Bright bluish green"),
|
||||
new BrickColor( 108, 0x685C43, "Earth yellow"),
|
||||
new BrickColor( 110, 0x435493, "Bright bluish violet"),
|
||||
new BrickColor( 111, 0xBFB7B1, "Tr. Brown"),
|
||||
new BrickColor( 112, 0x6874AC, "Medium bluish violet"),
|
||||
new BrickColor( 113, 0xE5ADC8, "Tr. Medi. reddish violet"),
|
||||
new BrickColor( 115, 0xC7D23C, "Med. yellowish green"),
|
||||
new BrickColor( 116, 0x55A5AF, "Med. bluish green"),
|
||||
new BrickColor( 118, 0xB7D7D5, "Light bluish green"),
|
||||
new BrickColor( 119, 0xA4BD47, "Br. yellowish green"),
|
||||
new BrickColor( 120, 0xD9E4A7, "Lig. yellowish green"),
|
||||
new BrickColor( 121, 0xE7AC58, "Med. yellowish orange"),
|
||||
new BrickColor( 123, 0xD36F4C, "Br. reddish orange"),
|
||||
new BrickColor( 124, 0x923978, "Bright reddish violet"),
|
||||
new BrickColor( 125, 0xEAB892, "Light orange"),
|
||||
new BrickColor( 126, 0xA5A5CB, "Tr. Bright bluish violet"),
|
||||
new BrickColor( 127, 0xDCBC81, "Gold"),
|
||||
new BrickColor( 128, 0xAE7A59, "Dark nougat"),
|
||||
new BrickColor( 131, 0x9CA3A8, "Silver"),
|
||||
new BrickColor( 133, 0xD5733D, "Neon orange"),
|
||||
new BrickColor( 134, 0xD8DD56, "Neon green"),
|
||||
new BrickColor( 135, 0x74869D, "Sand blue"),
|
||||
new BrickColor( 136, 0x877C90, "Sand violet"),
|
||||
new BrickColor( 137, 0xE09864, "Medium orange"),
|
||||
new BrickColor( 138, 0x958A73, "Sand yellow"),
|
||||
new BrickColor( 140, 0x203A56, "Earth blue"),
|
||||
new BrickColor( 141, 0x27462D, "Earth green"),
|
||||
new BrickColor( 143, 0xCFE2F7, "Tr. Flu. Blue"),
|
||||
new BrickColor( 145, 0x7988A1, "Sand blue metallic"),
|
||||
new BrickColor( 146, 0x958EA3, "Sand violet metallic"),
|
||||
new BrickColor( 147, 0x938767, "Sand yellow metallic"),
|
||||
new BrickColor( 148, 0x575857, "Dark grey metallic"),
|
||||
new BrickColor( 149, 0x161D32, "Black metallic"),
|
||||
new BrickColor( 150, 0xABADAC, "Light grey metallic"),
|
||||
new BrickColor( 151, 0x789082, "Sand green"),
|
||||
new BrickColor( 153, 0x957977, "Sand red"),
|
||||
new BrickColor( 154, 0x7B2E2F, "Dark red"),
|
||||
new BrickColor( 157, 0xFFF67B, "Tr. Flu. Yellow"),
|
||||
new BrickColor( 158, 0xE1A4C2, "Tr. Flu. Red"),
|
||||
new BrickColor( 168, 0x756C62, "Gun metallic"),
|
||||
new BrickColor( 176, 0x97695B, "Red flip/flop"),
|
||||
new BrickColor( 178, 0xB48455, "Yellow flip/flop"),
|
||||
new BrickColor( 179, 0x898788, "Silver flip/flop"),
|
||||
new BrickColor( 180, 0xD7A94B, "Curry"),
|
||||
new BrickColor( 190, 0xF9D62E, "Fire Yellow"),
|
||||
new BrickColor( 191, 0xE8AB2D, "Flame yellowish orange"),
|
||||
new BrickColor( 192, 0x694028, "Reddish brown"),
|
||||
new BrickColor( 193, 0xCF6024, "Flame reddish orange"),
|
||||
new BrickColor( 194, 0xA3A2A5, "Medium stone grey"),
|
||||
new BrickColor( 195, 0x4667A4, "Royal blue"),
|
||||
new BrickColor( 196, 0x23478B, "Dark Royal blue"),
|
||||
new BrickColor( 198, 0x8E4285, "Bright reddish lilac"),
|
||||
new BrickColor( 199, 0x635F62, "Dark stone grey"),
|
||||
new BrickColor( 200, 0x828A5D, "Lemon metalic"),
|
||||
new BrickColor( 208, 0xE5E4DF, "Light stone grey"),
|
||||
new BrickColor( 209, 0xB08E44, "Dark Curry"),
|
||||
new BrickColor( 210, 0x709578, "Faded green"),
|
||||
new BrickColor( 211, 0x79B5B5, "Turquoise"),
|
||||
new BrickColor( 212, 0x9FC3E9, "Light Royal blue"),
|
||||
new BrickColor( 213, 0x6C81B7, "Medium Royal blue"),
|
||||
new BrickColor( 216, 0x904C2A, "Rust"),
|
||||
new BrickColor( 217, 0x7C5C46, "Brown"),
|
||||
new BrickColor( 218, 0x96709F, "Reddish lilac"),
|
||||
new BrickColor( 219, 0x6B629B, "Lilac"),
|
||||
new BrickColor( 220, 0xA7A9CE, "Light lilac"),
|
||||
new BrickColor( 221, 0xCD6298, "Bright purple"),
|
||||
new BrickColor( 222, 0xE4ADC8, "Light purple"),
|
||||
new BrickColor( 223, 0xDC9095, "Light pink"),
|
||||
new BrickColor( 224, 0xF0D5A0, "Light brick yellow"),
|
||||
new BrickColor( 225, 0xEBB87F, "Warm yellowish orange"),
|
||||
new BrickColor( 226, 0xFDEA8D, "Cool yellow"),
|
||||
new BrickColor( 232, 0x7DBBDD, "Dove blue"),
|
||||
new BrickColor( 268, 0x342B75, "Medium lilac"),
|
||||
new BrickColor( 301, 0x506D54, "Slime green"),
|
||||
new BrickColor( 302, 0x5B5D69, "Smoky grey"),
|
||||
new BrickColor( 303, 0x0010B0, "Dark blue"),
|
||||
new BrickColor( 304, 0x2C651D, "Parsley green"),
|
||||
new BrickColor( 305, 0x527CAE, "Steel blue"),
|
||||
new BrickColor( 306, 0x335882, "Storm blue"),
|
||||
new BrickColor( 307, 0x102ADC, "Lapis"),
|
||||
new BrickColor( 308, 0x3D1585, "Dark indigo"),
|
||||
new BrickColor( 309, 0x348E40, "Sea green"),
|
||||
new BrickColor( 310, 0x5B9A4C, "Shamrock"),
|
||||
new BrickColor( 311, 0x9FA1AC, "Fossil"),
|
||||
new BrickColor( 312, 0x592259, "Mulberry"),
|
||||
new BrickColor( 313, 0x1F801D, "Forest green"),
|
||||
new BrickColor( 314, 0x9FADC0, "Cadet blue"),
|
||||
new BrickColor( 315, 0x0989CF, "Electric blue"),
|
||||
new BrickColor( 316, 0x7B007B, "Eggplant"),
|
||||
new BrickColor( 317, 0x7C9C6B, "Moss"),
|
||||
new BrickColor( 318, 0x8AAB85, "Artichoke"),
|
||||
new BrickColor( 319, 0xB9C4B1, "Sage green"),
|
||||
new BrickColor( 320, 0xCACBD1, "Ghost grey"),
|
||||
new BrickColor( 321, 0xA75E9B, "Lilac"),
|
||||
new BrickColor( 322, 0x7B2F7B, "Plum"),
|
||||
new BrickColor( 323, 0x94BE81, "Olivine"),
|
||||
new BrickColor( 324, 0xA8BD99, "Laurel green"),
|
||||
new BrickColor( 325, 0xDFDFDE, "Quill grey"),
|
||||
new BrickColor( 327, 0x970000, "Crimson"),
|
||||
new BrickColor( 328, 0xB1E5A6, "Mint"),
|
||||
new BrickColor( 329, 0x98C2DB, "Baby blue"),
|
||||
new BrickColor( 330, 0xFF98DC, "Carnation pink"),
|
||||
new BrickColor( 331, 0xFF5959, "Persimmon"),
|
||||
new BrickColor( 332, 0x750000, "Maroon"),
|
||||
new BrickColor( 333, 0xEFB838, "Gold"),
|
||||
new BrickColor( 334, 0xF8D96D, "Daisy orange"),
|
||||
new BrickColor( 335, 0xE7E7EC, "Pearl"),
|
||||
new BrickColor( 336, 0xC7D4E4, "Fog"),
|
||||
new BrickColor( 337, 0xFF9494, "Salmon"),
|
||||
new BrickColor( 338, 0xBE6862, "Terra Cotta"),
|
||||
new BrickColor( 339, 0x562424, "Cocoa"),
|
||||
new BrickColor( 340, 0xF1E7C7, "Wheat"),
|
||||
new BrickColor( 341, 0xFEF3BB, "Buttermilk"),
|
||||
new BrickColor( 342, 0xE0B2D0, "Mauve"),
|
||||
new BrickColor( 343, 0xD490BD, "Sunrise"),
|
||||
new BrickColor( 344, 0x965555, "Tawny"),
|
||||
new BrickColor( 345, 0x8F4C2A, "Rust"),
|
||||
new BrickColor( 346, 0xD3BE96, "Cashmere"),
|
||||
new BrickColor( 347, 0xE2DCBC, "Khaki"),
|
||||
new BrickColor( 348, 0xEDEAEA, "Lily white"),
|
||||
new BrickColor( 349, 0xE9DADA, "Seashell"),
|
||||
new BrickColor( 350, 0x883E3E, "Burgundy"),
|
||||
new BrickColor( 351, 0xBC9B5D, "Cork"),
|
||||
new BrickColor( 352, 0xC7AC78, "Burlap"),
|
||||
new BrickColor( 353, 0xCABFA3, "Beige"),
|
||||
new BrickColor( 354, 0xBBB3B2, "Oyster"),
|
||||
new BrickColor( 355, 0x6C584B, "Pine Cone"),
|
||||
new BrickColor( 356, 0xA0844F, "Fawn brown"),
|
||||
new BrickColor( 357, 0x958988, "Hurricane grey"),
|
||||
new BrickColor( 358, 0xABA89E, "Cloudy grey"),
|
||||
new BrickColor( 359, 0xAF9483, "Linen"),
|
||||
new BrickColor( 360, 0x966766, "Copper"),
|
||||
new BrickColor( 361, 0x564236, "Dirt brown"),
|
||||
new BrickColor( 362, 0x7E683F, "Bronze"),
|
||||
new BrickColor( 363, 0x69665C, "Flint"),
|
||||
new BrickColor( 364, 0x5A4C42, "Dark taupe"),
|
||||
new BrickColor( 365, 0x6A3909, "Burnt Sienna"),
|
||||
new BrickColor(1001, 0xF8F8F8, "Institutional white"),
|
||||
new BrickColor(1002, 0xCDCDCD, "Mid gray"),
|
||||
new BrickColor(1003, 0x111111, "Really black"),
|
||||
new BrickColor(1004, 0xFF0000, "Really red"),
|
||||
new BrickColor(1005, 0xFFB000, "Deep orange"),
|
||||
new BrickColor(1006, 0xB480FF, "Alder"),
|
||||
new BrickColor(1007, 0xA34B4B, "Dusty Rose"),
|
||||
new BrickColor(1008, 0xC1BE42, "Olive"),
|
||||
new BrickColor(1009, 0xFFFF00, "New Yeller"),
|
||||
new BrickColor(1010, 0x0000FF, "Really blue"),
|
||||
new BrickColor(1011, 0x002060, "Navy blue"),
|
||||
new BrickColor(1012, 0x2154B9, "Deep blue"),
|
||||
new BrickColor(1013, 0x04AFEC, "Cyan"),
|
||||
new BrickColor(1014, 0xAA5500, "CGA brown"),
|
||||
new BrickColor(1015, 0xAA00AA, "Magenta"),
|
||||
new BrickColor(1016, 0xFF66CC, "Pink"),
|
||||
new BrickColor(1017, 0xFFAF00, "Deep orange"),
|
||||
new BrickColor(1018, 0x12EED4, "Teal"),
|
||||
new BrickColor(1019, 0x00FFFF, "Toothpaste"),
|
||||
new BrickColor(1020, 0x00FF00, "Lime green"),
|
||||
new BrickColor(1021, 0x3A7D15, "Camo"),
|
||||
new BrickColor(1022, 0x7F8E64, "Grime"),
|
||||
new BrickColor(1023, 0x8C5B9F, "Lavender"),
|
||||
new BrickColor(1024, 0xAFDDFF, "Pastel light blue"),
|
||||
new BrickColor(1025, 0xFFC9C9, "Pastel orange"),
|
||||
new BrickColor(1026, 0xB1A7FF, "Pastel violet"),
|
||||
new BrickColor(1027, 0x9FF3E9, "Pastel blue-green"),
|
||||
new BrickColor(1028, 0xCCFFCC, "Pastel green"),
|
||||
new BrickColor(1029, 0xFFFFCC, "Pastel yellow"),
|
||||
new BrickColor(1030, 0xFFCC99, "Pastel brown"),
|
||||
new BrickColor(1031, 0x6225D1, "Royal purple"),
|
||||
new BrickColor(1032, 0xFF00BF, "Hot pink"),
|
||||
};
|
||||
}
|
||||
}
|
128
DataTypes/Utility/MaterialInfo.cs
Normal file
128
DataTypes/Utility/MaterialInfo.cs
Normal file
@ -0,0 +1,128 @@
|
||||
using System.Collections.Generic;
|
||||
using Roblox.Enums;
|
||||
|
||||
namespace Roblox.DataTypes.Utility
|
||||
{
|
||||
public static class MaterialInfo
|
||||
{
|
||||
public static IReadOnlyDictionary<Material, float> DensityMap = new Dictionary<Material, float>()
|
||||
{
|
||||
{Material.Air, 0.01f},
|
||||
{Material.Asphalt, 2.36f},
|
||||
{Material.Basalt, 2.69f},
|
||||
{Material.Brick, 1.92f},
|
||||
{Material.Cobblestone, 2.69f},
|
||||
{Material.Concrete, 2.40f},
|
||||
{Material.CorrodedMetal, 7.85f},
|
||||
{Material.CrackedLava, 2.69f},
|
||||
{Material.DiamondPlate, 7.85f},
|
||||
{Material.Fabric, 0.70f},
|
||||
{Material.Foil, 2.70f},
|
||||
{Material.Glacier, 0.92f},
|
||||
{Material.Glass, 2.40f},
|
||||
{Material.Granite, 2.69f},
|
||||
{Material.Grass, 0.90f},
|
||||
{Material.Ground, 0.90f},
|
||||
{Material.Ice, 0.92f},
|
||||
{Material.LeafyGrass, 0.90f},
|
||||
{Material.Limestone, 2.69f},
|
||||
{Material.Marble, 2.56f},
|
||||
{Material.Metal, 7.85f},
|
||||
{Material.Mud, 0.90f},
|
||||
{Material.Neon, 0.70f},
|
||||
{Material.Pavement, 2.69f},
|
||||
{Material.Pebble, 2.40f},
|
||||
{Material.Plastic, 0.70f},
|
||||
{Material.Rock, 2.69f},
|
||||
{Material.Salt, 2.16f},
|
||||
{Material.Sand, 1.60f},
|
||||
{Material.Sandstone, 2.69f},
|
||||
{Material.Slate, 2.69f},
|
||||
{Material.SmoothPlastic, 0.70f},
|
||||
{Material.Snow, 0.90f},
|
||||
{Material.Water, 1.00f},
|
||||
{Material.Wood, 0.35f},
|
||||
{Material.WoodPlanks, 0.35f},
|
||||
};
|
||||
|
||||
public static IReadOnlyDictionary<Material, float> ElasticityMap = new Dictionary<Material, float>()
|
||||
{
|
||||
{Material.Air, 0.01f},
|
||||
{Material.Asphalt, 0.20f},
|
||||
{Material.Basalt, 0.15f},
|
||||
{Material.Brick, 0.15f},
|
||||
{Material.Cobblestone, 0.17f},
|
||||
{Material.Concrete, 0.20f},
|
||||
{Material.CorrodedMetal, 0.20f},
|
||||
{Material.CrackedLava, 0.15f},
|
||||
{Material.DiamondPlate, 0.25f},
|
||||
{Material.Fabric, 0.05f},
|
||||
{Material.Foil, 0.25f},
|
||||
{Material.Glacier, 0.15f},
|
||||
{Material.Glass, 0.20f},
|
||||
{Material.Granite, 0.20f},
|
||||
{Material.Grass, 0.10f},
|
||||
{Material.Ground, 0.10f},
|
||||
{Material.Ice, 0.15f},
|
||||
{Material.LeafyGrass, 0.10f},
|
||||
{Material.Limestone, 0.15f},
|
||||
{Material.Marble, 0.17f},
|
||||
{Material.Metal, 0.25f},
|
||||
{Material.Mud, 0.07f},
|
||||
{Material.Neon, 0.20f},
|
||||
{Material.Pavement, 0.17f},
|
||||
{Material.Pebble, 0.17f},
|
||||
{Material.Plastic, 0.50f},
|
||||
{Material.Rock, 0.17f},
|
||||
{Material.Salt, 0.05f},
|
||||
{Material.Sand, 0.05f},
|
||||
{Material.Sandstone, 0.15f},
|
||||
{Material.Slate, 0.20f},
|
||||
{Material.SmoothPlastic, 0.50f},
|
||||
{Material.Snow, 0.03f},
|
||||
{Material.Water, 0.01f},
|
||||
{Material.Wood, 0.20f},
|
||||
{Material.WoodPlanks, 0.20f},
|
||||
};
|
||||
|
||||
public static IReadOnlyDictionary<Material, float> FrictionMap = new Dictionary<Material, float>()
|
||||
{
|
||||
{Material.Air, 0.01f},
|
||||
{Material.Asphalt, 0.80f},
|
||||
{Material.Basalt, 0.70f},
|
||||
{Material.Brick, 0.80f},
|
||||
{Material.Cobblestone, 0.50f},
|
||||
{Material.Concrete, 0.70f},
|
||||
{Material.CorrodedMetal, 0.70f},
|
||||
{Material.CrackedLava, 0.65f},
|
||||
{Material.DiamondPlate, 0.35f},
|
||||
{Material.Fabric, 0.35f},
|
||||
{Material.Foil, 0.40f},
|
||||
{Material.Glacier, 0.05f},
|
||||
{Material.Glass, 0.25f},
|
||||
{Material.Granite, 0.40f},
|
||||
{Material.Grass, 0.40f},
|
||||
{Material.Ground, 0.45f},
|
||||
{Material.Ice, 0.02f},
|
||||
{Material.LeafyGrass, 0.40f},
|
||||
{Material.Limestone, 0.50f},
|
||||
{Material.Marble, 0.20f},
|
||||
{Material.Metal, 0.40f},
|
||||
{Material.Mud, 0.30f},
|
||||
{Material.Neon, 0.30f},
|
||||
{Material.Pavement, 0.50f},
|
||||
{Material.Pebble, 0.40f},
|
||||
{Material.Plastic, 0.30f},
|
||||
{Material.Rock, 0.50f},
|
||||
{Material.Salt, 0.50f},
|
||||
{Material.Sand, 0.50f},
|
||||
{Material.Sandstone, 0.50f},
|
||||
{Material.Slate, 0.40f},
|
||||
{Material.SmoothPlastic, 0.20f},
|
||||
{Material.Snow, 0.30f},
|
||||
{Material.Water, 0.00f},
|
||||
{Material.Wood, 0.48f},
|
||||
{Material.WoodPlanks, 0.48f},
|
||||
};
|
||||
}
|
||||
}
|
207
DataTypes/Utility/Quaternion.cs
Normal file
207
DataTypes/Utility/Quaternion.cs
Normal file
@ -0,0 +1,207 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes.Utility
|
||||
{
|
||||
public class Quaternion
|
||||
{
|
||||
public readonly float X;
|
||||
public readonly float Y;
|
||||
public readonly float Z;
|
||||
public readonly float W;
|
||||
|
||||
public float Magnitude
|
||||
{
|
||||
get
|
||||
{
|
||||
float squared = Dot(this);
|
||||
double magnitude = Math.Sqrt(squared);
|
||||
|
||||
return (float)magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
public Quaternion(float x, float y, float z, float w)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public Quaternion(Vector3 qv, float qw)
|
||||
{
|
||||
X = qv.X;
|
||||
Y = qv.Y;
|
||||
Z = qv.Z;
|
||||
W = qw;
|
||||
}
|
||||
|
||||
public Quaternion(CFrame cf)
|
||||
{
|
||||
CFrame matrix = (cf - cf.Position);
|
||||
float[] ac = cf.GetComponents();
|
||||
|
||||
float m41 = ac[0], m42 = ac[1], m43 = ac[2],
|
||||
m11 = ac[3], m12 = ac[4], m13 = ac[5],
|
||||
m21 = ac[6], m22 = ac[7], m23 = ac[8],
|
||||
m31 = ac[9], m32 = ac[10], m33 = ac[11];
|
||||
|
||||
float trace = m11 + m22 + m33;
|
||||
|
||||
if (trace > 0)
|
||||
{
|
||||
float s = (float)Math.Sqrt(1 + trace);
|
||||
float r = 0.5f / s;
|
||||
|
||||
W = s * 0.5f;
|
||||
X = (m32 - m23) * r;
|
||||
Y = (m13 - m31) * r;
|
||||
Z = (m21 - m12) * r;
|
||||
}
|
||||
else
|
||||
{
|
||||
float big = Math.Max(Math.Max(m11, m22), m33);
|
||||
|
||||
if (big == m11)
|
||||
{
|
||||
float s = (float)Math.Sqrt(1 + m11 - m22 - m33);
|
||||
float r = 0.5f / s;
|
||||
|
||||
W = (m32 - m23) * r;
|
||||
X = 0.5f * s;
|
||||
Y = (m21 + m12) * r;
|
||||
Z = (m13 + m31) * r;
|
||||
}
|
||||
else if (big == m22)
|
||||
{
|
||||
float s = (float)Math.Sqrt(1 - m11 + m22 - m33);
|
||||
float r = 0.5f / s;
|
||||
|
||||
W = (m13 - m31) * r;
|
||||
X = (m21 + m12) * r;
|
||||
Y = 0.5f * s;
|
||||
Z = (m32 + m23) * r;
|
||||
}
|
||||
else if (big == m33)
|
||||
{
|
||||
float s = (float)Math.Sqrt(1 - m11 - m22 + m33);
|
||||
float r = 0.5f / s;
|
||||
|
||||
W = (m21 - m12) * r;
|
||||
X = (m13 + m31) * r;
|
||||
Y = (m32 + m23) * r;
|
||||
Z = 0.5f * s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float Dot(Quaternion other)
|
||||
{
|
||||
return (X * other.X) + (Y * other.Y) + (Z * other.Z) + (W * other.W);
|
||||
}
|
||||
|
||||
public Quaternion Lerp(Quaternion other, float alpha)
|
||||
{
|
||||
Quaternion result = this * (1.0f - alpha) + other * alpha;
|
||||
return result / result.Magnitude;
|
||||
}
|
||||
|
||||
public Quaternion Slerp(Quaternion other, float alpha)
|
||||
{
|
||||
float cosAng = Dot(other);
|
||||
|
||||
if (cosAng < 0)
|
||||
{
|
||||
other = -other;
|
||||
cosAng = -cosAng;
|
||||
}
|
||||
|
||||
double ang = Math.Acos(cosAng);
|
||||
|
||||
if (ang >= 0.05f)
|
||||
{
|
||||
float scale0 = (float)Math.Sin((1.0f - alpha) * ang);
|
||||
float scale1 = (float)Math.Sin(alpha * ang);
|
||||
float denom = (float)Math.Sin(ang);
|
||||
|
||||
return ((this * scale0) + (other * scale1)) / denom;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Lerp(other, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public CFrame ToCFrame()
|
||||
{
|
||||
float xc = X * 2f;
|
||||
float yc = Y * 2f;
|
||||
float zc = Z * 2f;
|
||||
|
||||
float xx = X * xc;
|
||||
float xy = X * yc;
|
||||
float xz = X * zc;
|
||||
|
||||
float wx = W * xc;
|
||||
float wy = W * yc;
|
||||
float wz = W * zc;
|
||||
|
||||
float yy = Y * yc;
|
||||
float yz = Y * zc;
|
||||
float zz = Z * zc;
|
||||
|
||||
return new CFrame
|
||||
(
|
||||
0, 0, 0,
|
||||
|
||||
1f - (yy + zz),
|
||||
xy - wz,
|
||||
xz + wy,
|
||||
|
||||
xy + wz,
|
||||
1f - (xx + zz),
|
||||
yz - wx,
|
||||
|
||||
xz - wy,
|
||||
yz + wx,
|
||||
1f - (xx + yy)
|
||||
);
|
||||
}
|
||||
|
||||
public static Quaternion operator +(Quaternion a, Quaternion b)
|
||||
{
|
||||
return new Quaternion(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
|
||||
}
|
||||
|
||||
public static Quaternion operator -(Quaternion a, Quaternion b)
|
||||
{
|
||||
return new Quaternion(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
|
||||
}
|
||||
|
||||
public static Quaternion operator *(Quaternion a, float f)
|
||||
{
|
||||
return new Quaternion(a.X * f, a.Y * f, a.Z * f, a.W * f);
|
||||
}
|
||||
|
||||
public static Quaternion operator /(Quaternion a, float f)
|
||||
{
|
||||
return new Quaternion(a.X / f, a.Y / f, a.Z / f, a.W / f);
|
||||
}
|
||||
|
||||
public static Quaternion operator -(Quaternion a)
|
||||
{
|
||||
return new Quaternion(-a.X, -a.Y, -a.Z, -a.W);
|
||||
}
|
||||
|
||||
public static Quaternion operator *(Quaternion a, Quaternion b)
|
||||
{
|
||||
Vector3 v1 = new Vector3(a.X, a.Y, a.Z);
|
||||
float s1 = a.W;
|
||||
|
||||
Vector3 v2 = new Vector3(b.X, b.Y, b.Z);
|
||||
float s2 = b.W;
|
||||
|
||||
return new Quaternion(s1 * v2 + s2 * v1 + v1.Cross(v2), s1 * s2 - v1.Dot(v2));
|
||||
}
|
||||
}
|
||||
}
|
100
DataTypes/Vector2.cs
Normal file
100
DataTypes/Vector2.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Vector2
|
||||
{
|
||||
public readonly float 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;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public Vector2(float[] coords)
|
||||
{
|
||||
X = coords.Length > 0 ? coords[0] : 0;
|
||||
Y = coords.Length > 1 ? coords[1] : 0;
|
||||
}
|
||||
|
||||
private delegate Vector2 Operator(Vector2 a, Vector2 b);
|
||||
|
||||
private static Vector2 upcastFloatOp(Vector2 vec, float num, Operator upcast)
|
||||
{
|
||||
Vector2 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);
|
||||
return upcast(numVec, vec);
|
||||
}
|
||||
|
||||
private static Operator add = new Operator((a, b) => new Vector2(a.X + b.X, a.Y + b.Y));
|
||||
private static Operator sub = new Operator((a, b) => new Vector2(a.X - b.X, a.Y - b.Y));
|
||||
private static Operator mul = new Operator((a, b) => new Vector2(a.X * b.X, a.Y * b.Y));
|
||||
private static Operator div = new Operator((a, b) => new Vector2(a.X / b.X, a.Y / b.Y));
|
||||
|
||||
public static Vector2 operator +(Vector2 a, Vector2 b) => add(a, b);
|
||||
public static Vector2 operator +(Vector2 v, float n) => upcastFloatOp(v, n, add);
|
||||
public static Vector2 operator +(float n, Vector2 v) => upcastFloatOp(n, v, add);
|
||||
|
||||
public static Vector2 operator -(Vector2 a, Vector2 b) => sub(a, b);
|
||||
public static Vector2 operator -(Vector2 v, float n) => upcastFloatOp(v, n, sub);
|
||||
public static Vector2 operator -(float n, Vector2 v) => upcastFloatOp(n, v, sub);
|
||||
|
||||
public static Vector2 operator *(Vector2 a, Vector2 b) => mul(a, b);
|
||||
public static Vector2 operator *(Vector2 v, float n) => upcastFloatOp(v, n, mul);
|
||||
public static Vector2 operator *(float n, Vector2 v) => upcastFloatOp(n, v, mul);
|
||||
|
||||
public static Vector2 operator /(Vector2 a, Vector2 b) => div(a, b);
|
||||
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 Zero => new Vector2(0, 0);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", X, Y);
|
||||
}
|
||||
|
||||
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 Vector2 Lerp(Vector2 other, float t)
|
||||
{
|
||||
return this + (other - this) * t;
|
||||
}
|
||||
}
|
||||
}
|
133
DataTypes/Vector3.cs
Normal file
133
DataTypes/Vector3.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using Roblox.Enums;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Vector3
|
||||
{
|
||||
public readonly float X, Y, Z;
|
||||
|
||||
public float Magnitude
|
||||
{
|
||||
get
|
||||
{
|
||||
float product = Dot(this);
|
||||
double magnitude = Math.Sqrt(product);
|
||||
|
||||
return (float)magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Unit
|
||||
{
|
||||
get { return this / Magnitude; }
|
||||
}
|
||||
|
||||
public Vector3(float x = 0, float y = 0, float z = 0)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public Vector3(float[] coords)
|
||||
{
|
||||
X = coords.Length > 0 ? coords[0] : 0;
|
||||
Y = coords.Length > 1 ? coords[1] : 0;
|
||||
Z = coords.Length > 2 ? coords[2] : 0;
|
||||
}
|
||||
|
||||
public static Vector3 FromAxis(Axis axis)
|
||||
{
|
||||
float[] coords = new float[3] { 0f, 0f, 0f };
|
||||
|
||||
int index = (int)axis;
|
||||
coords[index] = 1f;
|
||||
|
||||
return new Vector3(coords);
|
||||
}
|
||||
|
||||
public static Vector3 FromNormalId(NormalId normalId)
|
||||
{
|
||||
float[] coords = new float[3] { 0f, 0f, 0f };
|
||||
|
||||
int index = (int)normalId;
|
||||
coords[index % 3] = (index > 2 ? -1f : 1f);
|
||||
|
||||
return new Vector3(coords);
|
||||
}
|
||||
|
||||
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);
|
||||
return upcast(vec, numVec);
|
||||
}
|
||||
|
||||
private static Vector3 upcastFloatOp(float num, Vector3 vec, Operator upcast)
|
||||
{
|
||||
Vector3 numVec = new Vector3(num, num, num);
|
||||
return upcast(numVec, vec);
|
||||
}
|
||||
|
||||
private static Operator add = new Operator((a, b) => new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z));
|
||||
private static Operator sub = new Operator((a, b) => new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z));
|
||||
private static Operator mul = new Operator((a, b) => new Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z));
|
||||
private static Operator div = new Operator((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 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 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 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 Zero => new Vector3(0, 0, 0);
|
||||
public static Vector3 Right => new Vector3(1, 0, 0);
|
||||
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)
|
||||
{
|
||||
float dotX = X * other.X;
|
||||
float dotY = Y * other.Y;
|
||||
float dotZ = Z * other.Z;
|
||||
|
||||
return dotX + dotY + dotZ;
|
||||
}
|
||||
|
||||
public Vector3 Cross(Vector3 other)
|
||||
{
|
||||
float crossX = Y * other.Z - other.Y * Z;
|
||||
float crossY = Z * other.X - other.Z * X;
|
||||
float crossZ = X * other.Y - other.X * Y;
|
||||
|
||||
return new Vector3(crossX, crossY, crossZ);
|
||||
}
|
||||
|
||||
public Vector3 Lerp(Vector3 other, float t)
|
||||
{
|
||||
return this + (other - this) * t;
|
||||
}
|
||||
|
||||
public bool isClose(Vector3 other, float epsilon = 0.0f)
|
||||
{
|
||||
return (other - this).Magnitude <= Math.Abs(epsilon);
|
||||
}
|
||||
}
|
||||
}
|
69
DataTypes/Vector3int16.cs
Normal file
69
DataTypes/Vector3int16.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
namespace Roblox.DataTypes
|
||||
{
|
||||
public struct Vector3int16
|
||||
{
|
||||
public readonly short X, Y, Z;
|
||||
|
||||
public Vector3int16(short x = 0, short y = 0, short z = 0)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public Vector3int16(int x = 0, int y = 0, int z = 0)
|
||||
{
|
||||
X = (short)x;
|
||||
Y = (short)y;
|
||||
Z = (short)z;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(", ", X, Y, Z);
|
||||
}
|
||||
|
||||
private delegate Vector3int16 Operator(Vector3int16 a, Vector3int16 b);
|
||||
|
||||
private static Vector3int16 upcastShortOp(Vector3int16 vec, short num, Operator upcast)
|
||||
{
|
||||
Vector3int16 numVec = new Vector3int16(num, num, num);
|
||||
return upcast(vec, numVec);
|
||||
}
|
||||
|
||||
private static Vector3int16 upcastShortOp(short num, Vector3int16 vec, Operator upcast)
|
||||
{
|
||||
Vector3int16 numVec = new Vector3int16(num, num, num);
|
||||
return upcast(numVec, vec);
|
||||
}
|
||||
|
||||
private static Operator add = new Operator((a, b) => new Vector3int16(a.X + b.X, a.Y + b.Y, a.Z + b.Z));
|
||||
private static Operator sub = new Operator((a, b) => new Vector3int16(a.X - b.X, a.Y - b.Y, a.Z - b.Z));
|
||||
private static Operator mul = new Operator((a, b) => new Vector3int16(a.X * b.X, a.Y * b.Y, a.Z * b.Z));
|
||||
private static Operator div = new Operator((a, b) =>
|
||||
{
|
||||
if (b.X == 0 || b.Y == 0 || b.Z == 0)
|
||||
throw new DivideByZeroException();
|
||||
|
||||
return new Vector3int16(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
|
||||
});
|
||||
|
||||
public static Vector3int16 operator +(Vector3int16 a, Vector3int16 b) => add(a, b);
|
||||
public static Vector3int16 operator +(Vector3int16 v, short n) => upcastShortOp(v, n, add);
|
||||
public static Vector3int16 operator +(short n, Vector3int16 v) => upcastShortOp(n, v, add);
|
||||
|
||||
public static Vector3int16 operator -(Vector3int16 a, Vector3int16 b) => sub(a, b);
|
||||
public static Vector3int16 operator -(Vector3int16 v, short n) => upcastShortOp(v, n, sub);
|
||||
public static Vector3int16 operator -(short n, Vector3int16 v) => upcastShortOp(n, v, sub);
|
||||
|
||||
public static Vector3int16 operator *(Vector3int16 a, Vector3int16 b) => mul(a, b);
|
||||
public static Vector3int16 operator *(Vector3int16 v, short n) => upcastShortOp(v, n, mul);
|
||||
public static Vector3int16 operator *(short n, Vector3int16 v) => upcastShortOp(n, v, mul);
|
||||
|
||||
public static Vector3int16 operator /(Vector3int16 a, Vector3int16 b) => div(a, b);
|
||||
public static Vector3int16 operator /(Vector3int16 v, short n) => upcastShortOp(v, n, div);
|
||||
public static Vector3int16 operator /(short n, Vector3int16 v) => upcastShortOp(n, v, div);
|
||||
}
|
||||
}
|
36
Properties/AssemblyInfo.cs
Normal file
36
Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("RobloxFileFormat")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("RobloxFileFormat")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("cf50c0e2-23a7-4dc1-b4b2-e60cde716253")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
99
RobloxFileFormat.csproj
Normal file
99
RobloxFileFormat.csproj
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{CF50C0E2-23A7-4DC1-B4B2-E60CDE716253}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Roblox</RootNamespace>
|
||||
<AssemblyName>RobloxFileFormat</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="LZ4, Version=1.0.15.93, Culture=neutral, PublicKeyToken=62e1b5ec1eec9bdd, processorArchitecture=MSIL">
|
||||
<HintPath>packages\lz4net.1.0.15.93\lib\net4-client\LZ4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BinaryFormat\Chunk.cs" />
|
||||
<Compile Include="BinaryFormat\BinaryFile.cs" />
|
||||
<Compile Include="BinaryFormat\ChunkTypes\INST.cs" />
|
||||
<Compile Include="BinaryFormat\ChunkTypes\META.cs" />
|
||||
<Compile Include="BinaryFormat\ChunkTypes\PRNT.cs" />
|
||||
<Compile Include="BinaryFormat\ChunkTypes\PROP.cs" />
|
||||
<Compile Include="BinaryFormat\Reader.cs" />
|
||||
<Compile Include="Core\Property.cs" />
|
||||
<Compile Include="DataTypes\Axes.cs" />
|
||||
<Compile Include="DataTypes\BrickColor.cs" />
|
||||
<Compile Include="DataTypes\CFrame.cs" />
|
||||
<Compile Include="DataTypes\Color3.cs" />
|
||||
<Compile Include="DataTypes\ColorSequence.cs" />
|
||||
<Compile Include="DataTypes\ColorSequenceKeypoint.cs" />
|
||||
<Compile Include="DataTypes\Faces.cs" />
|
||||
<Compile Include="DataTypes\NumberRange.cs" />
|
||||
<Compile Include="DataTypes\NumberSequence.cs" />
|
||||
<Compile Include="DataTypes\NumberSequenceKeypoint.cs" />
|
||||
<Compile Include="DataTypes\PathWaypoint.cs" />
|
||||
<Compile Include="DataTypes\PhysicalProperties.cs" />
|
||||
<Compile Include="DataTypes\Ray.cs" />
|
||||
<Compile Include="DataTypes\Region3int16.cs" />
|
||||
<Compile Include="DataTypes\Utility\BrickColors.cs" />
|
||||
<Compile Include="DataTypes\Vector3int16.cs" />
|
||||
<Compile Include="Core\Enums.cs" />
|
||||
<Compile Include="DataTypes\Utility\MaterialInfo.cs" />
|
||||
<Compile Include="DataTypes\Utility\Quaternion.cs" />
|
||||
<Compile Include="DataTypes\Rect.cs" />
|
||||
<Compile Include="DataTypes\Region3.cs" />
|
||||
<Compile Include="DataTypes\UDim.cs" />
|
||||
<Compile Include="DataTypes\UDim2.cs" />
|
||||
<Compile Include="DataTypes\Vector2.cs" />
|
||||
<Compile Include="DataTypes\Vector3.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Core\RobloxFile.cs" />
|
||||
<Compile Include="Core\Instance.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
22
RobloxFileFormat.sln
Normal file
22
RobloxFileFormat.sln
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RobloxFileFormat", "RobloxFileFormat.csproj", "{CF50C0E2-23A7-4DC1-B4B2-E60CDE716253}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CF50C0E2-23A7-4DC1-B4B2-E60CDE716253}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CF50C0E2-23A7-4DC1-B4B2-E60CDE716253}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CF50C0E2-23A7-4DC1-B4B2-E60CDE716253}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CF50C0E2-23A7-4DC1-B4B2-E60CDE716253}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
4
packages.config
Normal file
4
packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="lz4net" version="1.0.15.93" targetFramework="net452" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user