Skip to content

Commit c8fe19c

Browse files
committed
New interfaces
- Updated VRM.MaterialProperty to VRM0.MaterialProperty for consistency. - Removed VRMFileProtocol as it is no longer needed. - Migrated VRM1 structures to VRM0 equivalents in VRMMigration.swift. - Adjusted VRMLoader to support loading VRM0 thumbnails. - Modified Humanoid and SecondaryAnimation classes to use VRM0 types. - Updated tests to validate VRM0 functionality and migration from VRM1. - Removed deprecated VRM1SceneLoader and related methods. - Added new tests for VRM0 to ensure proper functionality and migration.
1 parent 2b5698d commit c8fe19c

19 files changed

+411
-412
lines changed

Sources/VRMKit/VRM/VRM.swift

Lines changed: 62 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,190 +1,96 @@
11
import Foundation
22

3-
public struct VRM: VRMFile {
4-
public let gltf: BinaryGLTF
5-
public let meta: Meta
6-
public let version: String?
7-
public let materialProperties: [MaterialProperty]
8-
public let humanoid: Humanoid
9-
public let blendShapeMaster: BlendShapeMaster
10-
public let firstPerson: FirstPerson
11-
public let secondaryAnimation: SecondaryAnimation
12-
13-
public let materialPropertyNameMap: [String: MaterialProperty]
3+
/// VRM data, supporting both VRM0 and VRM1 formats
4+
public enum VRM {
5+
case v0(VRM0)
6+
case v1(VRM1)
147

158
public init(data: Data) throws {
16-
gltf = try BinaryGLTF(data: data)
17-
9+
let gltf = try BinaryGLTF(data: data)
1810
let rawExtensions = try gltf.jsonData.extensions ??? .keyNotFound("extensions")
1911
let extensions = try rawExtensions.value as? [String: [String: Any]] ??? .dataInconsistent("extension type mismatch")
2012

21-
let decoder = DictionaryDecoder()
22-
2313
if extensions.keys.contains("VRMC_vrm") {
24-
// VRM 1.0 Support
25-
let vrm1 = try VRM1(data: data)
26-
27-
// Version
28-
version = vrm1.specVersion
29-
30-
// Meta
31-
meta = Meta(vrm1: vrm1.meta)
32-
33-
// Humanoid
34-
humanoid = Humanoid(vrm1: vrm1.humanoid)
35-
36-
// BlendShapeMaster
37-
blendShapeMaster = BlendShapeMaster(vrm1: vrm1.expressions, gltf: gltf)
38-
39-
// FirstPerson
40-
firstPerson = FirstPerson(vrm1: vrm1.firstPerson, lookAt: vrm1.lookAt)
41-
42-
// SecondaryAnimation (SpringBone)
43-
secondaryAnimation = SecondaryAnimation(vrm1: vrm1.springBone)
44-
45-
// MaterialProperties (MToon)
46-
materialProperties = try VRM.migrateMaterials(gltf: gltf, vrm1: vrm1)
47-
48-
materialPropertyNameMap = materialProperties.reduce(into: [:]) { $0[$1.name] = $1 }
49-
14+
self = .v1(try VRM1(data: data))
5015
} else {
51-
// VRM 0.x Support
52-
let vrm = try extensions["VRM"] ??? .keyNotFound("VRM")
53-
54-
meta = try decoder.decode(Meta.self, from: try vrm["meta"] ??? .keyNotFound("meta"))
55-
version = vrm["version"] as? String
56-
materialProperties = try decoder.decode([MaterialProperty].self, from: try vrm["materialProperties"] ??? .keyNotFound("materialProperties"))
57-
humanoid = try decoder.decode(Humanoid.self, from: try vrm["humanoid"] ??? .keyNotFound("humanoid"))
58-
blendShapeMaster = try decoder.decode(BlendShapeMaster.self, from: try vrm["blendShapeMaster"] ??? .keyNotFound("blendShapeMaster"))
59-
firstPerson = try decoder.decode(FirstPerson.self, from: try vrm["firstPerson"] ??? .keyNotFound("firstPerson"))
60-
secondaryAnimation = try decoder.decode(SecondaryAnimation.self, from: try vrm["secondaryAnimation"] ??? .keyNotFound("secondaryAnimation"))
61-
62-
materialPropertyNameMap = materialProperties.reduce(into: [:]) { $0[$1.name] = $1 }
16+
self = .v0(try VRM0(data: data))
6317
}
6418
}
65-
}
66-
67-
public extension VRM {
68-
struct Meta: Codable {
69-
public let title: String?
70-
public let author: String?
71-
public let contactInformation: String?
72-
public let reference: String?
73-
public let texture: Int?
74-
public let version: String?
7519

76-
public let allowedUserName: String?
77-
public let violentUssageName: String?
78-
public let sexualUssageName: String?
79-
public let commercialUssageName: String?
80-
public let otherPermissionUrl: String?
20+
// MARK: - Common Interface
8121

82-
public let licenseName: String?
83-
public let otherLicenseUrl: String?
22+
/// The underlying BinaryGLTF data
23+
public var gltf: BinaryGLTF {
24+
switch self {
25+
case .v0(let vrm): return vrm.gltf
26+
case .v1(let vrm): return vrm.gltf
27+
}
8428
}
8529

86-
struct MaterialProperty: Codable {
87-
public let name: String
88-
public let shader: String
89-
public let renderQueue: Int
90-
public let floatProperties: CodableAny
91-
public let keywordMap: [String: Bool]
92-
public let tagMap: [String: String]
93-
public let textureProperties: [String: Int]
94-
public let vectorProperties: CodableAny
30+
/// VRM spec version string
31+
public var specVersion: String {
32+
switch self {
33+
case .v0(let vrm): return vrm.version ?? "0.x"
34+
case .v1(let vrm): return vrm.specVersion
35+
}
9536
}
9637

97-
struct Humanoid: Codable {
98-
public let armStretch: Double
99-
public let feetSpacing: Double
100-
public let hasTranslationDoF: Bool
101-
public let legStretch: Double
102-
public let lowerArmTwist: Double
103-
public let lowerLegTwist: Double
104-
public let upperArmTwist: Double
105-
public let upperLegTwist: Double
106-
public let humanBones: [HumanBone]
38+
// MARK: - VRM0 Format interfaces (for current migration period)
39+
// In the future, these will be replaced with VRM1 native types
10740

108-
public struct HumanBone: Codable {
109-
public let bone: String
110-
public let node: Int
111-
public let useDefaultValues: Bool
41+
/// Meta information (VRM0 format)
42+
public var meta: VRM0.Meta {
43+
switch self {
44+
case .v0(let vrm): return vrm.meta
45+
case .v1(let vrm): return VRM0.Meta(vrm1: vrm.meta)
11246
}
11347
}
11448

115-
struct BlendShapeMaster: Codable {
116-
public let blendShapeGroups: [BlendShapeGroup]
117-
public struct BlendShapeGroup: Codable {
118-
public let binds: [Bind]?
119-
public let materialValues: [MaterialValueBind]?
120-
public let name: String
121-
public let presetName: String
122-
let _isBinary: Bool?
123-
public var isBinary: Bool { return _isBinary ?? false }
124-
private enum CodingKeys: String, CodingKey {
125-
case binds
126-
case materialValues
127-
case name
128-
case presetName
129-
case _isBinary = "isBinary"
130-
}
131-
public struct Bind: Codable {
132-
public let index: Int
133-
public let mesh: Int
134-
public let weight: Double
135-
}
136-
public struct MaterialValueBind: Codable {
137-
public let materialName: String
138-
public let propertyName: String
139-
public let targetValue: [Double]
140-
}
49+
/// Humanoid bone mapping (VRM0 format)
50+
public var humanoid: VRM0.Humanoid {
51+
switch self {
52+
case .v0(let vrm): return vrm.humanoid
53+
case .v1(let vrm): return VRM0.Humanoid(vrm1: vrm.humanoid)
14154
}
14255
}
14356

144-
struct FirstPerson: Codable {
145-
public let firstPersonBone: Int
146-
public let firstPersonBoneOffset: Vector3
147-
public let meshAnnotations: [MeshAnnotation]
148-
public let lookAtTypeName: LookAtType
149-
150-
public struct MeshAnnotation: Codable {
151-
public let firstPersonFlag: String
152-
public let mesh: Int
57+
/// Material properties (VRM0 format)
58+
public var materialProperties: [VRM0.MaterialProperty] {
59+
switch self {
60+
case .v0(let vrm): return vrm.materialProperties
61+
case .v1(let vrm): return VRM0(migratedFrom: vrm).materialProperties
15362
}
154-
public enum LookAtType: String, Codable {
155-
case none = "None"
156-
case bone = "Bone"
157-
case blendShape = "BlendShape"
63+
}
64+
65+
/// Material property name map (VRM0 format)
66+
public var materialPropertyNameMap: [String: VRM0.MaterialProperty] {
67+
switch self {
68+
case .v0(let vrm): return vrm.materialPropertyNameMap
69+
case .v1(let vrm): return VRM0(migratedFrom: vrm).materialPropertyNameMap
15870
}
15971
}
16072

161-
struct SecondaryAnimation: Codable {
162-
public let boneGroups: [BoneGroup]
163-
public let colliderGroups: [ColliderGroup]
164-
public struct BoneGroup: Codable {
165-
public let bones: [Int]
166-
public let center: Int
167-
public let colliderGroups: [Int]
168-
public let comment: String?
169-
public let dragForce: Double
170-
public let gravityDir: Vector3
171-
public let gravityPower: Double
172-
public let hitRadius: Double
173-
public let stiffiness: Double
73+
/// BlendShape master (VRM0 format)
74+
public var blendShapeMaster: VRM0.BlendShapeMaster {
75+
switch self {
76+
case .v0(let vrm): return vrm.blendShapeMaster
77+
case .v1(let vrm): return VRM0(migratedFrom: vrm).blendShapeMaster
17478
}
175-
176-
public struct ColliderGroup: Codable {
177-
public let node: Int
178-
public let colliders: [Collider]
179-
180-
public struct Collider: Codable {
181-
public let offset: Vector3
182-
public let radius: Double
183-
}
79+
}
80+
81+
/// First person settings (VRM0 format)
82+
public var firstPerson: VRM0.FirstPerson {
83+
switch self {
84+
case .v0(let vrm): return vrm.firstPerson
85+
case .v1(let vrm): return VRM0(migratedFrom: vrm).firstPerson
18486
}
18587
}
18688

187-
struct Vector3: Codable {
188-
public let x, y, z: Double
89+
/// Secondary animation / spring bones (VRM0 format)
90+
public var secondaryAnimation: VRM0.SecondaryAnimation {
91+
switch self {
92+
case .v0(let vrm): return vrm.secondaryAnimation
93+
case .v1(let vrm): return VRM0(migratedFrom: vrm).secondaryAnimation
94+
}
18995
}
19096
}

0 commit comments

Comments
 (0)