Editor/RbxlToSbox.cs
using Sandbox;
using RbxlReader;
using RbxlReader.Instances;
using RbxlReader.DataTypes;
public static class RbxlToSbox {
public static readonly string DEFAULT_ROOT_NAME = "NOBLOX - Root";
public static void ImportFile(string filePath, Scene scene) {
PlaceBinary place = new(filePath);
foreach (GameObject obj in scene.Children) {
if (obj.Tags.Has("rbxl")) {
Log.Info("Found old .rbxl import object. Rewritting...");
obj.Destroy();
}
}
GameObject root = scene.CreateObject();
root.Name = DEFAULT_ROOT_NAME;
root.Tags.Add("rbxl");
var rootComp = root.AddComponent<RbxlRoot>();
rootComp.InstanceCount = place.NumberInstances;
rootComp.ClassCount = place.NumberClasses;
rootComp.IdToInstance = new InstanceComponent[rootComp.InstanceCount];
recursiveInstanceHandler(place.Workspace, scene, root, rootComp);
Log.Info("Post init setup");
foreach (InstanceComponent comp in scene.GetAllComponents<InstanceComponent>()) {
comp.PostApplyData();
}
Log.Info($"Imported {rootComp.ImportedObjectCount} GameObjects to scene.");
Log.Info("Cleaning instances up...");
int cleanCount = rootComp.Cleanup();
Log.Info($"{cleanCount} cleaned instances.");
Log.Info($"Importing completed! {rootComp.ImportedObjectCount - cleanCount} total.");
}
private static void recursiveInstanceHandler(Instance parent, Scene scene, GameObject previousObj, RbxlRoot root) {
Instance[] instances = parent.GetChildren();
if (instances.Length == 0) return;
foreach(Instance instance in instances) {
var gameObj = scene.CreateObject();
gameObj.Parent = previousObj;
var comp = handleProperties(instance, gameObj, root);
root.IdToInstance[comp.InstanceId] = comp;
root.ImportedObjectCount++;
recursiveInstanceHandler(instance, scene, gameObj, root);
}
}
private static InstanceComponent handleProperties(Instance instance, GameObject gameObject, RbxlRoot root) {
InstanceComponent comp;
switch (instance.ClassName) {
case "SpawnLocation":
case "Part": {
comp = gameObject.AddComponent<PartComponent>(true);
var part = (PartComponent)comp;
CFrame cf = (CFrame)instance.GetProperty("CFrame").Value;
var size = (RbxlReader.DataTypes.Vector3)instance.GetProperty("size").Value;
var rot = cf.ToEulerAngles();
var color = (Color3)instance.GetProperty("Color3uint8").Value;
var transparency = (float)instance.GetProperty("Transparency").Value;
part.StudPosition = new(-cf.Position.X, cf.Position.Z, cf.Position.Y);
part.StudSize = new(size.X, size.Z, size.Y);
part.StudRotation = new(MathX.RadianToDegree(rot.Roll), MathX.RadianToDegree(rot.Yaw), MathX.RadianToDegree(-rot.Pitch));
part.BrickColor = Color.FromBytes((int)color.R, (int)color.G, (int)color.B, (int)((1 - transparency) * 255));
part.Shape = (PartShape)(uint)instance.GetProperty("shape").Value;
part.CanCollide = (bool)instance.GetProperty("CanCollide").Value;
part.Anchored = (bool)instance.GetProperty("Anchored").Value;
break;
}
case "PointLight": {
comp = gameObject.AddComponent<RbxlPointLightComponent>();
var light = (RbxlPointLightComponent)comp;
light.Strength = (float)instance.GetProperty("Brightness").Value;
light.Range = (float)instance.GetProperty("Range").Value;
break;
}
case "WeldConstraint": {
comp = gameObject.AddComponent<WeldComponent>();
var constr = (ConstraintComponent)comp;
constr.Part0 = (int)instance.GetProperty("Part0Internal").Value;
constr.Part1 = (int)instance.GetProperty("Part1Internal").Value;
break;
}
case "RopeConstraint": {
comp = gameObject.AddComponent<RopeComponent>();
var constr = (RopeComponent)comp;
constr.Part0 = (int)instance.GetProperty("Attachment0").Value;
constr.Part1 = (int)instance.GetProperty("Attachment1").Value;
constr.Length = (float)instance.GetProperty("Length").Value;
break;
}
case "Weld":
case "Snap": {
comp = gameObject.AddComponent<WeldComponent>();
var constr = (ConstraintComponent)comp;
constr.Part0 = (int)instance.GetProperty("Part0").Value;
constr.Part1 = (int)instance.GetProperty("Part1").Value;
break;
}
default: {
comp = gameObject.AddComponent<InstanceComponent>();
break;
}
}
comp.InstanceId = instance.Id;
gameObject.Name = instance.Name;
comp.ClassName = instance.ClassName;
comp.Root = root;
comp.ApplyData();
return comp;
}
}