@zeewain/3d-avatar-sdk 1.2.1 → 1.2.3

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.
Files changed (55) hide show
  1. package/README.md +3 -4
  2. package/dist/assets/Build/webgl.data.unityweb +0 -0
  3. package/dist/assets/Build/webgl.framework.js.unityweb +0 -0
  4. package/dist/assets/Build/webgl.wasm.unityweb +0 -0
  5. package/dist/examples/test-umd/index.html +762 -0
  6. package/dist/examples/test-vue2/.eslintignore +45 -0
  7. package/dist/examples/test-vue2/.eslintrc.js +174 -0
  8. package/dist/examples/test-vue2/.stylelintignore +50 -0
  9. package/dist/examples/test-vue2/.stylelintrc.js +79 -0
  10. package/dist/examples/test-vue2/README.md +139 -0
  11. package/dist/examples/test-vue2/babel.config.js +14 -0
  12. package/dist/examples/test-vue2/package.json +53 -0
  13. package/dist/examples/test-vue2/pnpm-lock.yaml +8776 -0
  14. package/dist/examples/test-vue2/public/index.html +19 -0
  15. package/dist/examples/test-vue2/setup.js +170 -0
  16. package/dist/examples/test-vue2/src/App.vue +943 -0
  17. package/dist/examples/test-vue2/src/components/BroadcastAPI.vue +666 -0
  18. package/dist/examples/test-vue2/src/components/CameraAPI.vue +414 -0
  19. package/dist/examples/test-vue2/src/components/GlobalConfig.vue +200 -0
  20. package/dist/examples/test-vue2/src/components/InfoCards.vue +294 -0
  21. package/dist/examples/test-vue2/src/components/InitAPI.vue +334 -0
  22. package/dist/examples/test-vue2/src/components/LogPanel.vue +249 -0
  23. package/dist/examples/test-vue2/src/components/MotionControlAPI.vue +400 -0
  24. package/dist/examples/test-vue2/src/components/UnityPreview.vue +201 -0
  25. package/dist/examples/test-vue2/src/main.js +16 -0
  26. package/dist/examples/test-vue2/vue.config.js +41 -0
  27. package/dist/examples/test-vue3/.eslintrc +3 -0
  28. package/dist/examples/test-vue3/.stylelintignore +3 -0
  29. package/dist/examples/test-vue3/.stylelintrc +48 -0
  30. package/dist/examples/test-vue3/README.md +236 -0
  31. package/dist/examples/test-vue3/env.d.ts +8 -0
  32. package/dist/examples/test-vue3/index.html +95 -0
  33. package/dist/examples/test-vue3/package.json +55 -0
  34. package/dist/examples/test-vue3/pnpm-lock.yaml +4636 -0
  35. package/dist/examples/test-vue3/setup.js +167 -0
  36. package/dist/examples/test-vue3/src/App.vue +962 -0
  37. package/dist/examples/test-vue3/src/components/BroadcastAPI.vue +636 -0
  38. package/dist/examples/test-vue3/src/components/CameraAPI.vue +376 -0
  39. package/dist/examples/test-vue3/src/components/GlobalConfig.vue +213 -0
  40. package/dist/examples/test-vue3/src/components/InfoCards.vue +288 -0
  41. package/dist/examples/test-vue3/src/components/InitAPI.vue +339 -0
  42. package/dist/examples/test-vue3/src/components/LogPanel.vue +236 -0
  43. package/dist/examples/test-vue3/src/components/MotionControlAPI.vue +373 -0
  44. package/dist/examples/test-vue3/src/components/UnityPreview.vue +189 -0
  45. package/dist/examples/test-vue3/src/main.ts +12 -0
  46. package/dist/examples/test-vue3/src/types.ts +9 -0
  47. package/dist/examples/test-vue3/tsconfig.json +44 -0
  48. package/dist/examples/test-vue3/tsconfig.node.json +14 -0
  49. package/dist/examples/test-vue3/vite.config.ts +75 -0
  50. package/dist/index.d.ts +15 -9
  51. package/dist/index.es5.js +75 -27
  52. package/dist/index.es5.umd.js +75 -27
  53. package/dist/index.esm.js +78 -22
  54. package/dist/index.umd.cjs +78 -22
  55. package/package.json +4 -3
