diff --git a/docs/attributes.md b/docs/attributes.md index 74f2dba59..ff1e9d6d2 100644 --- a/docs/attributes.md +++ b/docs/attributes.md @@ -16,6 +16,7 @@ This document describes the Attribute binary format. In this format there is no - [Color3](#color3) - [Vector2](#vector2) - [Vector3](#vector3) + - [CFrame](#cframe) - [NumberSequence](#numbersequence) - [ColorSequence](#colorsequence) - [NumberRange](#numberrange) @@ -147,6 +148,38 @@ The `Vector3` type is a struct composed of three `f32`s: A Vector3 with the value `10, 20, 30` looks like this: `00 00 20 41 00 00 a0 41 00 00 f0 41`. +### CFrame +**Type ID `0x14`** + +The `CFrame` type is composed of a `Vector3`, a 1-byte rotation ID, and an optional rotation matrix: + +| Field Name | Format | Value | +|:----------------|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Position | `Vector3` | The positional component of the `CFrame`. | +| Rotation ID | `u8` | An identifier representing axis-alignment of the rotation, determining whether the rotation matrix is present (see `Rotation matrix`). If the rotation *is* axis-aligned, this field is one of the values from the table below; otherwise, it is `00`. | +| Rotation matrix | `Optional` | The rotational component of the `CFrame`, stored as a sequence of nine `f32`s. If Rotation ID is `00`, this field is the XVector, the YVector, and ZVector, in that order; otherwise, it is absent. | + +A rotation is considered "axis-aligned" if it's in increments of 90 degrees around one or more axes. The following table shows the mapping between Rotation IDs and rotations (rotations are Euler angles in degrees, applied in the order `Y -> X -> Z`): + +| ID | Rotation | ID | Rotation | +|:-----|:---------------|:-----|:---------------| +| `02` | (0, 0, 0) | `14` | (0, 180, 0) | +| `03` | (90, 0, 0) | `15` | (-90, -180, 0) | +| `05` | (0, 180, 180) | `17` | (0, 0, 180) | +| `06` | (-90, 0, 0) | `18` | (90, 180, 0) | +| `07` | (0, 180, 90) | `19` | (0, 0, -90) | +| `09` | (0, 90, 90) | `1b` | (0, -90, -90) | +| `0a` | (0, 0, 90) | `1c` | (0, -180, -90) | +| `0c` | (0, -90, 90) | `1e` | (0, 90, -90) | +| `0d` | (-90, -90, 0) | `1f` | (90, 90, 0) | +| `0e` | (0, -90, 0) | `20` | (0, 90, 0) | +| `10` | (90, -90, 0) | `22` | (-90, 90, 0) | +| `11` | (0, 90, 180) | `23` | (0, -90, 180) | + +A `CFrame` with the value `CFrame.new(1, 2, 3) * CFrame.Angles(0, 45, 0)` looks like this when serialized: `00 00 80 3f 00 00 00 40 00 00 40 40 00 f3 04 35 3f 00 00 00 00 f3 04 35 3f 00 00 00 00 00 00 80 3f 00 00 00 00 f3 04 35 bf 00 00 00 00 f3 04 35 3f`. + +Demonstrating the axis-aligned rotation matrix case, a `CFrame` with the value `CFrame.new(1, 2, 3)` looks like this: `00 00 80 3f 00 00 00 40 00 00 40 40 02`. + ### NumberSequence **Type ID `0x17`** diff --git a/rbx_binary/src/tests/models.rs b/rbx_binary/src/tests/models.rs index 967cdd6aa..3965e2c3e 100644 --- a/rbx_binary/src/tests/models.rs +++ b/rbx_binary/src/tests/models.rs @@ -62,4 +62,5 @@ binary_tests! { package_link, text_label_with_font, gui_inset_and_font_migration, + folder_with_cframe_attributes, } diff --git a/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__decoded.snap b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__decoded.snap new file mode 100644 index 000000000..3a9e8a51a --- /dev/null +++ b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__decoded.snap @@ -0,0 +1,416 @@ +--- +source: rbx_binary/src/tests/util.rs +expression: decoded_viewed +--- +- referent: referent-0 + name: Folder + class: Folder + properties: + Attributes: + Attributes: + Rotation02: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 1 + - 0 + - - 0 + - 0 + - 1 + Rotation03: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 0 + - -1 + - - 0 + - 1 + - 0 + Rotation05: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - -1 + - 0 + - - 0 + - 0 + - -1 + Rotation06: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 0 + - 1 + - - 0 + - -1 + - 0 + Rotation07: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 1 + - 0 + - 0 + - - 0 + - 0 + - -1 + Rotation09: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 1 + - 0 + - 0 + - - 0 + - 1 + - 0 + Rotation0a: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 1 + - 0 + - 0 + - - 0 + - 0 + - 1 + Rotation0c: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 1 + - 0 + - 0 + - - 0 + - -1 + - 0 + Rotation0d: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 0 + - 0 + - 1 + - - 1 + - 0 + - 0 + Rotation0e: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 0 + - 1 + - 0 + - - 1 + - 0 + - 0 + Rotation10: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 0 + - 0 + - -1 + - - 1 + - 0 + - 0 + Rotation11: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 0 + - -1 + - 0 + - - 1 + - 0 + - 0 + Rotation14: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 1 + - 0 + - - 0 + - 0 + - -1 + Rotation15: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 0 + - 1 + - - 0 + - 1 + - 0 + Rotation17: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - -1 + - 0 + - - 0 + - 0 + - 1 + Rotation18: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 0 + - -1 + - - 0 + - -1 + - 0 + Rotation19: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - -1 + - 0 + - 0 + - - 0 + - 0 + - 1 + Rotation1b: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - -1 + - 0 + - 0 + - - 0 + - 1 + - 0 + Rotation1c: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - -1 + - 0 + - 0 + - - 0 + - 0 + - -1 + Rotation1e: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - -1 + - 0 + - 0 + - - 0 + - -1 + - 0 + Rotation1f: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 0 + - 0 + - -1 + - - -1 + - 0 + - 0 + Rotation20: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 0 + - 1 + - 0 + - - -1 + - 0 + - 0 + Rotation22: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 0 + - 0 + - 1 + - - -1 + - 0 + - 0 + Rotation23: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 0 + - -1 + - 0 + - - -1 + - 0 + - 0 + YetAnotherCFrameAttribute: + CFrame: + position: + - 1 + - 3.1333337 + - 0.808 + orientation: + - - -0.24184482 + - -0.9396926 + - -0.24184477 + - - 0.70710677 + - -0.00000003090862 + - -0.70710677 + - - 0.664463 + - -0.34202018 + - 0.664463 + SourceAssetId: + Int64: -1 + Tags: + Tags: [] + children: [] + diff --git a/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__encoded.snap b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__encoded.snap new file mode 100644 index 000000000..65d3e0ea7 --- /dev/null +++ b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__encoded.snap @@ -0,0 +1,44 @@ +--- +source: rbx_binary/src/tests/util.rs +expression: text_roundtrip +--- +num_types: 1 +num_instances: 1 +chunks: + - Inst: + type_id: 0 + type_name: Folder + object_format: 0 + referents: + - 0 + - Prop: + type_id: 0 + prop_name: AttributesSerialize + prop_type: String + values: + - 19 00 00 00 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 32 14 00 00 00 00 00 00 00 00 00 00 00 00 02 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 33 14 00 00 00 00 00 00 00 00 00 00 00 00 03 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 35 14 00 00 00 00 00 00 00 00 00 00 00 00 05 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 36 14 00 00 00 00 00 00 00 00 00 00 00 00 06 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 37 14 00 00 00 00 00 00 00 00 00 00 00 00 07 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 39 14 00 00 00 00 00 00 00 00 00 00 00 00 09 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 61 14 00 00 00 00 00 00 00 00 00 00 00 00 0a 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 63 14 00 00 00 00 00 00 00 00 00 00 00 00 0c 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 64 14 00 00 00 00 00 00 00 00 00 00 00 00 0d 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 65 14 00 00 00 00 00 00 00 00 00 00 00 00 0e 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 30 14 00 00 00 00 00 00 00 00 00 00 00 00 10 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 31 14 00 00 00 00 00 00 00 00 00 00 00 00 11 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 34 14 00 00 00 00 00 00 00 00 00 00 00 00 14 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 35 14 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 37 14 00 00 00 00 00 00 00 00 00 00 00 00 17 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 38 14 00 00 00 00 00 00 00 00 00 00 00 00 18 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 39 14 00 00 00 00 00 00 00 00 00 00 00 00 19 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 62 14 00 00 00 00 00 00 00 00 00 00 00 00 1b 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 63 14 00 00 00 00 00 00 00 00 00 00 00 00 1c 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 65 14 00 00 00 00 00 00 00 00 00 00 00 00 1e 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 66 14 00 00 00 00 00 00 00 00 00 00 00 00 1f 0a 00 00 00 52 6f 74 61 74 69 6f 6e 32 30 14 00 00 00 00 00 00 00 00 00 00 00 00 20 0a 00 00 00 52 6f 74 61 74 69 6f 6e 32 32 14 00 00 00 00 00 00 00 00 00 00 00 00 22 0a 00 00 00 52 6f 74 61 74 69 6f 6e 32 33 14 00 00 00 00 00 00 00 00 00 00 00 00 23 19 00 00 00 59 65 74 41 6e 6f 74 68 65 72 43 46 72 61 6d 65 41 74 74 72 69 62 75 74 65 14 00 00 80 3f 8a 88 48 40 17 d9 4e 3f 00 2b a6 77 be b2 8f 70 bf 28 a6 77 be f3 04 35 3f 63 c0 04 b3 f3 04 35 bf 3f 1a 2a 3f 45 1d af be 3f 1a 2a 3f + - Prop: + type_id: 0 + prop_name: Name + prop_type: String + values: + - Folder + - Prop: + type_id: 0 + prop_name: SourceAssetId + prop_type: Int64 + values: + - -1 + - Prop: + type_id: 0 + prop_name: Tags + prop_type: String + values: + - "" + - Prnt: + version: 0 + links: + - - 0 + - -1 + - End + diff --git a/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__input.snap b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__input.snap new file mode 100644 index 000000000..3e677114e --- /dev/null +++ b/rbx_binary/src/tests/snapshots/rbx_binary__tests__util__folder-with-cframe-attributes__input.snap @@ -0,0 +1,48 @@ +--- +source: rbx_binary/src/tests/util.rs +expression: text_decoded +--- +num_types: 1 +num_instances: 1 +chunks: + - Meta: + entries: + - - ExplicitAutoJoints + - "true" + - Inst: + type_id: 0 + type_name: Folder + object_format: 0 + referents: + - 0 + - Prop: + type_id: 0 + prop_name: AttributesSerialize + prop_type: String + values: + - 19 00 00 00 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 32 14 00 00 00 00 00 00 00 00 00 00 00 00 02 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 33 14 00 00 00 00 00 00 00 00 00 00 00 00 03 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 35 14 00 00 00 00 00 00 00 00 00 00 00 00 05 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 36 14 00 00 00 00 00 00 00 00 00 00 00 00 06 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 37 14 00 00 00 00 00 00 00 00 00 00 00 00 07 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 39 14 00 00 00 00 00 00 00 00 00 00 00 00 09 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 61 14 00 00 00 00 00 00 00 00 00 00 00 00 0a 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 63 14 00 00 00 00 00 00 00 00 00 00 00 00 0c 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 64 14 00 00 00 00 00 00 00 00 00 00 00 00 0d 0a 00 00 00 52 6f 74 61 74 69 6f 6e 30 65 14 00 00 00 00 00 00 00 00 00 00 00 00 0e 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 30 14 00 00 00 00 00 00 00 00 00 00 00 00 10 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 31 14 00 00 00 00 00 00 00 00 00 00 00 00 11 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 34 14 00 00 00 00 00 00 00 00 00 00 00 00 14 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 35 14 00 00 00 00 00 00 00 00 00 00 00 00 15 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 37 14 00 00 00 00 00 00 00 00 00 00 00 00 17 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 38 14 00 00 00 00 00 00 00 00 00 00 00 00 18 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 39 14 00 00 00 00 00 00 00 00 00 00 00 00 19 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 62 14 00 00 00 00 00 00 00 00 00 00 00 00 1b 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 63 14 00 00 00 00 00 00 00 00 00 00 00 00 1c 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 65 14 00 00 00 00 00 00 00 00 00 00 00 00 1e 0a 00 00 00 52 6f 74 61 74 69 6f 6e 31 66 14 00 00 00 00 00 00 00 00 00 00 00 00 1f 0a 00 00 00 52 6f 74 61 74 69 6f 6e 32 30 14 00 00 00 00 00 00 00 00 00 00 00 00 20 0a 00 00 00 52 6f 74 61 74 69 6f 6e 32 32 14 00 00 00 00 00 00 00 00 00 00 00 00 22 0a 00 00 00 52 6f 74 61 74 69 6f 6e 32 33 14 00 00 00 00 00 00 00 00 00 00 00 00 23 19 00 00 00 59 65 74 41 6e 6f 74 68 65 72 43 46 72 61 6d 65 41 74 74 72 69 62 75 74 65 14 00 00 80 3f 8a 88 48 40 17 d9 4e 3f 00 2b a6 77 be b2 8f 70 bf 28 a6 77 be f3 04 35 3f 63 c0 04 b3 f3 04 35 bf 3f 1a 2a 3f 45 1d af be 3f 1a 2a 3f + - Prop: + type_id: 0 + prop_name: Name + prop_type: String + values: + - Folder + - Prop: + type_id: 0 + prop_name: SourceAssetId + prop_type: Int64 + values: + - -1 + - Prop: + type_id: 0 + prop_name: Tags + prop_type: String + values: + - "" + - Prnt: + version: 0 + links: + - - 0 + - -1 + - End + diff --git a/rbx_types/CHANGELOG.md b/rbx_types/CHANGELOG.md index cb7f34e61..9ccd90b73 100644 --- a/rbx_types/CHANGELOG.md +++ b/rbx_types/CHANGELOG.md @@ -4,10 +4,12 @@ * Added support for `UniqueId` values. ([#271]) * Changed `BinaryString`'s non-human readable serde implementation to be identical to `Vec`. ([#276]) * Added `Font::new` and `Font::regular` constructors. ([#283]) +* Added support for `CFrame` values in attributes. ([#296]) [#271]: https://github.com/rojo-rbx/rbx-dom/pull/271 [#276]: https://github.com/rojo-rbx/rbx-dom/pull/276 [#283]: https://github.com/rojo-rbx/rbx-dom/pull/283 +[#296]: https://github.com/rojo-rbx/rbx-dom/pull/296 ## 1.5.0 (2023-04-22) * Implemented `Font`. ([#248]) diff --git a/rbx_types/src/attributes/error.rs b/rbx_types/src/attributes/error.rs index 017a9e6e9..b60201f4d 100644 --- a/rbx_types/src/attributes/error.rs +++ b/rbx_types/src/attributes/error.rs @@ -30,6 +30,9 @@ pub(crate) enum AttributeError { #[error(transparent)] Io(#[from] std::io::Error), + #[error(transparent)] + BadAttributeValue(#[from] crate::Error), + #[error("couldn't read bytes to deserialize {0}")] ReadType(&'static str), } diff --git a/rbx_types/src/attributes/reader.rs b/rbx_types/src/attributes/reader.rs index 2afa861ee..3c614dedd 100644 --- a/rbx_types/src/attributes/reader.rs +++ b/rbx_types/src/attributes/reader.rs @@ -4,9 +4,9 @@ use std::{ }; use crate::{ - BinaryString, BrickColor, Color3, ColorSequence, ColorSequenceKeypoint, NumberRange, - NumberSequence, NumberSequenceKeypoint, Rect, UDim, UDim2, Variant, VariantType, Vector2, - Vector3, + BinaryString, BrickColor, CFrame, Color3, ColorSequence, ColorSequenceKeypoint, Matrix3, + NumberRange, NumberSequence, NumberSequenceKeypoint, Rect, UDim, UDim2, Variant, VariantType, + Vector2, Vector3, }; use super::{type_id, AttributeError}; @@ -143,6 +143,24 @@ pub(crate) fn read_attributes( ) .into(), + VariantType::CFrame => { + let position = read_vector3(&mut value)?; + let rotation_id = read_u8(&mut value)?; + + let rotation = if rotation_id == 0 { + Matrix3::new( + read_vector3(&mut value)?, + read_vector3(&mut value)?, + read_vector3(&mut value)?, + ) + } else { + Matrix3::from_basic_rotation_id(rotation_id)? + }; + + CFrame::new(position, rotation) + } + .into(), + other => return Err(AttributeError::UnsupportedVariantType(other)), }; @@ -214,6 +232,14 @@ fn read_vector2(mut reader: R) -> io::Result { Ok(Vector2::new(read_f32(&mut reader)?, read_f32(&mut reader)?)) } +fn read_vector3(mut reader: R) -> io::Result { + Ok(Vector3::new( + read_f32(&mut reader)?, + read_f32(&mut reader)?, + read_f32(&mut reader)?, + )) +} + /// Implementation taken from read_exact, but allowing an empty buffer by /// returning `Ok(false)` instead of an EOF error. fn read_exact_or_none(mut reader: R, mut buf: &mut [u8]) -> io::Result { diff --git a/rbx_types/src/attributes/type_id.rs b/rbx_types/src/attributes/type_id.rs index b0ca82bfa..e891bc2e7 100644 --- a/rbx_types/src/attributes/type_id.rs +++ b/rbx_types/src/attributes/type_id.rs @@ -40,7 +40,7 @@ type_ids! { Vector3 => 0x11, // ??? => 0x12, // ??? => 0x13, - // ??? => 0x14, + CFrame => 0x14, // ??? => 0x15, // ??? => 0x16, NumberSequence => 0x17, diff --git a/rbx_types/src/attributes/writer.rs b/rbx_types/src/attributes/writer.rs index b9aa85017..15c53c00f 100644 --- a/rbx_types/src/attributes/writer.rs +++ b/rbx_types/src/attributes/writer.rs @@ -9,6 +9,7 @@ use super::{type_id, AttributeError}; use crate::{ basic_types::{Color3, UDim, Vector2}, variant::Variant, + Vector3, }; /// Writes the attribute property (AttributesSerialize) from a map of attribute names -> values. @@ -76,6 +77,21 @@ pub(crate) fn write_attributes( write_f32(&mut writer, vector3.y)?; write_f32(&mut writer, vector3.z)? } + Variant::CFrame(cframe) => { + write_vector3(&mut writer, cframe.position)?; + + let matrix = cframe.orientation; + + if let Some(rotation_id) = matrix.to_basic_rotation_id() { + write_u8(&mut writer, rotation_id)?; + } else { + write_u8(&mut writer, 0x00)?; + + write_vector3(&mut writer, matrix.x)?; + write_vector3(&mut writer, matrix.y)?; + write_vector3(&mut writer, matrix.z)?; + } + } other_variant => unreachable!("variant {:?} was not implemented", other_variant), } @@ -96,6 +112,10 @@ fn write_u32(mut writer: W, n: u32) -> io::Result<()> { writer.write_all(&n.to_le_bytes()[..]) } +fn write_u8(mut writer: W, n: u8) -> io::Result<()> { + writer.write_all(&n.to_le_bytes()[..]) +} + fn write_color3(mut writer: W, color: Color3) -> io::Result<()> { write_f32(&mut writer, color.r)?; write_f32(&mut writer, color.g)?; @@ -117,3 +137,9 @@ fn write_vector2(mut writer: W, vector2: Vector2) -> io::Result<()> { write_f32(&mut writer, vector2.x)?; write_f32(&mut writer, vector2.y) } + +fn write_vector3(mut writer: W, vector3: Vector3) -> io::Result<()> { + write_f32(&mut writer, vector3.x)?; + write_f32(&mut writer, vector3.y)?; + write_f32(&mut writer, vector3.z) +} diff --git a/rbx_xml/src/tests/models.rs b/rbx_xml/src/tests/models.rs index 7fdacd690..f8103cbb8 100644 --- a/rbx_xml/src/tests/models.rs +++ b/rbx_xml/src/tests/models.rs @@ -63,4 +63,5 @@ model_tests! { package_link, text_label_with_font, gui_inset_and_font_migration, + folder_with_cframe_attributes, } diff --git a/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-cframe-attributes__decoded.snap b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-cframe-attributes__decoded.snap new file mode 100644 index 000000000..4afeb91d4 --- /dev/null +++ b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-cframe-attributes__decoded.snap @@ -0,0 +1,416 @@ +--- +source: rbx_xml/src/tests/mod.rs +expression: "DomViewer::new().view_children(&decoded)" +--- +- referent: referent-0 + name: Folder + class: Folder + properties: + Attributes: + Attributes: + Rotation02: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 1 + - 0 + - - 0 + - 0 + - 1 + Rotation03: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 0 + - -1 + - - 0 + - 1 + - 0 + Rotation05: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - -1 + - 0 + - - 0 + - 0 + - -1 + Rotation06: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 0 + - 1 + - - 0 + - -1 + - 0 + Rotation07: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 1 + - 0 + - 0 + - - 0 + - 0 + - -1 + Rotation09: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 1 + - 0 + - 0 + - - 0 + - 1 + - 0 + Rotation0a: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 1 + - 0 + - 0 + - - 0 + - 0 + - 1 + Rotation0c: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 1 + - 0 + - 0 + - - 0 + - -1 + - 0 + Rotation0d: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 0 + - 0 + - 1 + - - 1 + - 0 + - 0 + Rotation0e: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 0 + - 1 + - 0 + - - 1 + - 0 + - 0 + Rotation10: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 0 + - 0 + - -1 + - - 1 + - 0 + - 0 + Rotation11: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 0 + - -1 + - 0 + - - 1 + - 0 + - 0 + Rotation14: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 1 + - 0 + - - 0 + - 0 + - -1 + Rotation15: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 0 + - 1 + - - 0 + - 1 + - 0 + Rotation17: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - -1 + - 0 + - - 0 + - 0 + - 1 + Rotation18: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 0 + - -1 + - - 0 + - -1 + - 0 + Rotation19: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - -1 + - 0 + - 0 + - - 0 + - 0 + - 1 + Rotation1b: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - -1 + - 0 + - 0 + - - 0 + - 1 + - 0 + Rotation1c: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - -1 + - 0 + - 0 + - - 0 + - 0 + - -1 + Rotation1e: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - -1 + - 0 + - 0 + - - 0 + - -1 + - 0 + Rotation1f: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 0 + - 0 + - -1 + - - -1 + - 0 + - 0 + Rotation20: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 0 + - 1 + - 0 + - - -1 + - 0 + - 0 + Rotation22: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 0 + - 0 + - 1 + - - -1 + - 0 + - 0 + Rotation23: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 0 + - -1 + - 0 + - - -1 + - 0 + - 0 + YetAnotherCFrameAttribute: + CFrame: + position: + - 1 + - 3.1333337 + - 0.808 + orientation: + - - -0.24184482 + - -0.9396926 + - -0.24184477 + - - 0.70710677 + - -0.00000003090862 + - -0.70710677 + - - 0.664463 + - -0.34202018 + - 0.664463 + SourceAssetId: + Int64: -1 + Tags: + Tags: [] + children: [] + diff --git a/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-cframe-attributes__roundtrip.snap b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-cframe-attributes__roundtrip.snap new file mode 100644 index 000000000..a5fa749e4 --- /dev/null +++ b/rbx_xml/src/tests/snapshots/rbx_xml__tests__folder-with-cframe-attributes__roundtrip.snap @@ -0,0 +1,416 @@ +--- +source: rbx_xml/src/tests/mod.rs +expression: "DomViewer::new().view_children(&roundtrip)" +--- +- referent: referent-0 + name: Folder + class: Folder + properties: + Attributes: + Attributes: + Rotation02: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 1 + - 0 + - - 0 + - 0 + - 1 + Rotation03: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 0 + - -1 + - - 0 + - 1 + - 0 + Rotation05: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - -1 + - 0 + - - 0 + - 0 + - -1 + Rotation06: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 1 + - 0 + - 0 + - - 0 + - 0 + - 1 + - - 0 + - -1 + - 0 + Rotation07: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 1 + - 0 + - 0 + - - 0 + - 0 + - -1 + Rotation09: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 1 + - 0 + - 0 + - - 0 + - 1 + - 0 + Rotation0a: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 1 + - 0 + - 0 + - - 0 + - 0 + - 1 + Rotation0c: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 1 + - 0 + - 0 + - - 0 + - -1 + - 0 + Rotation0d: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 0 + - 0 + - 1 + - - 1 + - 0 + - 0 + Rotation0e: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 0 + - 1 + - 0 + - - 1 + - 0 + - 0 + Rotation10: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 0 + - 0 + - -1 + - - 1 + - 0 + - 0 + Rotation11: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 0 + - -1 + - 0 + - - 1 + - 0 + - 0 + Rotation14: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 1 + - 0 + - - 0 + - 0 + - -1 + Rotation15: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 0 + - 1 + - - 0 + - 1 + - 0 + Rotation17: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - -1 + - 0 + - - 0 + - 0 + - 1 + Rotation18: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - -1 + - 0 + - 0 + - - 0 + - 0 + - -1 + - - 0 + - -1 + - 0 + Rotation19: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - -1 + - 0 + - 0 + - - 0 + - 0 + - 1 + Rotation1b: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - -1 + - 0 + - 0 + - - 0 + - 1 + - 0 + Rotation1c: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - -1 + - 0 + - 0 + - - 0 + - 0 + - -1 + Rotation1e: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - -1 + - 0 + - 0 + - - 0 + - -1 + - 0 + Rotation1f: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 1 + - 0 + - - 0 + - 0 + - -1 + - - -1 + - 0 + - 0 + Rotation20: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - 1 + - - 0 + - 1 + - 0 + - - -1 + - 0 + - 0 + Rotation22: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - -1 + - 0 + - - 0 + - 0 + - 1 + - - -1 + - 0 + - 0 + Rotation23: + CFrame: + position: + - 0 + - 0 + - 0 + orientation: + - - 0 + - 0 + - -1 + - - 0 + - -1 + - 0 + - - -1 + - 0 + - 0 + YetAnotherCFrameAttribute: + CFrame: + position: + - 1 + - 3.1333337 + - 0.808 + orientation: + - - -0.24184482 + - -0.9396926 + - -0.24184477 + - - 0.70710677 + - -0.00000003090862 + - -0.70710677 + - - 0.664463 + - -0.34202018 + - 0.664463 + SourceAssetId: + Int64: -1 + Tags: + Tags: [] + children: [] + diff --git a/test-files b/test-files index 52f2c1a68..54a4e83f2 160000 --- a/test-files +++ b/test-files @@ -1 +1 @@ -Subproject commit 52f2c1a686e7b67d996005eeddf63b97b170a741 +Subproject commit 54a4e83f2fec2372f5f4794a32355cb30c1827d6