diff --git a/BinaryFormat/Chunks/PROP.cs b/BinaryFormat/Chunks/PROP.cs index 9a21c29..8e8cbc3 100644 --- a/BinaryFormat/Chunks/PROP.cs +++ b/BinaryFormat/Chunks/PROP.cs @@ -353,11 +353,22 @@ namespace RobloxFiles.BinaryFormat.Chunks try { var info = ImplicitMember.Get(instType, Name); + + if (info == null) + { + if (RobloxFile.LogErrors) + Console.Error.WriteLine($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); + + return value; + } + return Enum.Parse(info.MemberType, value.ToInvariantString()); } catch { - Console.WriteLine($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); + if (RobloxFile.LogErrors) + Console.Error.WriteLine($"Enum cast failed for {inst.ClassName}.{Name} using value {value}!"); + return value; } }); @@ -522,7 +533,9 @@ namespace RobloxFiles.BinaryFormat.Chunks break; default: - Console.Error.WriteLine("Unhandled property type: {0}!", Type); + if (RobloxFile.LogErrors) + Console.Error.WriteLine("Unhandled property type: {0}!", Type); + break; // } diff --git a/DataTypes/CFrame.cs b/DataTypes/CFrame.cs index 4af543e..5521edc 100644 --- a/DataTypes/CFrame.cs +++ b/DataTypes/CFrame.cs @@ -346,19 +346,28 @@ namespace RobloxFiles.DataTypes 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) + public static CFrame FromEulerAnglesXYZ(float x, float y, float z) { - CFrame cfx = FromAxisAngle(Vector3.Right, x); - CFrame cfy = FromAxisAngle(Vector3.Up, y); - CFrame cfz = FromAxisAngle(Vector3.Back, z); + CFrame cfx = FromAxisAngle(Vector3.Right, x), + cfy = FromAxisAngle(Vector3.Up, y), + cfz = FromAxisAngle(Vector3.Back, z); return cfx * cfy * cfz; } - public static CFrame FromEulerAnglesXYZ(float x, float y, float z) + public static CFrame FromEulerAnglesXYZ(params float[] angles) { - return Angles(x, y, z); + Contract.Requires(angles.Length == 3); + + float x = angles[0], + y = angles[1], + z = angles[2]; + + return FromEulerAnglesXYZ(x, y, z); } + + public static CFrame Angles(float x, float y, float z) => FromEulerAnglesXYZ(x, y, z); + public static CFrame Angles(params float[] angles) => FromEulerAnglesXYZ(angles); public CFrame Lerp(CFrame other, float t) { diff --git a/DataTypes/Color3.cs b/DataTypes/Color3.cs index d7dda5f..fc7d271 100644 --- a/DataTypes/Color3.cs +++ b/DataTypes/Color3.cs @@ -65,20 +65,13 @@ namespace RobloxFiles.DataTypes 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(); + 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(0, 0, 0); } } diff --git a/RobloxFileFormat.csproj b/RobloxFileFormat.csproj index b3211ca..1fad478 100644 --- a/RobloxFileFormat.csproj +++ b/RobloxFileFormat.csproj @@ -48,7 +48,7 @@ prompt 1 MinimumRecommendedRules.ruleset - x64 + AnyCPU diff --git a/RobloxFileFormat.dll b/RobloxFileFormat.dll index a7ba9b6..bed9461 100644 Binary files a/RobloxFileFormat.dll and b/RobloxFileFormat.dll differ diff --git a/Tree/Instance.cs b/Tree/Instance.cs index 5de87fc..65e319f 100644 --- a/Tree/Instance.cs +++ b/Tree/Instance.cs @@ -56,6 +56,9 @@ namespace RobloxFiles /// Indicates whether this Instance is a Service. public bool IsService { get; internal set; } + /// Indicates whether this Instance has been destroyed. + public bool Destroyed { get; internal set; } + /// A list of CollectionService tags assigned to this Instance. public List Tags { get; } = new List(); @@ -200,12 +203,9 @@ namespace RobloxFiles if (Parent == this) throw new InvalidOperationException($"Attempt to set {Name} as its own parent"); - lock (ParentUnsafe) - { - ParentUnsafe?.Children.Remove(this); - value?.Children.Add(this); - ParentUnsafe = value; - } + ParentUnsafe?.Children.Remove(this); + value?.Children.Add(this); + ParentUnsafe = value; } } @@ -418,6 +418,28 @@ namespace RobloxFiles return result; } + /// + /// Disposes of this instance and its descendants, and locks its parent. + /// All property bindings, tags, and attributes are cleared. + /// + public void Destroy() + { + Destroyed = true; + props.Clear(); + + Parent = null; + ParentLocked = true; + + Tags?.Clear(); + Attributes?.Clear(); + + while (Children.Any()) + { + var child = Children.First(); + child.Destroy(); + } + } + /// /// Returns the first child of this Instance which derives from the provided type . /// If the instance is not found, this returns null. diff --git a/XmlFormat/IO/XmlFileReader.cs b/XmlFormat/IO/XmlFileReader.cs index 5d76351..fef434f 100644 --- a/XmlFormat/IO/XmlFileReader.cs +++ b/XmlFormat/IO/XmlFileReader.cs @@ -114,7 +114,7 @@ namespace RobloxFiles.XmlFormat } else if (RobloxFile.LogErrors) { - Console.WriteLine("No IXmlPropertyToken found for property type: " + propType + '!'); + Console.Error.WriteLine("No IXmlPropertyToken found for property type: " + propType + '!'); } } } diff --git a/XmlFormat/Tokens/Color3.cs b/XmlFormat/Tokens/Color3.cs index 62462b3..64ce450 100644 --- a/XmlFormat/Tokens/Color3.cs +++ b/XmlFormat/Tokens/Color3.cs @@ -7,7 +7,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens public class Color3Token : IXmlPropertyToken { public string Token => "Color3"; - private string[] Fields = new string[3] { "R", "G", "B" }; + private readonly string[] Fields = new string[3] { "R", "G", "B" }; public bool ReadProperty(Property prop, XmlNode token) { @@ -21,7 +21,15 @@ namespace RobloxFiles.XmlFormat.PropertyTokens try { var coord = token[key]; - fields[i] = Formatting.ParseFloat(coord.InnerText); + string text = coord?.InnerText; + + if (text == null) + { + text = "0"; + success = false; + } + + fields[i] = Formatting.ParseFloat(text); } catch { diff --git a/XmlFormat/Tokens/Content.cs b/XmlFormat/Tokens/Content.cs index 60c4242..e1073bf 100644 --- a/XmlFormat/Tokens/Content.cs +++ b/XmlFormat/Tokens/Content.cs @@ -33,7 +33,7 @@ namespace RobloxFiles.XmlFormat.PropertyTokens if (!RobloxFile.LogErrors) return true; - Console.WriteLine("ContentToken: Got illegal base64 string: {0}", data); + Console.Error.WriteLine("ContentToken: Got illegal base64 string: {0}", data); } } }