rw-parser-ng 2.0.5 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -674
- package/README.md +88 -88
- package/lib/renderware/RwFile.js +3 -0
- package/lib/renderware/dff/DffParser.js +16 -2
- package/lib/utils/ByteStream.d.ts +1 -0
- package/lib/utils/ByteStream.js +4 -0
- package/package.json +10 -9
- package/src/index.ts +12 -12
- package/src/renderware/RwFile.ts +26 -22
- package/src/renderware/RwSections.ts +27 -27
- package/src/renderware/common/types.ts +58 -58
- package/src/renderware/dff/DffModelType.ts +4 -4
- package/src/renderware/dff/DffParser.ts +611 -596
- package/src/renderware/errors/RwParseError.ts +11 -11
- package/src/renderware/ifp/IfpData.ts +32 -32
- package/src/renderware/ifp/IfpParser.ts +202 -202
- package/src/renderware/txd/TxdParser.ts +234 -234
- package/src/renderware/utils/ImageDecoder.ts +570 -570
- package/src/renderware/utils/ImageFormatEnums.ts +27 -27
- package/src/renderware/utils/RwVersion.ts +28 -28
- package/src/utils/ByteStream.ts +80 -75
- package/tsconfig.json +66 -66
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export class RwParseError extends Error {
|
|
2
|
-
constructor(message?: string) {
|
|
3
|
-
super(message);
|
|
4
|
-
}
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export class RwParseStructureNotFoundError extends RwParseError {
|
|
8
|
-
constructor(structureName: string) {
|
|
9
|
-
super(`Structure ${structureName} not found.`);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
1
|
+
export class RwParseError extends Error {
|
|
2
|
+
constructor(message?: string) {
|
|
3
|
+
super(message);
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class RwParseStructureNotFoundError extends RwParseError {
|
|
8
|
+
constructor(structureName: string) {
|
|
9
|
+
super(`Structure ${structureName} not found.`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { RwQuaternion, RwVector3 } from "../common/types";
|
|
2
|
-
|
|
3
|
-
export enum IfpVersion {
|
|
4
|
-
ANP3,
|
|
5
|
-
ANPK,
|
|
6
|
-
UNSUPPORTED,
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface RwIfp {
|
|
10
|
-
version: IfpVersion,
|
|
11
|
-
name: string,
|
|
12
|
-
animations: RwIfpAnimation[],
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface RwIfpAnimation {
|
|
16
|
-
name: string,
|
|
17
|
-
bones: RwIfpBone[],
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface RwIfpBone {
|
|
21
|
-
name: string,
|
|
22
|
-
keyframeType: string,
|
|
23
|
-
useBoneId: boolean,
|
|
24
|
-
boneId: number,
|
|
25
|
-
keyframes: RwIfpKeyframe[],
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface RwIfpKeyframe {
|
|
29
|
-
time: number,
|
|
30
|
-
position: RwVector3,
|
|
31
|
-
rotation: RwQuaternion,
|
|
32
|
-
scale: RwVector3,
|
|
1
|
+
import { RwQuaternion, RwVector3 } from "../common/types";
|
|
2
|
+
|
|
3
|
+
export enum IfpVersion {
|
|
4
|
+
ANP3,
|
|
5
|
+
ANPK,
|
|
6
|
+
UNSUPPORTED,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface RwIfp {
|
|
10
|
+
version: IfpVersion,
|
|
11
|
+
name: string,
|
|
12
|
+
animations: RwIfpAnimation[],
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface RwIfpAnimation {
|
|
16
|
+
name: string,
|
|
17
|
+
bones: RwIfpBone[],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface RwIfpBone {
|
|
21
|
+
name: string,
|
|
22
|
+
keyframeType: string,
|
|
23
|
+
useBoneId: boolean,
|
|
24
|
+
boneId: number,
|
|
25
|
+
keyframes: RwIfpKeyframe[],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RwIfpKeyframe {
|
|
29
|
+
time: number,
|
|
30
|
+
position: RwVector3,
|
|
31
|
+
rotation: RwQuaternion,
|
|
32
|
+
scale: RwVector3,
|
|
33
33
|
}
|
|
@@ -1,203 +1,203 @@
|
|
|
1
|
-
import { RwFile } from '../RwFile';
|
|
2
|
-
import { IfpVersion, RwIfp, RwIfpAnimation, RwIfpBone, RwIfpKeyframe } from './IfpData';
|
|
3
|
-
|
|
4
|
-
export class IfpParser extends RwFile
|
|
5
|
-
{
|
|
6
|
-
constructor(buffer: Buffer) {
|
|
7
|
-
super(buffer);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
public parse(): RwIfp {
|
|
11
|
-
const fileSignature = this.readString(4);
|
|
12
|
-
this.setPosition(0);
|
|
13
|
-
|
|
14
|
-
let version: IfpVersion;
|
|
15
|
-
if (fileSignature === 'ANP3') {
|
|
16
|
-
version = IfpVersion.ANP3;
|
|
17
|
-
return this.readAnp3();
|
|
18
|
-
} else if (fileSignature === 'ANPK') {
|
|
19
|
-
version = IfpVersion.ANPK;
|
|
20
|
-
return this.readAnpk();
|
|
21
|
-
} else {
|
|
22
|
-
version = IfpVersion.UNSUPPORTED;
|
|
23
|
-
throw new Error('Unsupported IFP version');
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private readAnp3(): RwIfp {
|
|
28
|
-
this.skip(4); // ANP3
|
|
29
|
-
const size = this.readUint32();
|
|
30
|
-
const name = this.readString(24);
|
|
31
|
-
const animationsCount = this.readUint32();
|
|
32
|
-
const animations: RwIfpAnimation[] = [];
|
|
33
|
-
|
|
34
|
-
for (let i = 0; i < animationsCount; i++) {
|
|
35
|
-
animations.push(this.readAnp3Animation());
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
version: IfpVersion.ANP3,
|
|
40
|
-
name,
|
|
41
|
-
animations
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
private readAnp3Animation(): RwIfpAnimation {
|
|
46
|
-
const name = this.readString(24);
|
|
47
|
-
const bonesCount = this.readUint32();
|
|
48
|
-
this.skip(4); // keyframes_size
|
|
49
|
-
this.skip(4); // unk
|
|
50
|
-
const bones: RwIfpBone[] = [];
|
|
51
|
-
|
|
52
|
-
for (let i = 0; i < bonesCount; i++) {
|
|
53
|
-
bones.push(this.readAnp3Bone());
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return { name, bones };
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private readAnp3Bone(): RwIfpBone {
|
|
60
|
-
const name = this.readString(24);
|
|
61
|
-
const keyframeTypeNum = this.readUint32();
|
|
62
|
-
const keyframesCount = this.readUint32();
|
|
63
|
-
const keyframeType = keyframeTypeNum === 4 ? 'KRT0' : 'KR00';
|
|
64
|
-
const boneId = this.readInt32();
|
|
65
|
-
const keyframes: RwIfpKeyframe[] = [];
|
|
66
|
-
|
|
67
|
-
for (let i = 0; i < keyframesCount; i++) {
|
|
68
|
-
const qx = this.readInt16() / 4096.0;
|
|
69
|
-
const qy = this.readInt16() / 4096.0;
|
|
70
|
-
const qz = this.readInt16() / 4096.0;
|
|
71
|
-
const qw = this.readInt16() / 4096.0;
|
|
72
|
-
const time = this.readInt16();
|
|
73
|
-
|
|
74
|
-
let px = 0, py = 0, pz = 0;
|
|
75
|
-
if (keyframeType[2] === 'T') {
|
|
76
|
-
px = this.readInt16() / 1024.0;
|
|
77
|
-
py = this.readInt16() / 1024.0;
|
|
78
|
-
pz = this.readInt16() / 1024.0;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
keyframes.push({
|
|
82
|
-
time,
|
|
83
|
-
position: { x: px, y: py, z: pz },
|
|
84
|
-
rotation: { w: qw, x: qx, y: qy, z: qz },
|
|
85
|
-
scale: { x: 1, y: 1, z: 1 }
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
name,
|
|
91
|
-
keyframeType,
|
|
92
|
-
useBoneId: true,
|
|
93
|
-
boneId,
|
|
94
|
-
keyframes
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
private readAnpk(): RwIfp {
|
|
99
|
-
this.skip(4); // ANPK
|
|
100
|
-
const size = this.readUint32();
|
|
101
|
-
this.skip(4); // INFO
|
|
102
|
-
const infoLen = this.readUint32();
|
|
103
|
-
const animationsCount = this.readUint32();
|
|
104
|
-
const name = this.readString(infoLen - 4);
|
|
105
|
-
const nameAlignLen = (4 - infoLen % 4) % 4;
|
|
106
|
-
this.skip(nameAlignLen);
|
|
107
|
-
|
|
108
|
-
const animations: RwIfpAnimation[] = [];
|
|
109
|
-
for (let i = 0; i < animationsCount; i++) {
|
|
110
|
-
animations.push(this.readAnpkAnimation());
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
version: IfpVersion.ANPK,
|
|
115
|
-
name,
|
|
116
|
-
animations
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private readAnpkAnimation(): RwIfpAnimation {
|
|
121
|
-
this.skip(4); // NAME
|
|
122
|
-
const nameLen = this.readUint32();
|
|
123
|
-
const name = this.readString(nameLen);
|
|
124
|
-
this.skip((4 - nameLen % 4) % 4);
|
|
125
|
-
this.skip(4); // DGAN
|
|
126
|
-
this.skip(4); // animation_size
|
|
127
|
-
this.skip(4); // INFO
|
|
128
|
-
this.skip(4); // unk_size
|
|
129
|
-
const bonesCount = this.readUint32();
|
|
130
|
-
this.skip(4); // unk
|
|
131
|
-
|
|
132
|
-
const bones: RwIfpBone[] = [];
|
|
133
|
-
for (let i = 0; i < bonesCount; i++) {
|
|
134
|
-
bones.push(this.readAnpkBone());
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return { name, bones };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private readAnpkBone(): RwIfpBone {
|
|
141
|
-
this.skip(4); // CPAN
|
|
142
|
-
this.skip(4); // bone_len
|
|
143
|
-
this.skip(4); // ANIM
|
|
144
|
-
const animLen = this.readUint32();
|
|
145
|
-
const name = this.readString(28);
|
|
146
|
-
const keyframesCount = this.readUint32();
|
|
147
|
-
this.skip(8); // unk
|
|
148
|
-
|
|
149
|
-
let boneId = 0;
|
|
150
|
-
const useBoneId = animLen === 44;
|
|
151
|
-
if (useBoneId) {
|
|
152
|
-
boneId = this.readInt32();
|
|
153
|
-
} else {
|
|
154
|
-
this.skip(8); // sibling_x, sibling_y
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
let keyframeType = 'K000';
|
|
158
|
-
const keyframes: RwIfpKeyframe[] = [];
|
|
159
|
-
|
|
160
|
-
if (keyframesCount > 0) {
|
|
161
|
-
keyframeType = this.readString(4);
|
|
162
|
-
this.skip(4); // keyframes_len
|
|
163
|
-
|
|
164
|
-
for (let i = 0; i < keyframesCount; i++) {
|
|
165
|
-
const qx = this.readFloat();
|
|
166
|
-
const qy = this.readFloat();
|
|
167
|
-
const qz = this.readFloat();
|
|
168
|
-
const qw = this.readFloat();
|
|
169
|
-
|
|
170
|
-
let px = 0, py = 0, pz = 0;
|
|
171
|
-
if (keyframeType[2] === 'T') {
|
|
172
|
-
px = this.readFloat();
|
|
173
|
-
py = this.readFloat();
|
|
174
|
-
pz = this.readFloat();
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
let sx = 1, sy = 1, sz = 1;
|
|
178
|
-
if (keyframeType[3] === 'S') {
|
|
179
|
-
sx = this.readFloat();
|
|
180
|
-
sy = this.readFloat();
|
|
181
|
-
sz = this.readFloat();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const time = this.readFloat();
|
|
185
|
-
|
|
186
|
-
keyframes.push({
|
|
187
|
-
time,
|
|
188
|
-
position: { x: px, y: py, z: pz },
|
|
189
|
-
rotation: { w: qw, x: qx, y: qy, z: qz },
|
|
190
|
-
scale: { x: sx, y: sy, z: sz }
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return {
|
|
196
|
-
name,
|
|
197
|
-
keyframeType,
|
|
198
|
-
useBoneId,
|
|
199
|
-
boneId,
|
|
200
|
-
keyframes
|
|
201
|
-
};
|
|
202
|
-
}
|
|
1
|
+
import { RwFile } from '../RwFile';
|
|
2
|
+
import { IfpVersion, RwIfp, RwIfpAnimation, RwIfpBone, RwIfpKeyframe } from './IfpData';
|
|
3
|
+
|
|
4
|
+
export class IfpParser extends RwFile
|
|
5
|
+
{
|
|
6
|
+
constructor(buffer: Buffer) {
|
|
7
|
+
super(buffer);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public parse(): RwIfp {
|
|
11
|
+
const fileSignature = this.readString(4);
|
|
12
|
+
this.setPosition(0);
|
|
13
|
+
|
|
14
|
+
let version: IfpVersion;
|
|
15
|
+
if (fileSignature === 'ANP3') {
|
|
16
|
+
version = IfpVersion.ANP3;
|
|
17
|
+
return this.readAnp3();
|
|
18
|
+
} else if (fileSignature === 'ANPK') {
|
|
19
|
+
version = IfpVersion.ANPK;
|
|
20
|
+
return this.readAnpk();
|
|
21
|
+
} else {
|
|
22
|
+
version = IfpVersion.UNSUPPORTED;
|
|
23
|
+
throw new Error('Unsupported IFP version');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private readAnp3(): RwIfp {
|
|
28
|
+
this.skip(4); // ANP3
|
|
29
|
+
const size = this.readUint32();
|
|
30
|
+
const name = this.readString(24);
|
|
31
|
+
const animationsCount = this.readUint32();
|
|
32
|
+
const animations: RwIfpAnimation[] = [];
|
|
33
|
+
|
|
34
|
+
for (let i = 0; i < animationsCount; i++) {
|
|
35
|
+
animations.push(this.readAnp3Animation());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
version: IfpVersion.ANP3,
|
|
40
|
+
name,
|
|
41
|
+
animations
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private readAnp3Animation(): RwIfpAnimation {
|
|
46
|
+
const name = this.readString(24);
|
|
47
|
+
const bonesCount = this.readUint32();
|
|
48
|
+
this.skip(4); // keyframes_size
|
|
49
|
+
this.skip(4); // unk
|
|
50
|
+
const bones: RwIfpBone[] = [];
|
|
51
|
+
|
|
52
|
+
for (let i = 0; i < bonesCount; i++) {
|
|
53
|
+
bones.push(this.readAnp3Bone());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { name, bones };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private readAnp3Bone(): RwIfpBone {
|
|
60
|
+
const name = this.readString(24);
|
|
61
|
+
const keyframeTypeNum = this.readUint32();
|
|
62
|
+
const keyframesCount = this.readUint32();
|
|
63
|
+
const keyframeType = keyframeTypeNum === 4 ? 'KRT0' : 'KR00';
|
|
64
|
+
const boneId = this.readInt32();
|
|
65
|
+
const keyframes: RwIfpKeyframe[] = [];
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < keyframesCount; i++) {
|
|
68
|
+
const qx = this.readInt16() / 4096.0;
|
|
69
|
+
const qy = this.readInt16() / 4096.0;
|
|
70
|
+
const qz = this.readInt16() / 4096.0;
|
|
71
|
+
const qw = this.readInt16() / 4096.0;
|
|
72
|
+
const time = this.readInt16();
|
|
73
|
+
|
|
74
|
+
let px = 0, py = 0, pz = 0;
|
|
75
|
+
if (keyframeType[2] === 'T') {
|
|
76
|
+
px = this.readInt16() / 1024.0;
|
|
77
|
+
py = this.readInt16() / 1024.0;
|
|
78
|
+
pz = this.readInt16() / 1024.0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
keyframes.push({
|
|
82
|
+
time,
|
|
83
|
+
position: { x: px, y: py, z: pz },
|
|
84
|
+
rotation: { w: qw, x: qx, y: qy, z: qz },
|
|
85
|
+
scale: { x: 1, y: 1, z: 1 }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
name,
|
|
91
|
+
keyframeType,
|
|
92
|
+
useBoneId: true,
|
|
93
|
+
boneId,
|
|
94
|
+
keyframes
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private readAnpk(): RwIfp {
|
|
99
|
+
this.skip(4); // ANPK
|
|
100
|
+
const size = this.readUint32();
|
|
101
|
+
this.skip(4); // INFO
|
|
102
|
+
const infoLen = this.readUint32();
|
|
103
|
+
const animationsCount = this.readUint32();
|
|
104
|
+
const name = this.readString(infoLen - 4);
|
|
105
|
+
const nameAlignLen = (4 - infoLen % 4) % 4;
|
|
106
|
+
this.skip(nameAlignLen);
|
|
107
|
+
|
|
108
|
+
const animations: RwIfpAnimation[] = [];
|
|
109
|
+
for (let i = 0; i < animationsCount; i++) {
|
|
110
|
+
animations.push(this.readAnpkAnimation());
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
version: IfpVersion.ANPK,
|
|
115
|
+
name,
|
|
116
|
+
animations
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private readAnpkAnimation(): RwIfpAnimation {
|
|
121
|
+
this.skip(4); // NAME
|
|
122
|
+
const nameLen = this.readUint32();
|
|
123
|
+
const name = this.readString(nameLen);
|
|
124
|
+
this.skip((4 - nameLen % 4) % 4);
|
|
125
|
+
this.skip(4); // DGAN
|
|
126
|
+
this.skip(4); // animation_size
|
|
127
|
+
this.skip(4); // INFO
|
|
128
|
+
this.skip(4); // unk_size
|
|
129
|
+
const bonesCount = this.readUint32();
|
|
130
|
+
this.skip(4); // unk
|
|
131
|
+
|
|
132
|
+
const bones: RwIfpBone[] = [];
|
|
133
|
+
for (let i = 0; i < bonesCount; i++) {
|
|
134
|
+
bones.push(this.readAnpkBone());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { name, bones };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private readAnpkBone(): RwIfpBone {
|
|
141
|
+
this.skip(4); // CPAN
|
|
142
|
+
this.skip(4); // bone_len
|
|
143
|
+
this.skip(4); // ANIM
|
|
144
|
+
const animLen = this.readUint32();
|
|
145
|
+
const name = this.readString(28);
|
|
146
|
+
const keyframesCount = this.readUint32();
|
|
147
|
+
this.skip(8); // unk
|
|
148
|
+
|
|
149
|
+
let boneId = 0;
|
|
150
|
+
const useBoneId = animLen === 44;
|
|
151
|
+
if (useBoneId) {
|
|
152
|
+
boneId = this.readInt32();
|
|
153
|
+
} else {
|
|
154
|
+
this.skip(8); // sibling_x, sibling_y
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let keyframeType = 'K000';
|
|
158
|
+
const keyframes: RwIfpKeyframe[] = [];
|
|
159
|
+
|
|
160
|
+
if (keyframesCount > 0) {
|
|
161
|
+
keyframeType = this.readString(4);
|
|
162
|
+
this.skip(4); // keyframes_len
|
|
163
|
+
|
|
164
|
+
for (let i = 0; i < keyframesCount; i++) {
|
|
165
|
+
const qx = this.readFloat();
|
|
166
|
+
const qy = this.readFloat();
|
|
167
|
+
const qz = this.readFloat();
|
|
168
|
+
const qw = this.readFloat();
|
|
169
|
+
|
|
170
|
+
let px = 0, py = 0, pz = 0;
|
|
171
|
+
if (keyframeType[2] === 'T') {
|
|
172
|
+
px = this.readFloat();
|
|
173
|
+
py = this.readFloat();
|
|
174
|
+
pz = this.readFloat();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let sx = 1, sy = 1, sz = 1;
|
|
178
|
+
if (keyframeType[3] === 'S') {
|
|
179
|
+
sx = this.readFloat();
|
|
180
|
+
sy = this.readFloat();
|
|
181
|
+
sz = this.readFloat();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const time = this.readFloat();
|
|
185
|
+
|
|
186
|
+
keyframes.push({
|
|
187
|
+
time,
|
|
188
|
+
position: { x: px, y: py, z: pz },
|
|
189
|
+
rotation: { w: qw, x: qx, y: qy, z: qz },
|
|
190
|
+
scale: { x: sx, y: sy, z: sz }
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
name,
|
|
197
|
+
keyframeType,
|
|
198
|
+
useBoneId,
|
|
199
|
+
boneId,
|
|
200
|
+
keyframes
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
203
|
}
|