@zeewain/3d-avatar-sdk 1.2.0 → 1.2.1
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/README.md +3 -1
- package/dist/assets/Build/webgl.data.unityweb +0 -0
- package/dist/assets/Build/webgl.framework.js.unityweb +0 -0
- package/dist/assets/Build/webgl.wasm.unityweb +0 -0
- package/dist/index.d.ts +127 -123
- package/dist/index.es5.js +29 -24
- package/dist/index.es5.umd.js +29 -24
- package/dist/index.esm.js +31 -27
- package/dist/index.umd.cjs +31 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -441,10 +441,12 @@ interface IAvatarSDKConfig {
|
|
|
441
441
|
token?: string; // 用户认证令牌
|
|
442
442
|
env?: 'dev' | 'test' | 'prod' | 'custom'; // 运行环境,默认'prod'
|
|
443
443
|
apiUrl?: string; // 自定义API地址(env='custom'时需要)
|
|
444
|
+
assetsUrl?:string; // 自定义资源文件地址(env='custom'时有效)
|
|
444
445
|
resourcesUrl?: string; // AB资源文件地址
|
|
445
446
|
idleMotionList?:string[]; // 待机动作编码列表,随机播放(排重方式),可选
|
|
446
447
|
// 回调函数
|
|
447
|
-
onProgress?: (progress: number) => void; //
|
|
448
|
+
onProgress?: (progress: number) => void; // 加载进度回调,可选
|
|
449
|
+
broadcastCallbacks?:IBroadcastCallbacks; // 播报回调函数,可选
|
|
448
450
|
}
|
|
449
451
|
```
|
|
450
452
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.d.ts
CHANGED
|
@@ -27,40 +27,6 @@ interface IUnityInstance {
|
|
|
27
27
|
SetFullscreen?(fullscreen: boolean): void;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* @fileoverview SDK配置接口定义
|
|
32
|
-
* @description 定义SDK实例初始化所需的配置参数
|
|
33
|
-
*/
|
|
34
|
-
/**
|
|
35
|
-
* SDK配置接口
|
|
36
|
-
* @interface IAvatarSDKConfig
|
|
37
|
-
* @description 定义SDK实例初始化所需的配置参数
|
|
38
|
-
*/
|
|
39
|
-
interface IAvatarSDKConfig {
|
|
40
|
-
/** 全局用户认证令牌 */
|
|
41
|
-
token?: string;
|
|
42
|
-
/** 运行环境 */
|
|
43
|
-
env?: 'dev' | 'test' | 'prod' | 'custom';
|
|
44
|
-
/** api接口地址,仅当env为custom时有效 */
|
|
45
|
-
apiUrl?: string;
|
|
46
|
-
/** AB资源文件地址 */
|
|
47
|
-
resourcesUrl?: string;
|
|
48
|
-
/** Unity加载器脚本URL */
|
|
49
|
-
loaderUrl: string;
|
|
50
|
-
/** Unity数据文件URL */
|
|
51
|
-
dataUrl: string;
|
|
52
|
-
/** Unity框架文件URL */
|
|
53
|
-
frameworkUrl: string;
|
|
54
|
-
/** Unity代码文件URL */
|
|
55
|
-
codeUrl: string;
|
|
56
|
-
/** 容器DOM元素ID,可选,默认为'unity-container' */
|
|
57
|
-
containerId?: string;
|
|
58
|
-
/** 待机动作编码列表,随机播放(排重方式)可选 */
|
|
59
|
-
idleMotionList?: string[];
|
|
60
|
-
/** 3D渲染引擎加载进度回调函数,可选 */
|
|
61
|
-
onProgress?: (progress: number) => void;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
30
|
/**
|
|
65
31
|
* @fileoverview Unity服务基础类型定义
|
|
66
32
|
* @description 定义Unity服务的通用接口和类型,为所有Unity服务提供统一的基础类型
|
|
@@ -175,94 +141,6 @@ interface IUnityLogger {
|
|
|
175
141
|
error(message: string, error?: Error, data?: any): void;
|
|
176
142
|
}
|
|
177
143
|
|
|
178
|
-
/**
|
|
179
|
-
* @fileoverview Avatar API接口定义
|
|
180
|
-
* @description 定义数字人控制API的核心接口、类型和枚举
|
|
181
|
-
*/
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Avatar操作类型枚举
|
|
185
|
-
* @enum {string}
|
|
186
|
-
* @description 定义Avatar服务支持的操作类型
|
|
187
|
-
*/
|
|
188
|
-
declare enum AvatarOperationType {
|
|
189
|
-
INITIALIZE_AVATAR = "initializeAvatar",
|
|
190
|
-
PLAY_MOTION = "playMotion",
|
|
191
|
-
GET_CURRENT_MOTION = "getCurrentMotion",
|
|
192
|
-
UNLOAD_AVATAR = "unloadAvatar",
|
|
193
|
-
SET_CAMERA = "setCamera"
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Avatar摄像机类型枚举
|
|
197
|
-
* @enum {string}
|
|
198
|
-
* @description 定义Avatar支持的摄像机类型
|
|
199
|
-
*/
|
|
200
|
-
declare enum AvatarCameraType {
|
|
201
|
-
WHOLE = "whole",
|
|
202
|
-
HALF = "half",
|
|
203
|
-
FACE = "face"
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Avatar回调响应接口
|
|
207
|
-
* @interface IAvatarCallbackResponse
|
|
208
|
-
* @extends {IUnityCallbackResponse}
|
|
209
|
-
* @description 定义Avatar操作的回调响应格式,扩展基础响应接口
|
|
210
|
-
*/
|
|
211
|
-
interface IAvatarCallbackResponse extends IUnityCallbackResponse {
|
|
212
|
-
data?: {
|
|
213
|
-
/** 动作ID,可选 */
|
|
214
|
-
motionId?: string;
|
|
215
|
-
/** 动作剩余时间,可选 */
|
|
216
|
-
motionRemainingTime?: number;
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Avatar API接口
|
|
221
|
-
* @interface IAvatarAPI
|
|
222
|
-
* @description 定义数字人控制API的核心接口,包含数字人初始化、动作控制、摄像机设置等功能
|
|
223
|
-
*/
|
|
224
|
-
interface IAvatarAPI {
|
|
225
|
-
/**
|
|
226
|
-
* 初始化数字人
|
|
227
|
-
* @param avatarCode - 数字人编码
|
|
228
|
-
* @param cameraType - 摄像机类型,默认为'whole'
|
|
229
|
-
* @returns Promise<IAvatarCallbackResponse> 初始化操作的Promise
|
|
230
|
-
*/
|
|
231
|
-
initializeAvatar(avatarCode: string, cameraType?: AvatarCameraType): Promise<IAvatarCallbackResponse>;
|
|
232
|
-
/**
|
|
233
|
-
* 播放数字人动作
|
|
234
|
-
* @param clipCode - 动作编码
|
|
235
|
-
* @returns Promise<IAvatarCallbackResponse> 播放操作的Promise
|
|
236
|
-
*/
|
|
237
|
-
playMotion(clipCode: string): Promise<IAvatarCallbackResponse>;
|
|
238
|
-
/**
|
|
239
|
-
* 获取当前播放的动作信息
|
|
240
|
-
* @param getRemainingTime - 是否获取剩余时间
|
|
241
|
-
* @returns Promise<IAvatarCallbackResponse> 获取操作的Promise
|
|
242
|
-
*/
|
|
243
|
-
getCurrentMotion(getRemainingTime: boolean): Promise<IAvatarCallbackResponse>;
|
|
244
|
-
/**
|
|
245
|
-
* 卸载数字人
|
|
246
|
-
* @returns Promise<IAvatarCallbackResponse> 卸载操作的Promise
|
|
247
|
-
*/
|
|
248
|
-
unloadAvatar(): Promise<IAvatarCallbackResponse>;
|
|
249
|
-
/**
|
|
250
|
-
* 设置摄像机类型
|
|
251
|
-
* @param cameraType - 摄像机类型
|
|
252
|
-
* @returns Promise<IAvatarCallbackResponse> 设置操作的Promise
|
|
253
|
-
*/
|
|
254
|
-
setCamera(cameraType: AvatarCameraType): Promise<IAvatarCallbackResponse>;
|
|
255
|
-
/**
|
|
256
|
-
* 批量执行Avatar操作
|
|
257
|
-
* @param operations - 操作数组
|
|
258
|
-
* @returns Promise<IAvatarCallbackResponse[]> 返回所有操作的结果
|
|
259
|
-
*/
|
|
260
|
-
batchExecute(operations: Array<{
|
|
261
|
-
method: keyof IAvatarAPI;
|
|
262
|
-
params: any[];
|
|
263
|
-
}>): Promise<IAvatarCallbackResponse[]>;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
144
|
/**
|
|
267
145
|
* @fileoverview 流式播报服务接口定义
|
|
268
146
|
* @description 定义流式播报服务相关的类型、接口和枚举
|
|
@@ -436,6 +314,133 @@ interface IBroadcastAPI {
|
|
|
436
314
|
destroy(): void;
|
|
437
315
|
}
|
|
438
316
|
|
|
317
|
+
/**
|
|
318
|
+
* @fileoverview SDK配置接口定义
|
|
319
|
+
* @description 定义SDK实例初始化所需的配置参数
|
|
320
|
+
*/
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* SDK配置接口
|
|
324
|
+
* @interface IAvatarSDKConfig
|
|
325
|
+
* @description 定义SDK实例初始化所需的配置参数
|
|
326
|
+
*/
|
|
327
|
+
interface IAvatarSDKConfig {
|
|
328
|
+
/** 全局用户认证令牌 */
|
|
329
|
+
token?: string;
|
|
330
|
+
/** 运行环境 */
|
|
331
|
+
env?: 'dev' | 'test' | 'prod' | 'custom';
|
|
332
|
+
/** api接口地址,仅当env为custom时有效 */
|
|
333
|
+
apiUrl?: string;
|
|
334
|
+
/** 资源文件地址,仅当env为custom时有效 */
|
|
335
|
+
assetsUrl?: string;
|
|
336
|
+
/** AB资源文件地址 */
|
|
337
|
+
resourcesUrl?: string;
|
|
338
|
+
/** Unity加载器脚本URL */
|
|
339
|
+
loaderUrl: string;
|
|
340
|
+
/** Unity数据文件URL */
|
|
341
|
+
dataUrl: string;
|
|
342
|
+
/** Unity框架文件URL */
|
|
343
|
+
frameworkUrl: string;
|
|
344
|
+
/** Unity代码文件URL */
|
|
345
|
+
codeUrl: string;
|
|
346
|
+
/** 容器DOM元素ID,可选,默认为'unity-container' */
|
|
347
|
+
containerId?: string;
|
|
348
|
+
/** 待机动作编码列表,随机播放(排重方式)可选 */
|
|
349
|
+
idleMotionList?: string[];
|
|
350
|
+
/** 3D渲染引擎加载进度回调函数,可选 */
|
|
351
|
+
onProgress?: (progress: number) => void;
|
|
352
|
+
/** 播报回调函数,可选 */
|
|
353
|
+
broadcastCallbacks?: IBroadcastCallbacks;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @fileoverview Avatar API接口定义
|
|
358
|
+
* @description 定义数字人控制API的核心接口、类型和枚举
|
|
359
|
+
*/
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Avatar操作类型枚举
|
|
363
|
+
* @enum {string}
|
|
364
|
+
* @description 定义Avatar服务支持的操作类型
|
|
365
|
+
*/
|
|
366
|
+
declare enum AvatarOperationType {
|
|
367
|
+
INITIALIZE_AVATAR = "initializeAvatar",
|
|
368
|
+
PLAY_MOTION = "playMotion",
|
|
369
|
+
GET_CURRENT_MOTION = "getCurrentMotion",
|
|
370
|
+
UNLOAD_AVATAR = "unloadAvatar",
|
|
371
|
+
SET_CAMERA = "setCamera"
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Avatar摄像机类型枚举
|
|
375
|
+
* @enum {string}
|
|
376
|
+
* @description 定义Avatar支持的摄像机类型
|
|
377
|
+
*/
|
|
378
|
+
declare enum AvatarCameraType {
|
|
379
|
+
WHOLE = "whole",
|
|
380
|
+
HALF = "half",
|
|
381
|
+
FACE = "face"
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Avatar回调响应接口
|
|
385
|
+
* @interface IAvatarCallbackResponse
|
|
386
|
+
* @extends {IUnityCallbackResponse}
|
|
387
|
+
* @description 定义Avatar操作的回调响应格式,扩展基础响应接口
|
|
388
|
+
*/
|
|
389
|
+
interface IAvatarCallbackResponse extends IUnityCallbackResponse {
|
|
390
|
+
data?: {
|
|
391
|
+
/** 动作ID,可选 */
|
|
392
|
+
motionId?: string;
|
|
393
|
+
/** 动作剩余时间,可选 */
|
|
394
|
+
motionRemainingTime?: number;
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Avatar API接口
|
|
399
|
+
* @interface IAvatarAPI
|
|
400
|
+
* @description 定义数字人控制API的核心接口,包含数字人初始化、动作控制、摄像机设置等功能
|
|
401
|
+
*/
|
|
402
|
+
interface IAvatarAPI {
|
|
403
|
+
/**
|
|
404
|
+
* 初始化数字人
|
|
405
|
+
* @param avatarCode - 数字人编码
|
|
406
|
+
* @param cameraType - 摄像机类型,默认为'whole'
|
|
407
|
+
* @returns Promise<IAvatarCallbackResponse> 初始化操作的Promise
|
|
408
|
+
*/
|
|
409
|
+
initializeAvatar(avatarCode: string, cameraType?: AvatarCameraType): Promise<IAvatarCallbackResponse>;
|
|
410
|
+
/**
|
|
411
|
+
* 播放数字人动作
|
|
412
|
+
* @param clipCode - 动作编码
|
|
413
|
+
* @returns Promise<IAvatarCallbackResponse> 播放操作的Promise
|
|
414
|
+
*/
|
|
415
|
+
playMotion(clipCode: string): Promise<IAvatarCallbackResponse>;
|
|
416
|
+
/**
|
|
417
|
+
* 获取当前播放的动作信息
|
|
418
|
+
* @param getRemainingTime - 是否获取剩余时间
|
|
419
|
+
* @returns Promise<IAvatarCallbackResponse> 获取操作的Promise
|
|
420
|
+
*/
|
|
421
|
+
getCurrentMotion(getRemainingTime: boolean): Promise<IAvatarCallbackResponse>;
|
|
422
|
+
/**
|
|
423
|
+
* 卸载数字人
|
|
424
|
+
* @returns Promise<IAvatarCallbackResponse> 卸载操作的Promise
|
|
425
|
+
*/
|
|
426
|
+
unloadAvatar(): Promise<IAvatarCallbackResponse>;
|
|
427
|
+
/**
|
|
428
|
+
* 设置摄像机类型
|
|
429
|
+
* @param cameraType - 摄像机类型
|
|
430
|
+
* @returns Promise<IAvatarCallbackResponse> 设置操作的Promise
|
|
431
|
+
*/
|
|
432
|
+
setCamera(cameraType: AvatarCameraType): Promise<IAvatarCallbackResponse>;
|
|
433
|
+
/**
|
|
434
|
+
* 批量执行Avatar操作
|
|
435
|
+
* @param operations - 操作数组
|
|
436
|
+
* @returns Promise<IAvatarCallbackResponse[]> 返回所有操作的结果
|
|
437
|
+
*/
|
|
438
|
+
batchExecute(operations: Array<{
|
|
439
|
+
method: keyof IAvatarAPI;
|
|
440
|
+
params: any[];
|
|
441
|
+
}>): Promise<IAvatarCallbackResponse[]>;
|
|
442
|
+
}
|
|
443
|
+
|
|
439
444
|
/**
|
|
440
445
|
* @fileoverview 统一的3D数字人SDK入口类
|
|
441
446
|
* @description 提供统一的SDK接口,内部通过组合模式调用各个服务模块
|
|
@@ -716,7 +721,6 @@ declare class AvatarService extends UnityBaseService<AvatarOperationType> implem
|
|
|
716
721
|
protected get callbackFunctionName(): string;
|
|
717
722
|
/**
|
|
718
723
|
* 构造函数
|
|
719
|
-
* @param unityInstance - Unity实例对象
|
|
720
724
|
* @param config - 可选的服务配置,用于覆盖默认配置
|
|
721
725
|
* @description 初始化Avatar API,设置Unity实例和配置
|
|
722
726
|
* @example
|
package/dist/index.es5.js
CHANGED
|
@@ -12550,7 +12550,8 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
12550
12550
|
operation: operation,
|
|
12551
12551
|
code: code,
|
|
12552
12552
|
message: message,
|
|
12553
|
-
data: dataObj
|
|
12553
|
+
data: dataObj,
|
|
12554
|
+
originalData: data
|
|
12554
12555
|
});
|
|
12555
12556
|
var callback = this.pendingCallbacks.get(operation);
|
|
12556
12557
|
if (!callback) {
|
|
@@ -12899,7 +12900,6 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
12899
12900
|
__extends(AvatarService, _super);
|
|
12900
12901
|
/**
|
|
12901
12902
|
* 构造函数
|
|
12902
|
-
* @param unityInstance - Unity实例对象
|
|
12903
12903
|
* @param config - 可选的服务配置,用于覆盖默认配置
|
|
12904
12904
|
* @description 初始化Avatar API,设置Unity实例和配置
|
|
12905
12905
|
* @example
|
|
@@ -13413,16 +13413,11 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
13413
13413
|
UnityLoader.prototype.createContainer = function () {
|
|
13414
13414
|
var container = document.getElementById(this.config.containerId);
|
|
13415
13415
|
if (!container) {
|
|
13416
|
-
throw new
|
|
13416
|
+
throw new TypeError("Avatar container element with ID \"".concat(this.config.containerId, "\" not found"));
|
|
13417
|
+
} else if (!(container instanceof HTMLDivElement)) {
|
|
13418
|
+
throw new TypeError('Avatar container element must be a div element');
|
|
13417
13419
|
}
|
|
13418
|
-
container.style.width = '100%';
|
|
13419
|
-
container.style.height = '100%';
|
|
13420
13420
|
container.style.position = 'relative';
|
|
13421
|
-
// 移除容器提示元素
|
|
13422
|
-
var containerTip = document.getElementById('unity-container-tip');
|
|
13423
|
-
if (containerTip) {
|
|
13424
|
-
containerTip.remove();
|
|
13425
|
-
}
|
|
13426
13421
|
return container;
|
|
13427
13422
|
};
|
|
13428
13423
|
/**
|
|
@@ -13476,11 +13471,15 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
13476
13471
|
return __generator(this, function (_a) {
|
|
13477
13472
|
switch (_a.label) {
|
|
13478
13473
|
case 0:
|
|
13479
|
-
canvas =
|
|
13480
|
-
|
|
13481
|
-
canvas
|
|
13482
|
-
|
|
13483
|
-
|
|
13474
|
+
canvas = container.querySelector('#unity-canvas');
|
|
13475
|
+
// 避免重复创建
|
|
13476
|
+
if (!canvas) {
|
|
13477
|
+
canvas = document.createElement('canvas');
|
|
13478
|
+
canvas.id = 'unity-canvas';
|
|
13479
|
+
canvas.style.width = '100%';
|
|
13480
|
+
canvas.style.height = '100%';
|
|
13481
|
+
container.appendChild(canvas);
|
|
13482
|
+
}
|
|
13484
13483
|
// 移动设备适配
|
|
13485
13484
|
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
|
|
13486
13485
|
meta = document.createElement('meta');
|
|
@@ -13810,19 +13809,21 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
13810
13809
|
// 触发对应的事件回调(仅在成功时)
|
|
13811
13810
|
if (code === 0) {
|
|
13812
13811
|
switch (operation) {
|
|
13812
|
+
case exports.BroadcastOperationType.START_BROADCAST:
|
|
13813
|
+
if (isBroadcastCompleted) {
|
|
13814
|
+
(_b = (_a = this.callbacks).onFinish) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
13815
|
+
}
|
|
13816
|
+
break;
|
|
13813
13817
|
case exports.BroadcastOperationType.PAUSE_BROADCAST:
|
|
13814
|
-
(
|
|
13818
|
+
(_d = (_c = this.callbacks).onPause) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
13815
13819
|
this.logger.debug('Broadcast paused callback triggered');
|
|
13816
13820
|
break;
|
|
13817
13821
|
case exports.BroadcastOperationType.RESUME_BROADCAST:
|
|
13818
|
-
(
|
|
13822
|
+
(_f = (_e = this.callbacks).onResume) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
13819
13823
|
this.logger.debug('Broadcast resumed callback triggered');
|
|
13820
13824
|
break;
|
|
13821
13825
|
case exports.BroadcastOperationType.STOP_BROADCAST:
|
|
13822
|
-
(
|
|
13823
|
-
if (isBroadcastCompleted) {
|
|
13824
|
-
(_h = (_g = this.callbacks).onFinish) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
13825
|
-
}
|
|
13826
|
+
(_h = (_g = this.callbacks).onStop) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
13826
13827
|
this.logger.debug('Broadcast stopped callback triggered');
|
|
13827
13828
|
break;
|
|
13828
13829
|
}
|
|
@@ -14323,10 +14324,13 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
14323
14324
|
*/
|
|
14324
14325
|
ZEEAvatarLoader.prototype.destroy = function () {
|
|
14325
14326
|
if (this.unityInstance) {
|
|
14326
|
-
// 移除DOM
|
|
14327
|
+
// 移除DOM容器下的canvas元素
|
|
14327
14328
|
var container = document.getElementById(this.getContainerId());
|
|
14328
14329
|
if (container) {
|
|
14329
|
-
container.
|
|
14330
|
+
var canvas = container.querySelector('#unity-canvas');
|
|
14331
|
+
if (canvas) {
|
|
14332
|
+
canvas.remove();
|
|
14333
|
+
}
|
|
14330
14334
|
}
|
|
14331
14335
|
// 退出Unity实例
|
|
14332
14336
|
if (typeof this.unityInstance.Quit === 'function') {
|
|
@@ -14347,7 +14351,8 @@ var ZEEAvatarSDKLib = (function (exports) {
|
|
|
14347
14351
|
ZEEAvatarLoader.prototype.initGlobalConfig = function () {
|
|
14348
14352
|
var params = __assign(__assign({}, ConfigManager.getInstance().getConfig()), {
|
|
14349
14353
|
token: ConfigManager.getInstance().getToken(),
|
|
14350
|
-
apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false)
|
|
14354
|
+
apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false),
|
|
14355
|
+
assetsUrl: ConfigManager.getInstance().getConfig().assetsUrl
|
|
14351
14356
|
});
|
|
14352
14357
|
console.warn('[ Send Unity message ]: AvatarSDK.InitializeConfig', params);
|
|
14353
14358
|
this.unityInstance.SendMessage('AvatarSDK', 'InitializeConfig', JSON.stringify(params));
|
package/dist/index.es5.umd.js
CHANGED
|
@@ -12553,7 +12553,8 @@
|
|
|
12553
12553
|
operation: operation,
|
|
12554
12554
|
code: code,
|
|
12555
12555
|
message: message,
|
|
12556
|
-
data: dataObj
|
|
12556
|
+
data: dataObj,
|
|
12557
|
+
originalData: data
|
|
12557
12558
|
});
|
|
12558
12559
|
var callback = this.pendingCallbacks.get(operation);
|
|
12559
12560
|
if (!callback) {
|
|
@@ -12902,7 +12903,6 @@
|
|
|
12902
12903
|
__extends(AvatarService, _super);
|
|
12903
12904
|
/**
|
|
12904
12905
|
* 构造函数
|
|
12905
|
-
* @param unityInstance - Unity实例对象
|
|
12906
12906
|
* @param config - 可选的服务配置,用于覆盖默认配置
|
|
12907
12907
|
* @description 初始化Avatar API,设置Unity实例和配置
|
|
12908
12908
|
* @example
|
|
@@ -13416,16 +13416,11 @@
|
|
|
13416
13416
|
UnityLoader.prototype.createContainer = function () {
|
|
13417
13417
|
var container = document.getElementById(this.config.containerId);
|
|
13418
13418
|
if (!container) {
|
|
13419
|
-
throw new
|
|
13419
|
+
throw new TypeError("Avatar container element with ID \"".concat(this.config.containerId, "\" not found"));
|
|
13420
|
+
} else if (!(container instanceof HTMLDivElement)) {
|
|
13421
|
+
throw new TypeError('Avatar container element must be a div element');
|
|
13420
13422
|
}
|
|
13421
|
-
container.style.width = '100%';
|
|
13422
|
-
container.style.height = '100%';
|
|
13423
13423
|
container.style.position = 'relative';
|
|
13424
|
-
// 移除容器提示元素
|
|
13425
|
-
var containerTip = document.getElementById('unity-container-tip');
|
|
13426
|
-
if (containerTip) {
|
|
13427
|
-
containerTip.remove();
|
|
13428
|
-
}
|
|
13429
13424
|
return container;
|
|
13430
13425
|
};
|
|
13431
13426
|
/**
|
|
@@ -13479,11 +13474,15 @@
|
|
|
13479
13474
|
return __generator(this, function (_a) {
|
|
13480
13475
|
switch (_a.label) {
|
|
13481
13476
|
case 0:
|
|
13482
|
-
canvas =
|
|
13483
|
-
|
|
13484
|
-
canvas
|
|
13485
|
-
|
|
13486
|
-
|
|
13477
|
+
canvas = container.querySelector('#unity-canvas');
|
|
13478
|
+
// 避免重复创建
|
|
13479
|
+
if (!canvas) {
|
|
13480
|
+
canvas = document.createElement('canvas');
|
|
13481
|
+
canvas.id = 'unity-canvas';
|
|
13482
|
+
canvas.style.width = '100%';
|
|
13483
|
+
canvas.style.height = '100%';
|
|
13484
|
+
container.appendChild(canvas);
|
|
13485
|
+
}
|
|
13487
13486
|
// 移动设备适配
|
|
13488
13487
|
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
|
|
13489
13488
|
meta = document.createElement('meta');
|
|
@@ -13813,19 +13812,21 @@
|
|
|
13813
13812
|
// 触发对应的事件回调(仅在成功时)
|
|
13814
13813
|
if (code === 0) {
|
|
13815
13814
|
switch (operation) {
|
|
13815
|
+
case exports.BroadcastOperationType.START_BROADCAST:
|
|
13816
|
+
if (isBroadcastCompleted) {
|
|
13817
|
+
(_b = (_a = this.callbacks).onFinish) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
13818
|
+
}
|
|
13819
|
+
break;
|
|
13816
13820
|
case exports.BroadcastOperationType.PAUSE_BROADCAST:
|
|
13817
|
-
(
|
|
13821
|
+
(_d = (_c = this.callbacks).onPause) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
13818
13822
|
this.logger.debug('Broadcast paused callback triggered');
|
|
13819
13823
|
break;
|
|
13820
13824
|
case exports.BroadcastOperationType.RESUME_BROADCAST:
|
|
13821
|
-
(
|
|
13825
|
+
(_f = (_e = this.callbacks).onResume) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
13822
13826
|
this.logger.debug('Broadcast resumed callback triggered');
|
|
13823
13827
|
break;
|
|
13824
13828
|
case exports.BroadcastOperationType.STOP_BROADCAST:
|
|
13825
|
-
(
|
|
13826
|
-
if (isBroadcastCompleted) {
|
|
13827
|
-
(_h = (_g = this.callbacks).onFinish) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
13828
|
-
}
|
|
13829
|
+
(_h = (_g = this.callbacks).onStop) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
13829
13830
|
this.logger.debug('Broadcast stopped callback triggered');
|
|
13830
13831
|
break;
|
|
13831
13832
|
}
|
|
@@ -14326,10 +14327,13 @@
|
|
|
14326
14327
|
*/
|
|
14327
14328
|
ZEEAvatarLoader.prototype.destroy = function () {
|
|
14328
14329
|
if (this.unityInstance) {
|
|
14329
|
-
// 移除DOM
|
|
14330
|
+
// 移除DOM容器下的canvas元素
|
|
14330
14331
|
var container = document.getElementById(this.getContainerId());
|
|
14331
14332
|
if (container) {
|
|
14332
|
-
container.
|
|
14333
|
+
var canvas = container.querySelector('#unity-canvas');
|
|
14334
|
+
if (canvas) {
|
|
14335
|
+
canvas.remove();
|
|
14336
|
+
}
|
|
14333
14337
|
}
|
|
14334
14338
|
// 退出Unity实例
|
|
14335
14339
|
if (typeof this.unityInstance.Quit === 'function') {
|
|
@@ -14350,7 +14354,8 @@
|
|
|
14350
14354
|
ZEEAvatarLoader.prototype.initGlobalConfig = function () {
|
|
14351
14355
|
var params = __assign(__assign({}, ConfigManager.getInstance().getConfig()), {
|
|
14352
14356
|
token: ConfigManager.getInstance().getToken(),
|
|
14353
|
-
apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false)
|
|
14357
|
+
apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false),
|
|
14358
|
+
assetsUrl: ConfigManager.getInstance().getConfig().assetsUrl
|
|
14354
14359
|
});
|
|
14355
14360
|
console.warn('[ Send Unity message ]: AvatarSDK.InitializeConfig', params);
|
|
14356
14361
|
this.unityInstance.SendMessage('AvatarSDK', 'InitializeConfig', JSON.stringify(params));
|
package/dist/index.esm.js
CHANGED
|
@@ -474,7 +474,7 @@ class UnityBaseService {
|
|
|
474
474
|
*/
|
|
475
475
|
handleCallback(operation, code, message, data) {
|
|
476
476
|
const dataObj = data ? JSON.parse(data) : undefined;
|
|
477
|
-
this.logger.warn('[ Received Unity callback ]', { operation, code, message, data: dataObj });
|
|
477
|
+
this.logger.warn('[ Received Unity callback ]', { operation, code, message, data: dataObj, originalData: data });
|
|
478
478
|
const callback = this.pendingCallbacks.get(operation);
|
|
479
479
|
if (!callback) {
|
|
480
480
|
this.logger.warn(`No pending callback for operation: ${operation}`);
|
|
@@ -772,7 +772,6 @@ class AvatarService extends UnityBaseService {
|
|
|
772
772
|
}
|
|
773
773
|
/**
|
|
774
774
|
* 构造函数
|
|
775
|
-
* @param unityInstance - Unity实例对象
|
|
776
775
|
* @param config - 可选的服务配置,用于覆盖默认配置
|
|
777
776
|
* @description 初始化Avatar API,设置Unity实例和配置
|
|
778
777
|
* @example
|
|
@@ -1157,16 +1156,12 @@ class UnityLoader {
|
|
|
1157
1156
|
createContainer() {
|
|
1158
1157
|
const container = document.getElementById(this.config.containerId);
|
|
1159
1158
|
if (!container) {
|
|
1160
|
-
throw new
|
|
1159
|
+
throw new TypeError(`Avatar container element with ID "${this.config.containerId}" not found`);
|
|
1161
1160
|
}
|
|
1162
|
-
container
|
|
1163
|
-
|
|
1164
|
-
container.style.position = 'relative';
|
|
1165
|
-
// 移除容器提示元素
|
|
1166
|
-
const containerTip = document.getElementById('unity-container-tip');
|
|
1167
|
-
if (containerTip) {
|
|
1168
|
-
containerTip.remove();
|
|
1161
|
+
else if (!(container instanceof HTMLDivElement)) {
|
|
1162
|
+
throw new TypeError('Avatar container element must be a div element');
|
|
1169
1163
|
}
|
|
1164
|
+
container.style.position = 'relative';
|
|
1170
1165
|
return container;
|
|
1171
1166
|
}
|
|
1172
1167
|
/**
|
|
@@ -1215,12 +1210,15 @@ class UnityLoader {
|
|
|
1215
1210
|
*/
|
|
1216
1211
|
createUnityInstance(container) {
|
|
1217
1212
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
canvas
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1213
|
+
let canvas = container.querySelector('#unity-canvas');
|
|
1214
|
+
// 避免重复创建
|
|
1215
|
+
if (!canvas) {
|
|
1216
|
+
canvas = document.createElement('canvas');
|
|
1217
|
+
canvas.id = 'unity-canvas';
|
|
1218
|
+
canvas.style.width = '100%';
|
|
1219
|
+
canvas.style.height = '100%';
|
|
1220
|
+
container.appendChild(canvas);
|
|
1221
|
+
}
|
|
1224
1222
|
// 移动设备适配
|
|
1225
1223
|
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
|
|
1226
1224
|
// 添加移动设备viewport元标签
|
|
@@ -1545,19 +1543,21 @@ class BroadcastService extends UnityBaseService {
|
|
|
1545
1543
|
// 触发对应的事件回调(仅在成功时)
|
|
1546
1544
|
if (code === 0) {
|
|
1547
1545
|
switch (operation) {
|
|
1546
|
+
case BroadcastOperationType.START_BROADCAST:
|
|
1547
|
+
if (isBroadcastCompleted) {
|
|
1548
|
+
(_b = (_a = this.callbacks).onFinish) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1549
|
+
}
|
|
1550
|
+
break;
|
|
1548
1551
|
case BroadcastOperationType.PAUSE_BROADCAST:
|
|
1549
|
-
(
|
|
1552
|
+
(_d = (_c = this.callbacks).onPause) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
1550
1553
|
this.logger.debug('Broadcast paused callback triggered');
|
|
1551
1554
|
break;
|
|
1552
1555
|
case BroadcastOperationType.RESUME_BROADCAST:
|
|
1553
|
-
(
|
|
1556
|
+
(_f = (_e = this.callbacks).onResume) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
1554
1557
|
this.logger.debug('Broadcast resumed callback triggered');
|
|
1555
1558
|
break;
|
|
1556
1559
|
case BroadcastOperationType.STOP_BROADCAST:
|
|
1557
|
-
(
|
|
1558
|
-
if (isBroadcastCompleted) {
|
|
1559
|
-
(_h = (_g = this.callbacks).onFinish) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1560
|
-
}
|
|
1560
|
+
(_h = (_g = this.callbacks).onStop) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1561
1561
|
this.logger.debug('Broadcast stopped callback triggered');
|
|
1562
1562
|
break;
|
|
1563
1563
|
}
|
|
@@ -1984,10 +1984,13 @@ class ZEEAvatarLoader {
|
|
|
1984
1984
|
*/
|
|
1985
1985
|
destroy() {
|
|
1986
1986
|
if (this.unityInstance) {
|
|
1987
|
-
// 移除DOM
|
|
1987
|
+
// 移除DOM容器下的canvas元素
|
|
1988
1988
|
const container = document.getElementById(this.getContainerId());
|
|
1989
1989
|
if (container) {
|
|
1990
|
-
container.
|
|
1990
|
+
const canvas = container.querySelector('#unity-canvas');
|
|
1991
|
+
if (canvas) {
|
|
1992
|
+
canvas.remove();
|
|
1993
|
+
}
|
|
1991
1994
|
}
|
|
1992
1995
|
// 退出Unity实例
|
|
1993
1996
|
if (typeof this.unityInstance.Quit === 'function') {
|
|
@@ -2006,7 +2009,7 @@ class ZEEAvatarLoader {
|
|
|
2006
2009
|
* @protected
|
|
2007
2010
|
*/
|
|
2008
2011
|
initGlobalConfig() {
|
|
2009
|
-
const params = Object.assign(Object.assign({}, ConfigManager.getInstance().getConfig()), { token: ConfigManager.getInstance().getToken(), apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false) });
|
|
2012
|
+
const params = Object.assign(Object.assign({}, ConfigManager.getInstance().getConfig()), { token: ConfigManager.getInstance().getToken(), apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false), assetsUrl: ConfigManager.getInstance().getConfig().assetsUrl });
|
|
2010
2013
|
console.warn('[ Send Unity message ]: AvatarSDK.InitializeConfig', params);
|
|
2011
2014
|
this.unityInstance.SendMessage('AvatarSDK', 'InitializeConfig', JSON.stringify(params));
|
|
2012
2015
|
}
|
|
@@ -2076,7 +2079,8 @@ class ZEEAvatarSDK {
|
|
|
2076
2079
|
// 5. 创建带有唯一标识符的播报服务
|
|
2077
2080
|
this.broadcastService = new BroadcastService({
|
|
2078
2081
|
unityInstance: this.unityInstance,
|
|
2079
|
-
instanceId: this.instanceId
|
|
2082
|
+
instanceId: this.instanceId,
|
|
2083
|
+
callbacks: this.config.broadcastCallbacks
|
|
2080
2084
|
});
|
|
2081
2085
|
// 6. 初始化数字人
|
|
2082
2086
|
const result = yield this.avatarService.initializeAvatar(avatarCode, cameraType);
|
|
@@ -2291,7 +2295,7 @@ class ZEEAvatarSDK {
|
|
|
2291
2295
|
*/
|
|
2292
2296
|
ensureInitialized() {
|
|
2293
2297
|
if (!this.isInitialized) {
|
|
2294
|
-
throw new SDKError(OperationErrorCode.UNITY_NOT_INITIALIZED, '
|
|
2298
|
+
throw new SDKError(OperationErrorCode.UNITY_NOT_INITIALIZED, 'Avatar尚未初始化,请先调用initializeAvatar()方法');
|
|
2295
2299
|
}
|
|
2296
2300
|
}
|
|
2297
2301
|
}
|
package/dist/index.umd.cjs
CHANGED
|
@@ -480,7 +480,7 @@
|
|
|
480
480
|
*/
|
|
481
481
|
handleCallback(operation, code, message, data) {
|
|
482
482
|
const dataObj = data ? JSON.parse(data) : undefined;
|
|
483
|
-
this.logger.warn('[ Received Unity callback ]', { operation, code, message, data: dataObj });
|
|
483
|
+
this.logger.warn('[ Received Unity callback ]', { operation, code, message, data: dataObj, originalData: data });
|
|
484
484
|
const callback = this.pendingCallbacks.get(operation);
|
|
485
485
|
if (!callback) {
|
|
486
486
|
this.logger.warn(`No pending callback for operation: ${operation}`);
|
|
@@ -778,7 +778,6 @@
|
|
|
778
778
|
}
|
|
779
779
|
/**
|
|
780
780
|
* 构造函数
|
|
781
|
-
* @param unityInstance - Unity实例对象
|
|
782
781
|
* @param config - 可选的服务配置,用于覆盖默认配置
|
|
783
782
|
* @description 初始化Avatar API,设置Unity实例和配置
|
|
784
783
|
* @example
|
|
@@ -1163,16 +1162,12 @@
|
|
|
1163
1162
|
createContainer() {
|
|
1164
1163
|
const container = document.getElementById(this.config.containerId);
|
|
1165
1164
|
if (!container) {
|
|
1166
|
-
throw new
|
|
1165
|
+
throw new TypeError(`Avatar container element with ID "${this.config.containerId}" not found`);
|
|
1167
1166
|
}
|
|
1168
|
-
container
|
|
1169
|
-
|
|
1170
|
-
container.style.position = 'relative';
|
|
1171
|
-
// 移除容器提示元素
|
|
1172
|
-
const containerTip = document.getElementById('unity-container-tip');
|
|
1173
|
-
if (containerTip) {
|
|
1174
|
-
containerTip.remove();
|
|
1167
|
+
else if (!(container instanceof HTMLDivElement)) {
|
|
1168
|
+
throw new TypeError('Avatar container element must be a div element');
|
|
1175
1169
|
}
|
|
1170
|
+
container.style.position = 'relative';
|
|
1176
1171
|
return container;
|
|
1177
1172
|
}
|
|
1178
1173
|
/**
|
|
@@ -1221,12 +1216,15 @@
|
|
|
1221
1216
|
*/
|
|
1222
1217
|
createUnityInstance(container) {
|
|
1223
1218
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
canvas
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1219
|
+
let canvas = container.querySelector('#unity-canvas');
|
|
1220
|
+
// 避免重复创建
|
|
1221
|
+
if (!canvas) {
|
|
1222
|
+
canvas = document.createElement('canvas');
|
|
1223
|
+
canvas.id = 'unity-canvas';
|
|
1224
|
+
canvas.style.width = '100%';
|
|
1225
|
+
canvas.style.height = '100%';
|
|
1226
|
+
container.appendChild(canvas);
|
|
1227
|
+
}
|
|
1230
1228
|
// 移动设备适配
|
|
1231
1229
|
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
|
|
1232
1230
|
// 添加移动设备viewport元标签
|
|
@@ -1551,19 +1549,21 @@
|
|
|
1551
1549
|
// 触发对应的事件回调(仅在成功时)
|
|
1552
1550
|
if (code === 0) {
|
|
1553
1551
|
switch (operation) {
|
|
1552
|
+
case exports.BroadcastOperationType.START_BROADCAST:
|
|
1553
|
+
if (isBroadcastCompleted) {
|
|
1554
|
+
(_b = (_a = this.callbacks).onFinish) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1555
|
+
}
|
|
1556
|
+
break;
|
|
1554
1557
|
case exports.BroadcastOperationType.PAUSE_BROADCAST:
|
|
1555
|
-
(
|
|
1558
|
+
(_d = (_c = this.callbacks).onPause) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
1556
1559
|
this.logger.debug('Broadcast paused callback triggered');
|
|
1557
1560
|
break;
|
|
1558
1561
|
case exports.BroadcastOperationType.RESUME_BROADCAST:
|
|
1559
|
-
(
|
|
1562
|
+
(_f = (_e = this.callbacks).onResume) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
1560
1563
|
this.logger.debug('Broadcast resumed callback triggered');
|
|
1561
1564
|
break;
|
|
1562
1565
|
case exports.BroadcastOperationType.STOP_BROADCAST:
|
|
1563
|
-
(
|
|
1564
|
-
if (isBroadcastCompleted) {
|
|
1565
|
-
(_h = (_g = this.callbacks).onFinish) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1566
|
-
}
|
|
1566
|
+
(_h = (_g = this.callbacks).onStop) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1567
1567
|
this.logger.debug('Broadcast stopped callback triggered');
|
|
1568
1568
|
break;
|
|
1569
1569
|
}
|
|
@@ -1990,10 +1990,13 @@
|
|
|
1990
1990
|
*/
|
|
1991
1991
|
destroy() {
|
|
1992
1992
|
if (this.unityInstance) {
|
|
1993
|
-
// 移除DOM
|
|
1993
|
+
// 移除DOM容器下的canvas元素
|
|
1994
1994
|
const container = document.getElementById(this.getContainerId());
|
|
1995
1995
|
if (container) {
|
|
1996
|
-
container.
|
|
1996
|
+
const canvas = container.querySelector('#unity-canvas');
|
|
1997
|
+
if (canvas) {
|
|
1998
|
+
canvas.remove();
|
|
1999
|
+
}
|
|
1997
2000
|
}
|
|
1998
2001
|
// 退出Unity实例
|
|
1999
2002
|
if (typeof this.unityInstance.Quit === 'function') {
|
|
@@ -2012,7 +2015,7 @@
|
|
|
2012
2015
|
* @protected
|
|
2013
2016
|
*/
|
|
2014
2017
|
initGlobalConfig() {
|
|
2015
|
-
const params = Object.assign(Object.assign({}, ConfigManager.getInstance().getConfig()), { token: ConfigManager.getInstance().getToken(), apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false) });
|
|
2018
|
+
const params = Object.assign(Object.assign({}, ConfigManager.getInstance().getConfig()), { token: ConfigManager.getInstance().getToken(), apiBaseUrl: ConfigManager.getInstance().getApiBaseUrl(false), assetsUrl: ConfigManager.getInstance().getConfig().assetsUrl });
|
|
2016
2019
|
console.warn('[ Send Unity message ]: AvatarSDK.InitializeConfig', params);
|
|
2017
2020
|
this.unityInstance.SendMessage('AvatarSDK', 'InitializeConfig', JSON.stringify(params));
|
|
2018
2021
|
}
|
|
@@ -2082,7 +2085,8 @@
|
|
|
2082
2085
|
// 5. 创建带有唯一标识符的播报服务
|
|
2083
2086
|
this.broadcastService = new BroadcastService({
|
|
2084
2087
|
unityInstance: this.unityInstance,
|
|
2085
|
-
instanceId: this.instanceId
|
|
2088
|
+
instanceId: this.instanceId,
|
|
2089
|
+
callbacks: this.config.broadcastCallbacks
|
|
2086
2090
|
});
|
|
2087
2091
|
// 6. 初始化数字人
|
|
2088
2092
|
const result = yield this.avatarService.initializeAvatar(avatarCode, cameraType);
|
|
@@ -2297,7 +2301,7 @@
|
|
|
2297
2301
|
*/
|
|
2298
2302
|
ensureInitialized() {
|
|
2299
2303
|
if (!this.isInitialized) {
|
|
2300
|
-
throw new SDKError(exports.OperationErrorCode.UNITY_NOT_INITIALIZED, '
|
|
2304
|
+
throw new SDKError(exports.OperationErrorCode.UNITY_NOT_INITIALIZED, 'Avatar尚未初始化,请先调用initializeAvatar()方法');
|
|
2301
2305
|
}
|
|
2302
2306
|
}
|
|
2303
2307
|
}
|