@@ -0,0 +1,414 @@
1
+ <template>
2
+ <div class="camera-api">
3
+ <div class="api-description">
4
+ <el-alert
5
+ title="API说明"
6
+ type="info"
7
+ :closable="false"
8
+ show-icon
9
+ >
10
+ <template slot="default">
11
+ <div class="api-signature">
12
+ <code>setCamera(type: AvatarCameraType): Promise&lt;IAvatarCallbackResponse&gt;</code>
13
+ </div>
14
+ <p>设置数字人的摄像机类型和视角,支持全身、半身、近景三种预设类型</p>
15
+ <p class="api-features">
16
+ ✅ 实时镜头切换 &nbsp;&nbsp;
17
+ ✅ 平滑过渡动画 &nbsp;&nbsp;
18
+ ✅ 多种预设视角
19
+ </p>
20
+ </template>
21
+ </el-alert>
22
+ </div>
23
+
24
+ <div class="api-controls">
25
+ <el-card shadow="hover" class="control-card">
26
+ <div slot="header" class="card-header">
27
+ <span>镜头控制</span>
28
+ <el-tag v-if="sdkStatus.canControlCamera" type="success" size="mini">可用</el-tag>
29
+ <el-tag v-else type="info" size="mini">不可用</el-tag>
30
+ </div>
31
+
32
+ <div class="control-content">
33
+ <div class="preset-selector">
34
+ <el-form :model="presetData" label-width="80px" size="small">
35
+ <el-form-item label="预设视角" required>
36
+ <el-radio-group v-model="presetData.preset" class="preset-radio-group">
37
+ <el-radio-button label="whole">
38
+ <i class="el-icon-full-screen"></i>
39
+ 全身
40
+ </el-radio-button>
41
+ <el-radio-button label="half">
42
+ <i class="el-icon-picture"></i>
43
+ 半身
44
+ </el-radio-button>
45
+ <el-radio-button label="face">
46
+ <i class="el-icon-view"></i>
47
+ 近景
48
+ </el-radio-button>
49
+ </el-radio-group>
50
+ </el-form-item>
51
+
52
+ <el-form-item label="预览">
53
+ <div class="preset-preview">
54
+ <div class="preview-card" :class="{ active: presetData.preset === 'whole' }">
55
+ <div class="preview-icon">👤</div>
56
+ <div class="preview-label">全身视角</div>
57
+ <div class="preview-desc">显示数字人全身</div>
58
+ </div>
59
+ <div class="preview-card" :class="{ active: presetData.preset === 'half' }">
60
+ <div class="preview-icon">🧑‍💼</div>
61
+ <div class="preview-label">半身视角</div>
62
+ <div class="preview-desc">显示数字人上半身</div>
63
+ </div>
64
+ <div class="preview-card" :class="{ active: presetData.preset === 'face' }">
65
+ <div class="preview-icon">😊</div>
66
+ <div class="preview-label">近景视角</div>
67
+ <div class="preview-desc">显示数字人面部特写</div>
68
+ </div>
69
+ </div>
70
+ </el-form-item>
71
+
72
+ <el-form-item class="action-buttons">
73
+ <el-button
74
+ type="primary"
75
+ size="medium"
76
+ icon="el-icon-camera"
77
+ :loading="isLoading"
78
+ :disabled="!sdkStatus.canControlCamera || !presetData.preset || !globalConfig.avatarCode"
79
+ @click="handleSetCameraPreset"
80
+ >
81
+ {{ isLoading ? '切换中...' : '应用镜头设置' }}
82
+ </el-button>
83
+ </el-form-item>
84
+ </el-form>
85
+ </div>
86
+
87
+ <div class="status-tips">
88
+ <el-alert
89
+ v-if="!sdkStatus.canControlCamera"
90
+ title="请先初始化Avatar后再进行镜头控制"
91
+ type="warning"
92
+ :closable="false"
93
+ show-icon
94
+ />
95
+ <el-alert
96
+ v-else-if="!globalConfig.avatarCode"
97
+ title="请先在全局配置中设置Avatar Code"
98
+ type="warning"
99
+ :closable="false"
100
+ show-icon
101
+ />
102
+ </div>
103
+ </div>
104
+ </el-card>
105
+ </div>
106
+
107
+ <div class="api-result">
108
+ <el-card shadow="hover" class="result-card">
109
+ <div slot="header" class="card-header">
110
+ <span>执行结果</span>
111
+ <el-button
112
+ type="text"
113
+ size="mini"
114
+ icon="el-icon-refresh"
115
+ @click="clearResult"
116
+ >
117
+ 清空
118
+ </el-button>
119
+ </div>
120
+
121
+ <div class="result-content">
122
+ <pre class="result-text">{{ result }}</pre>
123
+ </div>
124
+ </el-card>
125
+ </div>
126
+ </div>
127
+ </template>
128
+
129
+ <script>
130
+ export default {
131
+ name: 'CameraAPI',
132
+ props: {
133
+ sdkStatus: {
134
+ type: Object,
135
+ required: true
136
+ },
137
+ globalConfig: {
138
+ type: Object,
139
+ required: true
140
+ }
141
+ },
142
+ data () {
143
+ return {
144
+ presetData: {
145
+ preset: 'whole'
146
+ },
147
+ result: '等待镜头控制操作...\n\n支持的镜头类型:\n- whole: 全身视角,展示数字人完整形象\n- half: 半身视角,适合对话场景\n- face: 近景视角,突出面部表情',
148
+ isLoading: false
149
+ }
150
+ },
151
+ methods: {
152
+ handleSetCameraPreset () {
153
+ const { avatarCode } = this.globalConfig
154
+
155
+ if (!avatarCode) {
156
+ this.result = '❌ 请先在全局配置中设置Avatar Code'
157
+ this.$message.warning('请先设置Avatar Code')
158
+ return
159
+ }
160
+
161
+ if (!this.presetData.preset) {
162
+ this.result = '❌ 请选择镜头预设类型'
163
+ this.$message.warning('请选择镜头预设类型')
164
+ return
165
+ }
166
+
167
+ this.isLoading = true
168
+ const presetName = this.getPresetName(this.presetData.preset)
169
+ this.result = `🔄 正在设置镜头...\n📹 目标视角: ${presetName}\n⚙️ 类型: ${this.presetData.preset}\n\n📡 发送镜头切换指令...`
170
+
171
+ try {
172
+ this.$emit('set-camera-preset', {
173
+ preset: this.presetData.preset
174
+ })
175
+
176
+ // 模拟加载时间
177
+ setTimeout(() => {
178
+ this.isLoading = false
179
+ this.result = `✅ 镜头设置请求已发送\n📋 请查看右侧日志面板获取详细信息\n\n📝 操作说明:\n- 镜头将平滑切换到${presetName}\n- 切换过程可能需要几秒钟\n- 不同视角适合不同的应用场景`
180
+ }, 800)
181
+ } catch (error) {
182
+ this.isLoading = false
183
+ this.result = `❌ 镜头设置失败: ${error.message}\n\n🔍 可能的原因:\n- Avatar未正确初始化\n- 镜头类型不支持\n- Unity通信异常`
184
+ this.$message.error(`镜头设置失败: ${error.message}`)
185
+ }
186
+ },
187
+
188
+ getPresetName (preset) {
189
+ const names = {
190
+ whole: '全身视角',
191
+ half: '半身视角',
192
+ face: '近景视角'
193
+ }
194
+ return names[preset] || preset
195
+ },
196
+
197
+ clearResult () {
198
+ this.result = '等待镜头控制操作...\n\n支持的镜头类型:\n- whole: 全身视角,展示数字人完整形象\n- half: 半身视角,适合对话场景\n- face: 近景视角,突出面部表情'
199
+ }
200
+ }
201
+ }
202
+ </script>
203
+
204
+ <style lang="scss" scoped>
205
+ .camera-api {
206
+ .api-description {
207
+ margin-bottom: 20px;
208
+
209
+ .api-signature {
210
+ background-color: #f5f5f5;
211
+ padding: 8px 12px;
212
+ border-radius: 4px;
213
+ margin-bottom: 10px;
214
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
215
+ font-size: 12px;
216
+ border-left: 4px solid #e6a23c;
217
+
218
+ code {
219
+ color: #2c3e50;
220
+ font-weight: 600;
221
+ }
222
+ }
223
+
224
+ p {
225
+ margin: 5px 0;
226
+ color: #606266;
227
+ font-size: 14px;
228
+
229
+ &.api-features {
230
+ color: #e6a23c;
231
+ font-weight: 500;
232
+ margin-top: 8px;
233
+ }
234
+ }
235
+ }
236
+
237
+ .api-controls {
238
+ margin-bottom: 20px;
239
+
240
+ .control-card {
241
+ .card-header {
242
+ display: flex;
243
+ justify-content: space-between;
244
+ align-items: center;
245
+ font-weight: 600;
246
+ }
247
+
248
+ .control-content {
249
+ .preset-selector {
250
+ .el-form-item {
251
+ margin-bottom: 18px;
252
+
253
+ :deep(.el-form-item__label) {
254
+ font-weight: 500;
255
+ color: #303133;
256
+ }
257
+
258
+ &.action-buttons {
259
+ margin-bottom: 0;
260
+ margin-top: 25px;
261
+
262
+ .el-button {
263
+ width: 100%;
264
+ padding: 10px 0;
265
+ font-weight: 500;
266
+ }
267
+ }
268
+ }
269
+
270
+ .preset-radio-group {
271
+ width: 100%;
272
+
273
+ .el-radio-button {
274
+ flex: 1;
275
+
276
+ :deep(.el-radio-button__inner) {
277
+ width: 100%;
278
+ padding: 8px 15px;
279
+
280
+ i {
281
+ margin-right: 5px;
282
+ }
283
+ }
284
+ }
285
+ }
286
+
287
+ .preset-preview {
288
+ display: flex;
289
+ gap: 10px;
290
+ margin-top: 10px;
291
+
292
+ .preview-card {
293
+ flex: 1;
294
+ padding: 12px;
295
+ border: 2px solid #e4e7ed;
296
+ border-radius: 6px;
297
+ text-align: center;
298
+ cursor: pointer;
299
+ transition: all 0.3s;
300
+
301
+ &:hover {
302
+ border-color: #409eff;
303
+ background-color: #f0f9ff;
304
+ }
305
+
306
+ &.active {
307
+ border-color: #409eff;
308
+ background-color: #ecf5ff;
309
+ }
310
+
311
+ .preview-icon {
312
+ font-size: 24px;
313
+ margin-bottom: 8px;
314
+ }
315
+
316
+ .preview-label {
317
+ font-weight: 500;
318
+ color: #303133;
319
+ margin-bottom: 4px;
320
+ font-size: 13px;
321
+ }
322
+
323
+ .preview-desc {
324
+ color: #909399;
325
+ font-size: 11px;
326
+ line-height: 1.3;
327
+ }
328
+ }
329
+ }
330
+ }
331
+
332
+ .status-tips {
333
+ margin-top: 15px;
334
+
335
+ .el-alert {
336
+ margin-bottom: 10px;
337
+
338
+ &:last-child {
339
+ margin-bottom: 0;
340
+ }
341
+ }
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ .api-result {
348
+ .result-card {
349
+ .card-header {
350
+ display: flex;
351
+ justify-content: space-between;
352
+ align-items: center;
353
+ font-weight: 600;
354
+ }
355
+
356
+ .result-content {
357
+ max-height: 300px;
358
+ overflow-y: auto;
359
+
360
+ .result-text {
361
+ margin: 0;
362
+ padding: 15px;
363
+ background-color: #f8f9fa;
364
+ border-radius: 4px;
365
+ border: 1px solid #e9ecef;
366
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
367
+ font-size: 13px;
368
+ line-height: 1.6;
369
+ color: #2c3e50;
370
+ white-space: pre-wrap;
371
+ word-wrap: break-word;
372
+ }
373
+ }
374
+ }
375
+ }
376
+ }
377
+
378
+ // 移动端优化
379
+ @media screen and (width <= 768px) {
380
+ .camera-api {
381
+ .preset-radio-group {
382
+ .el-radio-button {
383
+ :deep(.el-radio-button__inner) {
384
+ padding: 6px 10px;
385
+ font-size: 12px;
386
+
387
+ i {
388
+ margin-right: 3px;
389
+ }
390
+ }
391
+ }
392
+ }
393
+
394
+ .preset-preview {
395
+ .preview-card {
396
+ padding: 8px;
397
+
398
+ .preview-icon {
399
+ font-size: 20px;
400
+ margin-bottom: 6px;
401
+ }
402
+
403
+ .preview-label {
404
+ font-size: 12px;
405
+ }
406
+
407
+ .preview-desc {
408
+ font-size: 10px;
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+ </style>
@@ -0,0 +1,200 @@
1
+ <template>
2
+ <div class="global-config">
3
+ <div class="config-header">
4
+ <el-icon class="el-icon-setting" />
5
+ <span class="config-title">全局配置</span>
6
+ <el-tag type="primary" size="mini">必填</el-tag>
7
+ </div>
8
+
9
+ <el-form :model="formData"
10
+ size="small"
11
+ class="config-form"
12
+ >
13
+ <el-row :gutter="16">
14
+ <el-col :xs="12" :sm="12">
15
+ <el-form-item label="Token" required>
16
+ <el-input
17
+ v-model="formData.token"
18
+ placeholder="请输入全局Token"
19
+ prefix-icon="el-icon-key"
20
+ clearable
21
+ @input="handleTokenInput"
22
+ />
23
+ </el-form-item>
24
+ </el-col>
25
+
26
+ <el-col :xs="12" :sm="12">
27
+ <el-form-item label="Avatar Code" required>
28
+ <el-input
29
+ v-model="formData.avatarCode"
30
+ placeholder="请输入数字人编码"
31
+ prefix-icon="el-icon-user"
32
+ clearable
33
+ @input="handleAvatarCodeInput"
34
+ />
35
+ </el-form-item>
36
+ </el-col>
37
+ </el-row>
38
+ <el-form-item class="config-actions">
39
+ <el-button
40
+ type="primary"
41
+ size="small"
42
+ icon="el-icon-check"
43
+ @click="saveConfig"
44
+ :disabled="!formData.token || !formData.avatarCode"
45
+ >
46
+ 保存配置
47
+ </el-button>
48
+ </el-form-item>
49
+ </el-form>
50
+
51
+ <div class="config-tips">
52
+ <el-alert
53
+ title="配置提示"
54
+ type="info"
55
+ :closable="false"
56
+ show-icon
57
+ >
58
+ <template slot="default">
59
+ <ul>
60
+ <li>1、Token: 用于API鉴权的访问令牌。 2、Avatar Code: 默认数字人编码,用于初始化Avatar。 3、配置保存后将自动应用到所有API接口</li>
61
+ </ul>
62
+ </template>
63
+ </el-alert>
64
+ </div>
65
+ </div>
66
+ </template>
67
+
68
+ <script>
69
+ export default {
70
+ name: 'GlobalConfig',
71
+ props: {
72
+ globalToken: {
73
+ type: String,
74
+ default: ''
75
+ },
76
+ globalAvatarCode: {
77
+ type: String,
78
+ default: ''
79
+ }
80
+ },
81
+ data () {
82
+ return {
83
+ formData: {
84
+ token: this.globalToken,
85
+ avatarCode: this.globalAvatarCode
86
+ }
87
+ }
88
+ },
89
+ watch: {
90
+ globalToken (newVal) {
91
+ this.formData.token = newVal
92
+ },
93
+ globalAvatarCode (newVal) {
94
+ this.formData.avatarCode = newVal
95
+ }
96
+ },
97
+ methods: {
98
+ handleTokenInput (value) {
99
+ this.$emit('update:global-token', value)
100
+ },
101
+ handleAvatarCodeInput (value) {
102
+ this.$emit('update:global-avatar-code', value)
103
+ },
104
+ saveConfig () {
105
+ if (!this.formData.token || !this.formData.avatarCode) {
106
+ this.$message.warning('请填写完整的配置信息')
107
+ return
108
+ }
109
+
110
+ this.$emit('save-config', {
111
+ token: this.formData.token,
112
+ avatarCode: this.formData.avatarCode
113
+ })
114
+ },
115
+ applyAll () {
116
+ if (!this.formData.token || !this.formData.avatarCode) {
117
+ this.$message.warning('请先保存配置')
118
+ return
119
+ }
120
+
121
+ this.$emit('apply-all')
122
+ }
123
+ }
124
+ }
125
+ </script>
126
+
127
+ <style lang="scss" scoped>
128
+ .global-config {
129
+ .config-header {
130
+ display: flex;
131
+ align-items: center;
132
+ gap: 10px;
133
+ margin-bottom: 20px;
134
+ padding: 10px;
135
+ background: linear-gradient(135deg, #409eff, #66b1ff);
136
+ color: white;
137
+ border-radius: 4px;
138
+
139
+ .config-title {
140
+ font-weight: 600;
141
+ font-size: 14px;
142
+ }
143
+
144
+ .el-icon-setting {
145
+ font-size: 18px;
146
+ }
147
+ }
148
+
149
+ .config-form {
150
+ margin-bottom: 20px;
151
+
152
+ .config-actions {
153
+ text-align: center;
154
+
155
+ .el-button {
156
+ margin: 0 5px;
157
+ }
158
+ }
159
+ }
160
+
161
+ .config-tips {
162
+ .el-alert {
163
+ .el-alert__content {
164
+ ul {
165
+ margin: 0;
166
+ padding-left: 20px;
167
+
168
+ li {
169
+ margin: 5px 0;
170
+ font-size: 12px;
171
+ line-height: 1.5;
172
+ }
173
+ }
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ // 移动端优化
180
+ @media screen and (max-width: 768px) {
181
+ .global-config {
182
+ .config-form {
183
+ .el-form-item {
184
+ .el-form-item__label {
185
+ width: 80px !important;
186
+ font-size: 12px;
187
+ }
188
+ }
189
+
190
+ .config-actions {
191
+ .el-button {
192
+ display: block;
193
+ width: 100%;
194
+ margin: 5px 0;
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ </style>