diff --git a/Package.swift b/Package.swift index 5e5f5ac..d1b4d2e 100644 --- a/Package.swift +++ b/Package.swift @@ -18,12 +18,12 @@ let package = Package( .testTarget( name: "VRMKitTests", dependencies: ["VRMKit"], - resources: [.copy("Assets/AliciaSolid.vrm")] + resources: [.copy("Assets/AliciaSolid.vrm"), .copy("Assets/Seed-san.vrm")] ), .testTarget( name: "VRMSceneKitTests", dependencies: ["VRMSceneKit"], - resources: [.copy("Assets/AliciaSolid.vrm")] + resources: [.copy("Assets/AliciaSolid.vrm"), .copy("Assets/Seed-san.vrm")] ), ] ) diff --git a/Sources/VRMKit/Extensions/GlobalFunction.swift b/Sources/VRMKit/Extensions/GlobalFunction.swift index 97740cc..97bb35e 100644 --- a/Sources/VRMKit/Extensions/GlobalFunction.swift +++ b/Sources/VRMKit/Extensions/GlobalFunction.swift @@ -27,3 +27,4 @@ func ???(lhs: T?, guard let value = lhs else { throw error() } return value } + diff --git a/Sources/VRMKit/VRM/Material.swift b/Sources/VRMKit/VRM/Material.swift index bb7b58b..3316c3a 100644 --- a/Sources/VRMKit/VRM/Material.swift +++ b/Sources/VRMKit/VRM/Material.swift @@ -13,7 +13,7 @@ import Foundation extension GLTF { public struct Material: Codable { public let name: String? - public let extensions: CodableAny? + public let extensions: MaterialExtensions? public let extras: CodableAny? public let pbrMetallicRoughness: PbrMetallicRoughness? public let normalTexture: NormalTextureInfo? @@ -102,5 +102,64 @@ extension GLTF { case MASK case BLEND } + + public struct MaterialExtensions: Codable { + public let materialsMToon: MaterialsMToon? + + private enum CodingKeys: String, CodingKey { + case materialsMToon = "VRMC_materials_mtoon" + } + + public struct MaterialsMToon: Codable { + public let specVersion: String + public let transparentWithZWrite: Bool? + public let renderQueueOffsetNumber: Int? + public let shadeColorFactor: [Double]? + public let shadeMultiplyTexture: MaterialsMToonTextureInfo? + public let shadingShiftFactor: Double? + public let shadingShiftTexture: MaterialsMToonShadingShiftTexture? + public let shadingToonyFactor: Double? + public let giEqualizationFactor: Double? + public let matcapFactor: [Double]? + public let matcapTexture: MaterialsMToonTextureInfo? + public let parametricRimColorFactor: [Double]? + public let rimMultiplyTexture: MaterialsMToonTextureInfo? + public let rimLightingMixFactor: Double? + public let parametricRimFresnelPowerFactor: Double? + public let parametricRimLiftFactor: Double? + public let outlineWidthMode: MaterialsMToonOutlineWidthMode? + public let outlineWidthFactor: Double? + public let outlineWidthMultiplyTexture: MaterialsMToonTextureInfo? + public let outlineColorFactor: [Double]? + public let outlineLightingMixFactor: Double? + public let uvAnimationMaskTexture: MaterialsMToonTextureInfo? + public let uvAnimationScrollXSpeedFactor: Double? + public let uvAnimationScrollYSpeedFactor: Double? + public let uvAnimationRotationSpeedFactor: Double? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct MaterialsMToonTextureInfo: Codable { + public let index: Int + public let texCoord: Int? + public let extensions: CodableAny? + public let extras: CodableAny? + } + + public struct MaterialsMToonShadingShiftTexture: Codable { + public let index: Int + public let texCoord: Int? + public let scale: Double? + public let extensions: CodableAny? + public let extras: CodableAny? + } + + public enum MaterialsMToonOutlineWidthMode: String, Codable { + case none + case worldCoordinates + case screenCoordinates + } + } + } } } diff --git a/Sources/VRMKit/VRM/Node.swift b/Sources/VRMKit/VRM/Node.swift index b557688..9c71bd7 100644 --- a/Sources/VRMKit/VRM/Node.swift +++ b/Sources/VRMKit/VRM/Node.swift @@ -34,7 +34,7 @@ extension GLTF { } public let weights: [Float]? public let name: String? - public let extensions: CodableAny? + public let extensions: NodeExtensions? public let extras: CodableAny? private enum CodingKeys: String, CodingKey { @@ -51,5 +51,81 @@ extension GLTF { case extensions case extras } + + public struct NodeExtensions: Codable { + public let nodeConstraint: NodeConstraint? + + private enum CodingKeys: String, CodingKey { + case nodeConstraint = "VRMC_node_constraint" + } + + public struct NodeConstraint: Codable { + public let specVersion: String + public let constraint: Constraint + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct Constraint: Codable { + public let roll: RollConstraint? + public let aim: AimConstraint? + public let rotation: RotationConstraint? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct RollConstraint: Codable { + public let source: Int + public let rollAxis: RollAxis + public let weight: Double? + public let extensions: CodableAny? + public let extras: CodableAny? + + public enum RollAxis: String, Codable { + case x + case y + case z + + private enum CodingKeys: String, CodingKey { + case x = "X" + case y = "Y" + case z = "Z" + } + } + } + + public struct AimConstraint: Codable { + public let source: Int + public let aimAxis: AimAxis + public let weight: Double? + public let extensions: CodableAny? + public let extras: CodableAny? + + public enum AimAxis: String, Codable { + case positiveX + case negativeX + case positiveY + case negativeY + case positiveZ + case negativeZ + + private enum CodingKeys: String, CodingKey { + case positiveX = "PositiveX" + case negativeX = "NegativeX" + case positiveY = "PositiveY" + case negativeY = "NegativeY" + case positiveZ = "PositiveZ" + case negativeZ = "NegativeZ" + } + } + } + + public struct RotationConstraint: Codable { + public let source: Int + public let weight: Double? + public let extensions: CodableAny? + public let extras: CodableAny? + } + } + } + } } } diff --git a/Sources/VRMKit/VRM/VRM.swift b/Sources/VRMKit/VRM/VRM.swift index 6284495..9a1cb54 100644 --- a/Sources/VRMKit/VRM/VRM.swift +++ b/Sources/VRMKit/VRM/VRM.swift @@ -8,7 +8,7 @@ import Foundation -public struct VRM { +public struct VRM: VRMFile { public let gltf: BinaryGLTF public let meta: Meta public let version: String? diff --git a/Sources/VRMKit/VRM/VRM1.swift b/Sources/VRMKit/VRM/VRM1.swift new file mode 100644 index 0000000..9cb9a6f --- /dev/null +++ b/Sources/VRMKit/VRM/VRM1.swift @@ -0,0 +1,346 @@ +// +// VRM1.swift +// VRMKit +// +// Created by Tatsuya Tanaka on 20180909. +// Copyright © 2018年 tattn. All rights reserved. +// + +import Foundation + +public struct VRM1: VRMFile { + public let gltf: BinaryGLTF + public let specVersion: String + public let meta: Meta + public let humanoid: Humanoid + public let firstPerson: FirstPerson? + public let lookAt: LookAt? + public let expressions: Expressions? + public let springBone: SpringBone? + public let extensions: CodableAny? + public let extras: CodableAny? + + public init(data: Data) throws { + gltf = try BinaryGLTF(data: data) + + let rawExtensions = try gltf.jsonData.extensions ??? .keyNotFound("extensions") + let extensions = try rawExtensions.value as? [String: [String: Any]] ??? .dataInconsistent("extension type mismatch") + let vrm = try extensions["VRMC_vrm"] ??? .keyNotFound("VRMC_vrm") + specVersion = vrm["specVersion"] as! String + + let decoder = DictionaryDecoder() + meta = try decoder.decode(Meta.self, from: try vrm["meta"] ??? .keyNotFound("meta")) + humanoid = try decoder.decode(Humanoid.self, from: try vrm["humanoid"] ??? .keyNotFound("humanoid")) + firstPerson = vrm.keys.contains("firstPerson") ? try decoder.decode(FirstPerson.self, from: vrm["firstPerson"] ?? "".data(using: .utf8)!) : nil + lookAt = vrm.keys.contains("lookAt") ? try decoder.decode(LookAt.self, from: vrm["lookAt"] ?? "".data(using: .utf8)!) : nil + expressions = vrm.keys.contains("expressions") ? try decoder.decode(Expressions.self, from: vrm["expressions"] ?? "".data(using: .utf8)!) : nil + springBone = extensions.keys.contains("VRMC_springBone") ? try decoder.decode(SpringBone.self, from: extensions["VRMC_springBone"] ?? "".data(using: .utf8)!) : nil + self.extensions = vrm.keys.contains("extensions") ? try decoder.decode(CodableAny.self, from: vrm["extensions"] ?? "".data(using: .utf8)!) : nil + extras = vrm.keys.contains("extras") ? try decoder.decode(CodableAny.self, from: vrm["extras"] ?? "".data(using: .utf8)!) : nil + } +} + +// VRMC_vrm +public extension VRM1 { + struct Meta: Codable { + public let name: String + public let version: String? + public let authors: [String] + public let copyrightInformation: String? + public let contactInformation: String? + public let references: [String]? + public let thirdPartyLicenses: String? + public let thumbnailImage: Int? + public let licenseUrl: String + public let avatarPermission: AvatarPermissionType? + public let allowExcessivelyViolentUsage: Bool? + public let allowExcessivelySexualUsage: Bool? + public let commercialUsage: CommercialUsageType? + public let allowPoliticalOrReligiousUsage: Bool? + public let allowAntisocialOrHateUsage: Bool? + public let creditNotation: CreditNotationType? + public let allowRedistribution: Bool? + public let modification: ModificationType? + public let otherLicenseUrl: String? + public let extensions: CodableAny? + public let extras: CodableAny? + + public enum AvatarPermissionType: String, Codable { + case onlyAuthor + case onlySeparatelyLicensedPerson + case everyone + } + + public enum CommercialUsageType: String, Codable { + case personalNonProfit + case personalProfit + case corporation + } + + public enum CreditNotationType: String, Codable { + case required + case unnecessary + } + + public enum ModificationType: String, Codable { + case prohibited + case allowModification + case allowModificationRedistribution + } + } + + struct Humanoid: Codable { + public let humanBones: HumanBones + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct HumanBones: Codable{ + public let hips: HumanBone + public let spine: HumanBone + public let chest: HumanBone? + public let upperChest: HumanBone? + public let neck: HumanBone? + public let head: HumanBone + public let leftEye: HumanBone? + public let rightEye: HumanBone? + public let jaw: HumanBone? + public let leftUpperLeg: HumanBone + public let leftLowerLeg: HumanBone + public let leftFoot:HumanBone + public let leftToes: HumanBone? + public let rightUpperLeg: HumanBone + public let rightLowerLeg: HumanBone + public let rightFoot: HumanBone + public let rightToes: HumanBone? + public let leftShoulder: HumanBone? + public let leftUpperArm: HumanBone + public let leftLowerArm: HumanBone + public let leftHand: HumanBone + public let rightShoulder: HumanBone? + public let rightUpperArm: HumanBone + public let rightLowerArm: HumanBone + public let rightHand: HumanBone + public let leftThumbMetacarpal: HumanBone? + public let leftThumbProximal: HumanBone? + public let leftThumbDistal: HumanBone? + public let leftIndexProximal: HumanBone? + public let leftIndexIntermediate: HumanBone? + public let leftIndexDistal: HumanBone? + public let leftMiddleProximal: HumanBone? + public let leftMiddleIntermediate: HumanBone? + public let leftMiddleDistal: HumanBone? + public let leftRingProximal: HumanBone? + public let leftRingIntermediate: HumanBone? + public let leftRingDistal: HumanBone? + public let leftLittleProximal: HumanBone? + public let leftLittleIntermediate: HumanBone? + public let leftLittleDistal: HumanBone? + public let rightThumbMetacarpal: HumanBone? + public let rightThumbProximal: HumanBone? + public let rightThumbDistal: HumanBone? + public let rightIndexProximal: HumanBone? + public let rightIndexIntermediate: HumanBone? + public let rightIndexDistal: HumanBone? + public let rightMiddleProximal: HumanBone? + public let rightMiddleIntermediate: HumanBone? + public let rightMiddleDistal: HumanBone? + public let rightRingProximal: HumanBone? + public let rightRingIntermediate: HumanBone? + public let rightRingDistal: HumanBone? + public let rightLittleProximal: HumanBone? + public let rightLittleIntermediate: HumanBone? + public let rightLittleDistal: HumanBone? + + public struct HumanBone: Codable { + public let node: Int + public let extensions: CodableAny? + public let extras: CodableAny? + } + } + } + + struct FirstPerson: Codable { + public let meshAnnotations: [MeshAnnotation] + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct MeshAnnotation: Codable { + public let type: FirstPersonType + public let node: Int + public let extensions: CodableAny? + public let extras: CodableAny? + } + + public enum FirstPersonType: String, Codable { + case auto + case both + case thirdPersonOnly + case firstPersonOnly + } + } + + struct LookAt: Codable { + public let offsetFromHeadBone:[Double] + public let type: LookAtType + public let rangeMapHorizontalInner: LookAtRangeMap + public let rangeMapHorizontalOuter: LookAtRangeMap + public let rangeMapVerticalDown: LookAtRangeMap + public let rangeMapVerticalUp: LookAtRangeMap + public let extensions: CodableAny? + public let extras: CodableAny? + + public enum LookAtType: String, Codable { + case bone + case expression + } + + public struct LookAtRangeMap: Codable { + public let inputMaxValue: Double + public let outputScale: Double + public let extensions: CodableAny? + public let extras: CodableAny? + } + } + + struct Expressions: Codable { + public let preset: Preset + public let custom: CodableAny? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct Preset: Codable { + public let happy: Expression + public let angry: Expression + public let sad: Expression + public let relaxed: Expression + public let surprised: Expression + public let aa: Expression + public let ih: Expression + public let ou: Expression + public let ee: Expression + public let oh: Expression + public let blink: Expression + public let blinkLeft: Expression + public let blinkRight: Expression + public let lookUp: Expression + public let lookDown: Expression + public let lookLeft: Expression + public let lookRight: Expression + public let neutral: Expression + } + + public struct Expression: Codable { + public let morphTargetBinds: [MorphTargetBind]? + public let materialColorBinds: [MaterialColorBind]? + public let textureTransformBinds: [TextureTransformBind]? + public let isBinary: Bool? + public let overrideBlink: ExpressionOverrideType? + public let overrideLookAt: ExpressionOverrideType? + public let overrideMouth: ExpressionOverrideType? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct MorphTargetBind: Codable { + public let node: Int + public let index: Int + public let weight: Double + public let extensions: CodableAny? + public let extras: CodableAny? + } + + public struct MaterialColorBind: Codable { + public let material: Int + public let type: MaterialColorType + public let targetValue: [Double] + public let extensions: CodableAny? + public let extras: CodableAny? + + public enum MaterialColorType: String, Codable { + case color + case emissionColor + case shadeColor + case matcapColor + case rimColor + case outlineColor + } + } + + public struct TextureTransformBind: Codable { + public let material: Int + public let scale: [Double]? + public let offset: [Double]? + public let extensions: CodableAny? + public let extras: CodableAny? + } + + public enum ExpressionOverrideType: String, Codable { + case none + case block + case blend + } + } + } +} + +// VRMC_springBone +extension VRM1 { + public struct SpringBone: Codable { + public let specVersion: String + public let colliders: [Collider]? + public let colliderGroups: [ColliderGroup]? + public let springs: [Spring]? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct Collider: Codable { + public let node: Int + public let shape: Shape + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct Shape: Codable { + public let sphere: ColliderShapeSphere? + public let capsule: ColliderShapeCapsule? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct ColliderShapeSphere: Codable { + public let offset: [Double] + public let radius: Double + } + + public struct ColliderShapeCapsule: Codable { + public let offset: [Double] + public let radius: Double + public let tail: [Double] + } + } + } + + public struct ColliderGroup: Codable { + public let colliders: [Int] + public let extensions: CodableAny? + public let extras: CodableAny? + } + + public struct Spring: Codable { + public let name: String? + public let joints: [Joint] + public let colliderGroups: [Int]? + public let center: Int? + public let extensions: CodableAny? + public let extras: CodableAny? + + public struct Joint: Codable { + public let node: Int + public let hitRadius: Double + public let stiffness: Double + public let gravityPower: Double + public let gravityDir: [Double] + public let dragForce: Double + public let extensions: CodableAny? + public let extras: CodableAny? + } + } + } +} diff --git a/Sources/VRMKit/VRM/VRMFileProtocol.swift b/Sources/VRMKit/VRM/VRMFileProtocol.swift new file mode 100644 index 0000000..880777c --- /dev/null +++ b/Sources/VRMKit/VRM/VRMFileProtocol.swift @@ -0,0 +1,14 @@ +// +// VRMFile.swift +// VRMKit +// +// Created by Tatsuya Tanaka on 20180911. +// Copyright © 2018年 tattn. All rights reserved. +// + +import Foundation + +public protocol VRMFile { + init(data: Data) throws +} + diff --git a/Sources/VRMKit/VRMLoader.swift b/Sources/VRMKit/VRMLoader.swift index 9646495..f67b6e7 100644 --- a/Sources/VRMKit/VRMLoader.swift +++ b/Sources/VRMKit/VRMLoader.swift @@ -27,4 +27,20 @@ open class VRMLoader { open func load(withData data: Data) throws -> VRM { return try VRM(data: data) } + + open func load(_ type: T.Type = T.self, named: String) throws -> T { + guard let url = Bundle.main.url(forResource: named, withExtension: nil) else { + throw URLError(.fileDoesNotExist) + } + return try load(type, withURL: url) + } + + open func load(_ type: T.Type = T.self, withURL url: URL) throws -> T { + let data = try Data(contentsOf: url) + return try load(type, withData: data) + } + + open func load(_ type: T.Type = T.self, withData data: Data) throws -> T { + return try T(data: data) + } } diff --git a/Tests/VRMKitTests/Assets/Seed-san.vrm b/Tests/VRMKitTests/Assets/Seed-san.vrm new file mode 100644 index 0000000..ff4223f Binary files /dev/null and b/Tests/VRMKitTests/Assets/Seed-san.vrm differ diff --git a/Tests/VRMKitTests/Resources.swift b/Tests/VRMKitTests/Resources.swift index ca69534..5251aad 100644 --- a/Tests/VRMKitTests/Resources.swift +++ b/Tests/VRMKitTests/Resources.swift @@ -10,12 +10,16 @@ import Foundation enum Resources { case aliciaSolid + case seedSan var data: Data { switch self { case .aliciaSolid: let url = Bundle.module.url(forResource: "AliciaSolid", withExtension: "vrm")! return try! Data(contentsOf: url) + case .seedSan: + let url = Bundle.module.url(forResource: "Seed-san", withExtension: "vrm")! + return try! Data(contentsOf: url) } } } diff --git a/Tests/VRMKitTests/VRM1Tests.swift b/Tests/VRMKitTests/VRM1Tests.swift new file mode 100644 index 0000000..370e0bd --- /dev/null +++ b/Tests/VRMKitTests/VRM1Tests.swift @@ -0,0 +1,1194 @@ +// +// VRM1Tests.swift +// VRMKitTests +// +// Created by Tatsuya Tanaka on 20180908. +// Copyright © 2018年 tattn. All rights reserved. +// + +import XCTest +import VRMKit + +class VRM1Tests: XCTestCase { + + let vrm = try! VRM1(data: Resources.seedSan.data) + + override func setUp() { + super.setUp() + } + + func testSpecVersion() { + XCTAssertEqual(vrm.specVersion, "1.0") + } + + + func testMeta() { + XCTAssertEqual(vrm.meta.name, "Seed-san") + XCTAssertEqual(vrm.meta.version, "1") + XCTAssertEqual(vrm.meta.authors, ["VirtualCast, Inc."]) + XCTAssertEqual(vrm.meta.copyrightInformation, "VirtualCast, Inc.") + XCTAssertEqual(vrm.meta.contactInformation, nil) + XCTAssertEqual(vrm.meta.references, nil) + XCTAssertEqual(vrm.meta.thirdPartyLicenses, nil) + XCTAssertEqual(vrm.meta.thumbnailImage, 14) + XCTAssertEqual(vrm.meta.licenseUrl, "https://vrm.dev/licenses/1.0/") + XCTAssertEqual(vrm.meta.avatarPermission, .everyone) + XCTAssertEqual(vrm.meta.allowExcessivelyViolentUsage, true) + XCTAssertEqual(vrm.meta.allowExcessivelySexualUsage, true) + XCTAssertEqual(vrm.meta.commercialUsage, .corporation) + XCTAssertEqual(vrm.meta.allowPoliticalOrReligiousUsage, true) + XCTAssertEqual(vrm.meta.allowAntisocialOrHateUsage, true) + XCTAssertEqual(vrm.meta.creditNotation, .required) + XCTAssertEqual(vrm.meta.allowRedistribution, true) + XCTAssertEqual(vrm.meta.modification, .allowModificationRedistribution) + XCTAssertEqual(vrm.meta.otherLicenseUrl, nil) + } + + func testFirstPerson() { + XCTAssertEqual(vrm.firstPerson?.meshAnnotations.count, 5) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[0].type, .thirdPersonOnly) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[0].node, 0) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[1].type, .thirdPersonOnly) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[1].node, 1) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[2].type, .thirdPersonOnly) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[2].node, 2) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[3].type, .both) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[3].node, 144) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[4].type, .both) + XCTAssertEqual(vrm.firstPerson?.meshAnnotations[4].node, 145) + } + + func testLookAt() { + XCTAssertEqual(vrm.lookAt?.offsetFromHeadBone.count, 3) + XCTAssertEqual(vrm.lookAt?.offsetFromHeadBone[0], 0) + XCTAssertEqual(vrm.lookAt?.offsetFromHeadBone[1], 0.07764859) + XCTAssertEqual(vrm.lookAt?.offsetFromHeadBone[2], 0.100730225) + XCTAssertEqual(vrm.lookAt?.type, .expression) + XCTAssertEqual(vrm.lookAt?.rangeMapHorizontalInner.inputMaxValue, 90) + XCTAssertEqual(vrm.lookAt?.rangeMapHorizontalInner.outputScale, 1) + XCTAssertEqual(vrm.lookAt?.rangeMapHorizontalOuter.inputMaxValue, 90) + XCTAssertEqual(vrm.lookAt?.rangeMapHorizontalOuter.outputScale, 1) + XCTAssertEqual(vrm.lookAt?.rangeMapVerticalDown.inputMaxValue, 90) + XCTAssertEqual(vrm.lookAt?.rangeMapVerticalDown.outputScale, 1) + XCTAssertEqual(vrm.lookAt?.rangeMapVerticalUp.inputMaxValue, 90) + XCTAssertEqual(vrm.lookAt?.rangeMapVerticalUp.outputScale, 1) + } + + func testHumanoid() { + XCTAssertEqual(vrm.humanoid.humanBones.hips.node, 3) + XCTAssertEqual(vrm.humanoid.humanBones.spine.node, 4) + XCTAssertEqual(vrm.humanoid.humanBones.chest?.node, 5) + XCTAssertEqual(vrm.humanoid.humanBones.upperChest?.node, nil) + XCTAssertEqual(vrm.humanoid.humanBones.neck?.node, 44) + XCTAssertEqual(vrm.humanoid.humanBones.head.node, 45) + XCTAssertEqual(vrm.humanoid.humanBones.leftEye?.node, nil) + XCTAssertEqual(vrm.humanoid.humanBones.rightEye?.node, nil) + XCTAssertEqual(vrm.humanoid.humanBones.jaw?.node, nil) + XCTAssertEqual(vrm.humanoid.humanBones.leftUpperLeg.node, 130) + XCTAssertEqual(vrm.humanoid.humanBones.leftLowerLeg.node, 131) + XCTAssertEqual(vrm.humanoid.humanBones.leftFoot.node, 132) + XCTAssertEqual(vrm.humanoid.humanBones.leftToes?.node, 134) + XCTAssertEqual(vrm.humanoid.humanBones.rightUpperLeg.node, 137) + XCTAssertEqual(vrm.humanoid.humanBones.rightLowerLeg.node, 138) + XCTAssertEqual(vrm.humanoid.humanBones.rightFoot.node, 139) + XCTAssertEqual(vrm.humanoid.humanBones.rightToes?.node, 141) + XCTAssertEqual(vrm.humanoid.humanBones.leftShoulder?.node, 82) + XCTAssertEqual(vrm.humanoid.humanBones.leftUpperArm.node, 83) + XCTAssertEqual(vrm.humanoid.humanBones.leftLowerArm.node, 84) + XCTAssertEqual(vrm.humanoid.humanBones.leftHand.node, 86) + XCTAssertEqual(vrm.humanoid.humanBones.rightShoulder?.node, 106) + XCTAssertEqual(vrm.humanoid.humanBones.rightUpperArm.node, 107) + XCTAssertEqual(vrm.humanoid.humanBones.rightLowerArm.node, 108) + XCTAssertEqual(vrm.humanoid.humanBones.rightHand.node, 110) + XCTAssertEqual(vrm.humanoid.humanBones.leftThumbMetacarpal?.node, 91) + XCTAssertEqual(vrm.humanoid.humanBones.leftThumbProximal?.node, 92) + XCTAssertEqual(vrm.humanoid.humanBones.leftThumbDistal?.node, 93) + XCTAssertEqual(vrm.humanoid.humanBones.leftIndexProximal?.node, 88) + XCTAssertEqual(vrm.humanoid.humanBones.leftIndexIntermediate?.node, 89) + XCTAssertEqual(vrm.humanoid.humanBones.leftIndexDistal?.node, 90) + XCTAssertEqual(vrm.humanoid.humanBones.leftMiddleProximal?.node, 95) + XCTAssertEqual(vrm.humanoid.humanBones.leftMiddleIntermediate?.node, 96) + XCTAssertEqual(vrm.humanoid.humanBones.leftMiddleDistal?.node, 97) + XCTAssertEqual(vrm.humanoid.humanBones.leftRingProximal?.node, 99) + XCTAssertEqual(vrm.humanoid.humanBones.leftRingIntermediate?.node, 100) + XCTAssertEqual(vrm.humanoid.humanBones.leftRingDistal?.node, 101) + XCTAssertEqual(vrm.humanoid.humanBones.leftLittleProximal?.node, 103) + XCTAssertEqual(vrm.humanoid.humanBones.leftLittleIntermediate?.node, 104) + XCTAssertEqual(vrm.humanoid.humanBones.leftLittleDistal?.node, 105) + XCTAssertEqual(vrm.humanoid.humanBones.rightThumbMetacarpal?.node, 115) + XCTAssertEqual(vrm.humanoid.humanBones.rightThumbProximal?.node, 116) + XCTAssertEqual(vrm.humanoid.humanBones.rightThumbDistal?.node, 117) + XCTAssertEqual(vrm.humanoid.humanBones.rightIndexProximal?.node, 112) + XCTAssertEqual(vrm.humanoid.humanBones.rightIndexIntermediate?.node, 113) + XCTAssertEqual(vrm.humanoid.humanBones.rightIndexDistal?.node, 114) + XCTAssertEqual(vrm.humanoid.humanBones.rightMiddleProximal?.node, 119) + XCTAssertEqual(vrm.humanoid.humanBones.rightMiddleIntermediate?.node, 120) + XCTAssertEqual(vrm.humanoid.humanBones.rightMiddleDistal?.node, 121) + XCTAssertEqual(vrm.humanoid.humanBones.rightRingProximal?.node, 123) + XCTAssertEqual(vrm.humanoid.humanBones.rightRingIntermediate?.node, 124) + XCTAssertEqual(vrm.humanoid.humanBones.rightRingDistal?.node, 125) + XCTAssertEqual(vrm.humanoid.humanBones.rightLittleProximal?.node, 127) + XCTAssertEqual(vrm.humanoid.humanBones.rightLittleIntermediate?.node, 128) + XCTAssertEqual(vrm.humanoid.humanBones.rightLittleDistal?.node, 129) + } + + func testExpressions() { + XCTAssertEqual(vrm.expressions?.preset.happy.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.happy.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.happy.morphTargetBinds?[0].index, 33) + XCTAssertEqual(vrm.expressions?.preset.happy.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.happy.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].material, 11) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].offset?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].offset?[0], 0.25) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].offset?[1], 0) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].scale?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].scale?[0], 1) + XCTAssertEqual(vrm.expressions?.preset.happy.textureTransformBinds?[0].scale?[1], 1) + XCTAssertEqual(vrm.expressions?.preset.happy.isBinary, true) + XCTAssertEqual(vrm.expressions?.preset.happy.overrideBlink, .blend) + XCTAssertEqual(vrm.expressions?.preset.happy.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.happy.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.angry.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.angry.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.angry.morphTargetBinds?[0].index, 34) + XCTAssertEqual(vrm.expressions?.preset.angry.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.angry.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].material, 11) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].offset?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].offset?[0], 0.5) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].offset?[1], 0) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].scale?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].scale?[0], 1) + XCTAssertEqual(vrm.expressions?.preset.angry.textureTransformBinds?[0].scale?[1], 1) + XCTAssertEqual(vrm.expressions?.preset.angry.isBinary, true) + XCTAssertEqual(vrm.expressions?.preset.angry.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.angry.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.angry.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.sad.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.sad.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.sad.morphTargetBinds?[0].index, 35) + XCTAssertEqual(vrm.expressions?.preset.sad.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.sad.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].material, 11) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].offset?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].offset?[0], 0.75) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].offset?[1], 0) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].scale?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].scale?[0], 1) + XCTAssertEqual(vrm.expressions?.preset.sad.textureTransformBinds?[0].scale?[1], 1) + XCTAssertEqual(vrm.expressions?.preset.sad.isBinary, true) + XCTAssertEqual(vrm.expressions?.preset.sad.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.sad.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.sad.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.relaxed.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.relaxed.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.relaxed.morphTargetBinds?[0].index, 36) + XCTAssertEqual(vrm.expressions?.preset.relaxed.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.relaxed.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].material, 11) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].offset?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].offset?[0], 0.5) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].offset?[1], 0.25) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].scale?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].scale?[0], 1) + XCTAssertEqual(vrm.expressions?.preset.relaxed.textureTransformBinds?[0].scale?[1], 1) + XCTAssertEqual(vrm.expressions?.preset.relaxed.isBinary, true) + XCTAssertEqual(vrm.expressions?.preset.relaxed.overrideBlink, .some(.block)) + XCTAssertEqual(vrm.expressions?.preset.relaxed.overrideLookAt, .some(.block)) + XCTAssertEqual(vrm.expressions?.preset.relaxed.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.surprised.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.surprised.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.surprised.morphTargetBinds?[0].index, 38) + XCTAssertEqual(vrm.expressions?.preset.surprised.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.surprised.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].material, 11) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].offset?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].offset?[0], 0) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].offset?[1], 0.25) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].scale?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].scale?[0], 1) + XCTAssertEqual(vrm.expressions?.preset.surprised.textureTransformBinds?[0].scale?[1], 1) + XCTAssertEqual(vrm.expressions?.preset.surprised.isBinary, true) + XCTAssertEqual(vrm.expressions?.preset.surprised.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.surprised.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.surprised.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.aa.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.aa.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.aa.morphTargetBinds?[0].index, 25) + XCTAssertEqual(vrm.expressions?.preset.aa.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.aa.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.aa.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.aa.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.aa.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.aa.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.aa.overrideMouth, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ih.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.ih.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.ih.morphTargetBinds?[0].index, 26) + XCTAssertEqual(vrm.expressions?.preset.ih.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.ih.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.ih.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.ih.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.ih.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ih.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ih.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.ou.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.ou.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.ou.morphTargetBinds?[0].index, 27) + XCTAssertEqual(vrm.expressions?.preset.ou.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.ou.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.ou.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.ou.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.ou.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ou.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ou.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.ee.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.ee.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.ee.morphTargetBinds?[0].index, 28) + XCTAssertEqual(vrm.expressions?.preset.ee.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.ee.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.ee.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.ee.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.ee.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ee.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.ee.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.oh.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.oh.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.oh.morphTargetBinds?[0].index, 29) + XCTAssertEqual(vrm.expressions?.preset.oh.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.oh.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.oh.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.oh.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.oh.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.oh.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.oh.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?.count, 2) + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?[0].index, 1) + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?[1].node, 2) + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?[1].index, 2) + XCTAssertEqual(vrm.expressions?.preset.blink.morphTargetBinds?[1].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.blink.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.blink.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.blink.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.blink.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.blink.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.blink.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.morphTargetBinds?[0].index, 1) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.blinkLeft.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.blinkRight.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.morphTargetBinds?[0].index, 2) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.blinkRight.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.lookUp.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.lookUp.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.lookUp.morphTargetBinds?[0].index, 39) + XCTAssertEqual(vrm.expressions?.preset.lookUp.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.lookUp.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookUp.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookUp.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.lookUp.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookUp.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookUp.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.lookDown.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.lookDown.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.lookDown.morphTargetBinds?[0].index, 40) + XCTAssertEqual(vrm.expressions?.preset.lookDown.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.lookDown.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookDown.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookDown.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.lookDown.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookDown.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookDown.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.lookLeft.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.morphTargetBinds?[0].index, 41) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookLeft.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.lookRight.morphTargetBinds?.count, 1) + XCTAssertEqual(vrm.expressions?.preset.lookRight.morphTargetBinds?[0].node, 2) + XCTAssertEqual(vrm.expressions?.preset.lookRight.morphTargetBinds?[0].index, 42) + XCTAssertEqual(vrm.expressions?.preset.lookRight.morphTargetBinds?[0].weight, 1) + XCTAssertEqual(vrm.expressions?.preset.lookRight.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookRight.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.lookRight.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.lookRight.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookRight.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.lookRight.overrideMouth, .some(.none)) + + XCTAssertEqual(vrm.expressions?.preset.neutral.morphTargetBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.neutral.materialColorBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.neutral.textureTransformBinds?.count, nil) + XCTAssertEqual(vrm.expressions?.preset.neutral.isBinary, false) + XCTAssertEqual(vrm.expressions?.preset.neutral.overrideBlink, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.neutral.overrideLookAt, .some(.none)) + XCTAssertEqual(vrm.expressions?.preset.neutral.overrideMouth, .some(.none)) + } + + func testSpringBone() { + // colliders + XCTAssertEqual(vrm.springBone?.specVersion, "1.0") + XCTAssertEqual(vrm.springBone?.colliders?.count, 8) + XCTAssertEqual(vrm.springBone?.colliders?[0].node, 4) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.offset[0], -0.04) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.offset[1], 0) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.offset[2], 0.02) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.radius, 0.088) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.tail[0], 0.04) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.tail[1], 0) + XCTAssertEqual(vrm.springBone?.colliders?[0].shape.capsule?.tail[2], 0.02) + + XCTAssertEqual(vrm.springBone?.colliders?[1].node, 5) + XCTAssertEqual(vrm.springBone?.colliders?[1].shape.sphere?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[1].shape.sphere?.offset[0], 0) + XCTAssertEqual(vrm.springBone?.colliders?[1].shape.sphere?.offset[1], 0.02) + XCTAssertEqual(vrm.springBone?.colliders?[1].shape.sphere?.offset[2], -0.07) + XCTAssertEqual(vrm.springBone?.colliders?[1].shape.sphere?.radius, 0.113) + + XCTAssertEqual(vrm.springBone?.colliders?[2].node, 5) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.offset[0], 0.065) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.offset[1], 0.14) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.offset[2], 0.01) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.radius, 0.083) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.tail[0], -0.065) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.tail[1], 0.14) + XCTAssertEqual(vrm.springBone?.colliders?[2].shape.capsule?.tail[2], 0.01) + + XCTAssertEqual(vrm.springBone?.colliders?[3].node, 5) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.offset[0], 0.04) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.offset[1], 0) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.offset[2], 0.02) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.radius, 0.083) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.tail[0], -0.04) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.tail[1], 0) + XCTAssertEqual(vrm.springBone?.colliders?[3].shape.capsule?.tail[2], 0.02) + + XCTAssertEqual(vrm.springBone?.colliders?[4].node, 130) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.offset[0], -0.004536999) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.offset[1], 7.566095e-9) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.offset[2], 0.0127928918) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.radius, 0.07) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.tail[0], -0.001991607) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.tail[1], 0.329534262) + XCTAssertEqual(vrm.springBone?.colliders?[4].shape.capsule?.tail[2], 0.009325488) + + XCTAssertEqual(vrm.springBone?.colliders?[5].node, 131) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.offset[0], 4.570225e-9) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.offset[1], -1.477034e-8) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.offset[2], 0.008859742) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.radius, 0.065) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.tail[0], 2.013798e-8) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.tail[1], 0.3535266) + XCTAssertEqual(vrm.springBone?.colliders?[5].shape.capsule?.tail[2], 0.008811156) + + XCTAssertEqual(vrm.springBone?.colliders?[6].node, 137) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.offset[0], 0.004536999) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.offset[1], 7.566095e-9) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.offset[2], 0.0127928918) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.radius, 0.07) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.tail[0], 0.001991607) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.tail[1], 0.329534262) + XCTAssertEqual(vrm.springBone?.colliders?[6].shape.capsule?.tail[2], 0.009325488) + + XCTAssertEqual(vrm.springBone?.colliders?[7].node, 138) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.offset.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.offset[0], -4.57022464e-9) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.offset[1], -1.477034e-8) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.offset[2], 0.008859742) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.radius, 0.065) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.tail.count, 3) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.tail[0], -2.013798e-8) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.tail[1], 0.3535266) + XCTAssertEqual(vrm.springBone?.colliders?[7].shape.capsule?.tail[2], 0.008811156) + + // colliderGroups + XCTAssertEqual(vrm.springBone?.colliderGroups?.count, 2) + XCTAssertEqual(vrm.springBone?.colliderGroups?[0].colliders.count, 4) + XCTAssertEqual(vrm.springBone?.colliderGroups?[0].colliders[0], 0) + XCTAssertEqual(vrm.springBone?.colliderGroups?[0].colliders[1], 1) + XCTAssertEqual(vrm.springBone?.colliderGroups?[0].colliders[2], 2) + XCTAssertEqual(vrm.springBone?.colliderGroups?[0].colliders[3], 3) + XCTAssertEqual(vrm.springBone?.colliderGroups?[1].colliders.count, 4) + XCTAssertEqual(vrm.springBone?.colliderGroups?[1].colliders[0], 6) + XCTAssertEqual(vrm.springBone?.colliderGroups?[1].colliders[1], 7) + XCTAssertEqual(vrm.springBone?.colliderGroups?[1].colliders[2], 4) + XCTAssertEqual(vrm.springBone?.colliderGroups?[1].colliders[3], 5) + + // springs + XCTAssertEqual(vrm.springBone?.springs?.count, 9) + XCTAssertEqual(vrm.springBone?.springs?[0].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].colliderGroups?.count, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].colliderGroups?[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints.count, 7) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].node, 75) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[0].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].node, 76) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[1].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].node, 77) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[2].stiffness, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].node, 78) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[3].stiffness, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].node, 79) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[4].stiffness, 2) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].node, 80) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[5].stiffness, 2) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].node, 81) + XCTAssertEqual(vrm.springBone?.springs?[0].joints[6].stiffness, 2) + XCTAssertEqual(vrm.springBone?.springs?[0].name, "TailHair") + + XCTAssertEqual(vrm.springBone?.springs?[1].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[1].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].node, 47) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].node, 48) + XCTAssertEqual(vrm.springBone?.springs?[1].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[1].name, "FrontHairA") + + XCTAssertEqual(vrm.springBone?.springs?[2].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[2].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].node, 50) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].node, 51) + XCTAssertEqual(vrm.springBone?.springs?[2].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[2].name, "FrontHairB") + + XCTAssertEqual(vrm.springBone?.springs?[3].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[3].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].node, 53) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].node, 54) + XCTAssertEqual(vrm.springBone?.springs?[3].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[3].name, "FrontHairC") + + XCTAssertEqual(vrm.springBone?.springs?[4].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[4].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].node, 56) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].node, 57) + XCTAssertEqual(vrm.springBone?.springs?[4].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[4].name, "FrontHairD") + + XCTAssertEqual(vrm.springBone?.springs?[5].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[5].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].node, 59) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].node, 60) + XCTAssertEqual(vrm.springBone?.springs?[5].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[5].name, "FrontHairE") + + XCTAssertEqual(vrm.springBone?.springs?[6].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[6].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].node, 62) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].node, 63) + XCTAssertEqual(vrm.springBone?.springs?[6].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[6].name, "FrontHairF") + + XCTAssertEqual(vrm.springBone?.springs?[7].center, 3) + XCTAssertEqual(vrm.springBone?.springs?[7].joints.count, 2) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].node, 65) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[0].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].hitRadius, 0.01) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].node, 66) + XCTAssertEqual(vrm.springBone?.springs?[7].joints[1].stiffness, 1.2) + XCTAssertEqual(vrm.springBone?.springs?[7].name, "FrontHairG") + + XCTAssertEqual(vrm.springBone?.springs?[8].colliderGroups?.count, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].colliderGroups?[0], 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints.count, 7) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].node, 37) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[0].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].node, 38) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[1].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].node, 39) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[2].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].node, 40) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[3].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].node, 41) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[4].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].hitRadius, 0.06) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].node, 42) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[5].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].dragForce, 1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].gravityDir.count, 3) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].gravityDir[0], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].gravityDir[1], -1) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].gravityDir[2], 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].gravityPower, 0) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].hitRadius, 0.02) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].node, 43) + XCTAssertEqual(vrm.springBone?.springs?[8].joints[6].stiffness, 4) + XCTAssertEqual(vrm.springBone?.springs?[8].name, "RoboWire") + } + + func testMaterialsMToon() { + let material0MToon = vrm.gltf.jsonData.materials?[0].extensions?.materialsMToon + XCTAssertEqual(material0MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material0MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material0MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material0MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material0MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material0MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material0MToon?.outlineColorFactor?[0], 0) + XCTAssertEqual(material0MToon?.outlineColorFactor?[1], 0) + XCTAssertEqual(material0MToon?.outlineColorFactor?[2], 0) + XCTAssertEqual(material0MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material0MToon?.outlineWidthFactor, 0.0005) + XCTAssertEqual(material0MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material0MToon?.outlineWidthMultiplyTexture?.index, 1) + XCTAssertEqual(material0MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material0MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material0MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material0MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material0MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material0MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material0MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material0MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material0MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material0MToon?.shadeColorFactor?[0], 0.301212043) + XCTAssertEqual(material0MToon?.shadeColorFactor?[1], 0.301212043) + XCTAssertEqual(material0MToon?.shadeColorFactor?[2], 0.301212043) + XCTAssertEqual(material0MToon?.shadeMultiplyTexture?.index, 0) + XCTAssertEqual(material0MToon?.shadingShiftFactor, -0.05) + XCTAssertEqual(material0MToon?.shadingToonyFactor, 0.95) + XCTAssertEqual(material0MToon?.specVersion, "1.0") + XCTAssertEqual(material0MToon?.transparentWithZWrite, false) + XCTAssertEqual(material0MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material0MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material0MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material1MToon = vrm.gltf.jsonData.materials?[1].extensions?.materialsMToon + XCTAssertEqual(material1MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material1MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material1MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material1MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material1MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material1MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material1MToon?.outlineColorFactor?[0], 0.151317075) + XCTAssertEqual(material1MToon?.outlineColorFactor?[1], 0.193065077) + XCTAssertEqual(material1MToon?.outlineColorFactor?[2], 0.222877234) + XCTAssertEqual(material1MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material1MToon?.outlineWidthFactor, 0.0015) + XCTAssertEqual(material1MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material1MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material1MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material1MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material1MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material1MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material1MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material1MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material1MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material1MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material1MToon?.shadeColorFactor?[0], 0.20541285) + XCTAssertEqual(material1MToon?.shadeColorFactor?[1], 0.20541285) + XCTAssertEqual(material1MToon?.shadeColorFactor?[2], 0.20541285) + XCTAssertEqual(material1MToon?.shadeMultiplyTexture?.index, 2) + XCTAssertEqual(material1MToon?.shadingShiftFactor, -0.1) + XCTAssertEqual(material1MToon?.shadingToonyFactor, 0.9) + XCTAssertEqual(material1MToon?.specVersion, "1.0") + XCTAssertEqual(material1MToon?.transparentWithZWrite, false) + XCTAssertEqual(material1MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material1MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material1MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material2MToon = vrm.gltf.jsonData.materials?[2].extensions?.materialsMToon + XCTAssertEqual(material2MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material2MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material2MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material2MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material2MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material2MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material2MToon?.outlineColorFactor?[0], 0.2411783) + XCTAssertEqual(material2MToon?.outlineColorFactor?[1], 0.181807414) + XCTAssertEqual(material2MToon?.outlineColorFactor?[2], 0.1557278) + XCTAssertEqual(material2MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material2MToon?.outlineWidthFactor, 0.0011) + XCTAssertEqual(material2MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material2MToon?.outlineWidthMultiplyTexture?.index, 6) + XCTAssertEqual(material2MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material2MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material2MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material2MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material2MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material2MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material2MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material2MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material2MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material2MToon?.shadeColorFactor?[0], 1) + XCTAssertEqual(material2MToon?.shadeColorFactor?[1], 0.613979936) + XCTAssertEqual(material2MToon?.shadeColorFactor?[2], 0.5079454) + XCTAssertEqual(material2MToon?.shadeMultiplyTexture?.index, 4) + XCTAssertEqual(material2MToon?.shadingShiftFactor, -0.2) + XCTAssertEqual(material2MToon?.shadingShiftTexture?.index, 5) + XCTAssertEqual(material2MToon?.shadingShiftTexture?.scale, 1) + XCTAssertEqual(material2MToon?.shadingToonyFactor, 0.8) + XCTAssertEqual(material2MToon?.specVersion, "1.0") + XCTAssertEqual(material2MToon?.transparentWithZWrite, false) + XCTAssertEqual(material2MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material2MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material2MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material3MToon = vrm.gltf.jsonData.materials?[3].extensions?.materialsMToon + XCTAssertEqual(material3MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material3MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material3MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material3MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material3MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material3MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material3MToon?.outlineColorFactor?[0], 0) + XCTAssertEqual(material3MToon?.outlineColorFactor?[1], 0) + XCTAssertEqual(material3MToon?.outlineColorFactor?[2], 0) + XCTAssertEqual(material3MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material3MToon?.outlineWidthFactor, 0.5) + XCTAssertEqual(material3MToon?.outlineWidthMode, .some(.none)) + XCTAssertEqual(material3MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material3MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material3MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material3MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material3MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material3MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material3MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material3MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material3MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material3MToon?.shadeColorFactor?[0], 0.4352691) + XCTAssertEqual(material3MToon?.shadeColorFactor?[1], 0.3970382) + XCTAssertEqual(material3MToon?.shadeColorFactor?[2], 0.500747442) + XCTAssertEqual(material3MToon?.shadeMultiplyTexture?.index, 7) + XCTAssertEqual(material3MToon?.shadingShiftFactor, -0.2) + XCTAssertEqual(material3MToon?.shadingToonyFactor, 0.8) + XCTAssertEqual(material3MToon?.specVersion, "1.0") + XCTAssertEqual(material3MToon?.transparentWithZWrite, false) + XCTAssertEqual(material3MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material3MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material3MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material4MToon = vrm.gltf.jsonData.materials?[4].extensions?.materialsMToon + XCTAssertEqual(material4MToon?.giEqualizationFactor, 0.5) + XCTAssertEqual(material4MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material4MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material4MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material4MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material4MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material4MToon?.outlineColorFactor?[0], 0) + XCTAssertEqual(material4MToon?.outlineColorFactor?[1], 0) + XCTAssertEqual(material4MToon?.outlineColorFactor?[2], 0) + XCTAssertEqual(material4MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material4MToon?.outlineWidthFactor, 0.5) + XCTAssertEqual(material4MToon?.outlineWidthMode, .some(.none)) + XCTAssertEqual(material4MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material4MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material4MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material4MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material4MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material4MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material4MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material4MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material4MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material4MToon?.shadeColorFactor?[0], 1) + XCTAssertEqual(material4MToon?.shadeColorFactor?[1], 1) + XCTAssertEqual(material4MToon?.shadeColorFactor?[2], 1) + XCTAssertEqual(material4MToon?.shadingShiftFactor, -0.2) + XCTAssertEqual(material4MToon?.shadingToonyFactor, 0.8) + XCTAssertEqual(material4MToon?.specVersion, "1.0") + XCTAssertEqual(material4MToon?.transparentWithZWrite, false) + XCTAssertEqual(material4MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material4MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material4MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material5MToon = vrm.gltf.jsonData.materials?[5].extensions?.materialsMToon + XCTAssertEqual(material5MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material5MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material5MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material5MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material5MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material5MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material5MToon?.outlineColorFactor?[0], 0) + XCTAssertEqual(material5MToon?.outlineColorFactor?[1], 0) + XCTAssertEqual(material5MToon?.outlineColorFactor?[2], 0) + XCTAssertEqual(material5MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material5MToon?.outlineWidthFactor, 0.0015) + XCTAssertEqual(material5MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material5MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material5MToon?.parametricRimColorFactor?[0], 0.07896994) + XCTAssertEqual(material5MToon?.parametricRimColorFactor?[1], 0.07896994) + XCTAssertEqual(material5MToon?.parametricRimColorFactor?[2], 0.07896994) + XCTAssertEqual(material5MToon?.parametricRimFresnelPowerFactor, 4.3) + XCTAssertEqual(material5MToon?.parametricRimLiftFactor, 0.182) + XCTAssertEqual(material5MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material5MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material5MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material5MToon?.shadeColorFactor?[0], 0.4352691) + XCTAssertEqual(material5MToon?.shadeColorFactor?[1], 0.3970382) + XCTAssertEqual(material5MToon?.shadeColorFactor?[2], 0.500747442) + XCTAssertEqual(material5MToon?.shadeMultiplyTexture?.index, 8) + XCTAssertEqual(material5MToon?.shadingShiftFactor, -0.1) + XCTAssertEqual(material5MToon?.shadingToonyFactor, 0.9) + XCTAssertEqual(material5MToon?.specVersion, "1.0") + XCTAssertEqual(material5MToon?.transparentWithZWrite, false) + XCTAssertEqual(material5MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material5MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material5MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material6MToon = vrm.gltf.jsonData.materials?[6].extensions?.materialsMToon + XCTAssertEqual(material6MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material6MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material6MToon?.matcapFactor?[0], 1) + XCTAssertEqual(material6MToon?.matcapFactor?[1], 1) + XCTAssertEqual(material6MToon?.matcapFactor?[2], 1) + XCTAssertEqual(material6MToon?.matcapTexture?.index, 9) + XCTAssertEqual(material6MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material6MToon?.outlineColorFactor?[0], 0.07896994) + XCTAssertEqual(material6MToon?.outlineColorFactor?[1], 0.07896994) + XCTAssertEqual(material6MToon?.outlineColorFactor?[2], 0.07896994) + XCTAssertEqual(material6MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material6MToon?.outlineWidthFactor, 0.002) + XCTAssertEqual(material6MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material6MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material6MToon?.parametricRimColorFactor?[0], 0.345616162) + XCTAssertEqual(material6MToon?.parametricRimColorFactor?[1], 0.345616162) + XCTAssertEqual(material6MToon?.parametricRimColorFactor?[2], 0.345616162) + XCTAssertEqual(material6MToon?.parametricRimFresnelPowerFactor, 3.2) + XCTAssertEqual(material6MToon?.parametricRimLiftFactor, 0.15) + XCTAssertEqual(material6MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material6MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material6MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material6MToon?.shadeColorFactor?[0], 0.342953056) + XCTAssertEqual(material6MToon?.shadeColorFactor?[1], 0.37243554) + XCTAssertEqual(material6MToon?.shadeColorFactor?[2], 0.432035774) + XCTAssertEqual(material6MToon?.shadeMultiplyTexture?.index, 8) + XCTAssertEqual(material6MToon?.shadingShiftFactor, -0.1) + XCTAssertEqual(material6MToon?.shadingToonyFactor, 0.9) + XCTAssertEqual(material6MToon?.specVersion, "1.0") + XCTAssertEqual(material6MToon?.transparentWithZWrite, false) + XCTAssertEqual(material6MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material6MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material6MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material7MToon = vrm.gltf.jsonData.materials?[7].extensions?.materialsMToon + XCTAssertNil(material7MToon) + + let material8MToon = vrm.gltf.jsonData.materials?[8].extensions?.materialsMToon + XCTAssertEqual(material8MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material8MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material8MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material8MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material8MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material8MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material8MToon?.outlineColorFactor?[0], 0.01850021) + XCTAssertEqual(material8MToon?.outlineColorFactor?[1], 0.0176419467) + XCTAssertEqual(material8MToon?.outlineColorFactor?[2], 0.0251868479) + XCTAssertEqual(material8MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material8MToon?.outlineWidthFactor, 0.001) + XCTAssertEqual(material8MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material8MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material8MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material8MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material8MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material8MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material8MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material8MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material8MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material8MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material8MToon?.shadeColorFactor?[0], 0.4352691) + XCTAssertEqual(material8MToon?.shadeColorFactor?[1], 0.3970382) + XCTAssertEqual(material8MToon?.shadeColorFactor?[2], 0.500747442) + XCTAssertEqual(material8MToon?.shadeMultiplyTexture?.index, 4) + XCTAssertEqual(material8MToon?.shadingShiftFactor, -0.2) + XCTAssertEqual(material8MToon?.shadingToonyFactor, 0.8) + XCTAssertEqual(material8MToon?.specVersion, "1.0") + XCTAssertEqual(material8MToon?.transparentWithZWrite, false) + XCTAssertEqual(material8MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material8MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material8MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material9MToon = vrm.gltf.jsonData.materials?[9].extensions?.materialsMToon + XCTAssertNil(material9MToon) + + let material10MToon = vrm.gltf.jsonData.materials?[10].extensions?.materialsMToon + XCTAssertEqual(material10MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material10MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material10MToon?.matcapFactor?[0], 1) + XCTAssertEqual(material10MToon?.matcapFactor?[1], 1) + XCTAssertEqual(material10MToon?.matcapFactor?[2], 1) + XCTAssertEqual(material10MToon?.matcapTexture?.index, 9) + XCTAssertEqual(material10MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material10MToon?.outlineColorFactor?[0], 0.009166719) + XCTAssertEqual(material10MToon?.outlineColorFactor?[1], 0.009166719) + XCTAssertEqual(material10MToon?.outlineColorFactor?[2], 0.009166719) + XCTAssertEqual(material10MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material10MToon?.outlineWidthFactor, 0.001) + XCTAssertEqual(material10MToon?.outlineWidthMode, .some(.worldCoordinates)) + XCTAssertEqual(material10MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material10MToon?.parametricRimColorFactor?[0], 0.432035774) + XCTAssertEqual(material10MToon?.parametricRimColorFactor?[1], 0.432035774) + XCTAssertEqual(material10MToon?.parametricRimColorFactor?[2], 0.432035774) + XCTAssertEqual(material10MToon?.parametricRimFresnelPowerFactor, 7.9) + XCTAssertEqual(material10MToon?.parametricRimLiftFactor, 0.153) + XCTAssertEqual(material10MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material10MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material10MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material10MToon?.shadeColorFactor?[0], 0.4352691) + XCTAssertEqual(material10MToon?.shadeColorFactor?[1], 0.3970382) + XCTAssertEqual(material10MToon?.shadeColorFactor?[2], 0.500747442) + XCTAssertEqual(material10MToon?.shadeMultiplyTexture?.index, 2) + XCTAssertEqual(material10MToon?.shadingShiftFactor, -0.1) + XCTAssertEqual(material10MToon?.shadingToonyFactor, 0.9) + XCTAssertEqual(material10MToon?.specVersion, "1.0") + XCTAssertEqual(material10MToon?.transparentWithZWrite, false) + XCTAssertEqual(material10MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material10MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material10MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material11MToon = vrm.gltf.jsonData.materials?[11].extensions?.materialsMToon + XCTAssertEqual(material11MToon?.giEqualizationFactor, 0.9) + XCTAssertEqual(material11MToon?.matcapFactor?.count, 3) + XCTAssertEqual(material11MToon?.matcapFactor?[0], 0) + XCTAssertEqual(material11MToon?.matcapFactor?[1], 0) + XCTAssertEqual(material11MToon?.matcapFactor?[2], 0) + XCTAssertEqual(material11MToon?.outlineColorFactor?.count, 3) + XCTAssertEqual(material11MToon?.outlineColorFactor?[0], 0) + XCTAssertEqual(material11MToon?.outlineColorFactor?[1], 0) + XCTAssertEqual(material11MToon?.outlineColorFactor?[2], 0) + XCTAssertEqual(material11MToon?.outlineLightingMixFactor, 1) + XCTAssertEqual(material11MToon?.outlineWidthFactor, 0.5) + XCTAssertEqual(material11MToon?.outlineWidthMode, .some(.none)) + XCTAssertEqual(material11MToon?.parametricRimColorFactor?.count, 3) + XCTAssertEqual(material11MToon?.parametricRimColorFactor?[0], 0) + XCTAssertEqual(material11MToon?.parametricRimColorFactor?[1], 0) + XCTAssertEqual(material11MToon?.parametricRimColorFactor?[2], 0) + XCTAssertEqual(material11MToon?.parametricRimFresnelPowerFactor, 1) + XCTAssertEqual(material11MToon?.parametricRimLiftFactor, 0) + XCTAssertEqual(material11MToon?.renderQueueOffsetNumber, 0) + XCTAssertEqual(material11MToon?.rimLightingMixFactor, 1) + XCTAssertEqual(material11MToon?.shadeColorFactor?.count, 3) + XCTAssertEqual(material11MToon?.shadeColorFactor?[0], 1) + XCTAssertEqual(material11MToon?.shadeColorFactor?[1], 1) + XCTAssertEqual(material11MToon?.shadeColorFactor?[2], 1) + XCTAssertEqual(material11MToon?.shadeMultiplyTexture?.index, 12) + XCTAssertEqual(material11MToon?.shadingShiftFactor, -0.1) + XCTAssertEqual(material11MToon?.shadingToonyFactor, 0.9) + XCTAssertEqual(material11MToon?.specVersion, "1.0") + XCTAssertEqual(material11MToon?.transparentWithZWrite, false) + XCTAssertEqual(material11MToon?.uvAnimationRotationSpeedFactor, 0) + XCTAssertEqual(material11MToon?.uvAnimationScrollXSpeedFactor, 0) + XCTAssertEqual(material11MToon?.uvAnimationScrollYSpeedFactor, 0) + + let material12MToon = vrm.gltf.jsonData.materials?[12].extensions?.materialsMToon + XCTAssertNil(material12MToon) + + let material13MToon = vrm.gltf.jsonData.materials?[13].extensions?.materialsMToon + XCTAssertNil(material13MToon) + + let material14MToon = vrm.gltf.jsonData.materials?[14].extensions?.materialsMToon + XCTAssertNil(material14MToon) + + let material15MToon = vrm.gltf.jsonData.materials?[15].extensions?.materialsMToon + XCTAssertNil(material15MToon) + + let material16MToon = vrm.gltf.jsonData.materials?[16].extensions?.materialsMToon + XCTAssertNil(material16MToon) + } + + func testNodeConstraint() { + XCTAssertEqual(vrm.gltf.jsonData.nodes?[14].extensions?.nodeConstraint?.constraint.rotation?.source, 82) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[14].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[14].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[15].extensions?.nodeConstraint?.constraint.rotation?.source, 83) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[15].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[15].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[16].extensions?.nodeConstraint?.constraint.rotation?.source, 84) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[16].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[16].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[17].extensions?.nodeConstraint?.constraint.rotation?.source, 86) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[17].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[17].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[18].extensions?.nodeConstraint?.constraint.rotation?.source, 87) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[18].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[18].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[19].extensions?.nodeConstraint?.constraint.rotation?.source, 88) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[19].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[19].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[20].extensions?.nodeConstraint?.constraint.rotation?.source, 89) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[20].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[20].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[21].extensions?.nodeConstraint?.constraint.rotation?.source, 90) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[21].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[21].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[22].extensions?.nodeConstraint?.constraint.rotation?.source, 91) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[22].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[22].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[23].extensions?.nodeConstraint?.constraint.rotation?.source, 92) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[23].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[23].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[24].extensions?.nodeConstraint?.constraint.rotation?.source, 93) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[24].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[24].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[25].extensions?.nodeConstraint?.constraint.rotation?.source, 94) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[25].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[25].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[26].extensions?.nodeConstraint?.constraint.rotation?.source, 95) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[26].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[26].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[27].extensions?.nodeConstraint?.constraint.rotation?.source, 96) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[27].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[27].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[28].extensions?.nodeConstraint?.constraint.rotation?.source, 97) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[28].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[28].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[29].extensions?.nodeConstraint?.constraint.rotation?.source, 98) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[29].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[29].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[30].extensions?.nodeConstraint?.constraint.rotation?.source, 99) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[30].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[30].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[31].extensions?.nodeConstraint?.constraint.rotation?.source, 100) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[31].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[31].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[32].extensions?.nodeConstraint?.constraint.rotation?.source, 101) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[32].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[32].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[33].extensions?.nodeConstraint?.constraint.rotation?.source, 102) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[33].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[33].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[34].extensions?.nodeConstraint?.constraint.rotation?.source, 103) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[34].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[34].extensions?.nodeConstraint?.specVersion, "1.0") + XCTAssertEqual(vrm.gltf.jsonData.nodes?[35].extensions?.nodeConstraint?.constraint.rotation?.source, 104) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[35].extensions?.nodeConstraint?.constraint.rotation?.weight, 1) + XCTAssertEqual(vrm.gltf.jsonData.nodes?[35].extensions?.nodeConstraint?.specVersion, "1.0") + } +} diff --git a/Tests/VRMKitTests/VRMKitTests.swift b/Tests/VRMKitTests/VRMTests.swift similarity index 100% rename from Tests/VRMKitTests/VRMKitTests.swift rename to Tests/VRMKitTests/VRMTests.swift diff --git a/Tests/VRMSceneKitTests/Assets/Seed-san.vrm b/Tests/VRMSceneKitTests/Assets/Seed-san.vrm new file mode 120000 index 0000000..79944cf --- /dev/null +++ b/Tests/VRMSceneKitTests/Assets/Seed-san.vrm @@ -0,0 +1 @@ +../../VRMKitTests/Assets/Seed-san.vrm \ No newline at end of file