@zeewain/3d-avatar-sdk 1.2.1 → 1.2.2
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 -4
- 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/examples/test-umd/index.html +762 -0
- package/dist/examples/test-vue2/.eslintignore +45 -0
- package/dist/examples/test-vue2/.eslintrc.js +174 -0
- package/dist/examples/test-vue2/.stylelintignore +50 -0
- package/dist/examples/test-vue2/.stylelintrc.js +79 -0
- package/dist/examples/test-vue2/README.md +139 -0
- package/dist/examples/test-vue2/babel.config.js +14 -0
- package/dist/examples/test-vue2/package.json +53 -0
- package/dist/examples/test-vue2/pnpm-lock.yaml +8776 -0
- package/dist/examples/test-vue2/public/index.html +19 -0
- package/dist/examples/test-vue2/setup.js +170 -0
- package/dist/examples/test-vue2/src/App.vue +943 -0
- package/dist/examples/test-vue2/src/components/BroadcastAPI.vue +666 -0
- package/dist/examples/test-vue2/src/components/CameraAPI.vue +414 -0
- package/dist/examples/test-vue2/src/components/GlobalConfig.vue +200 -0
- package/dist/examples/test-vue2/src/components/InfoCards.vue +294 -0
- package/dist/examples/test-vue2/src/components/InitAPI.vue +334 -0
- package/dist/examples/test-vue2/src/components/LogPanel.vue +249 -0
- package/dist/examples/test-vue2/src/components/MotionControlAPI.vue +400 -0
- package/dist/examples/test-vue2/src/components/UnityPreview.vue +201 -0
- package/dist/examples/test-vue2/src/main.js +16 -0
- package/dist/examples/test-vue2/vue.config.js +41 -0
- package/dist/examples/test-vue3/.eslintrc +3 -0
- package/dist/examples/test-vue3/.stylelintignore +3 -0
- package/dist/examples/test-vue3/.stylelintrc +48 -0
- package/dist/examples/test-vue3/README.md +236 -0
- package/dist/examples/test-vue3/env.d.ts +8 -0
- package/dist/examples/test-vue3/index.html +95 -0
- package/dist/examples/test-vue3/package.json +55 -0
- package/dist/examples/test-vue3/pnpm-lock.yaml +4636 -0
- package/dist/examples/test-vue3/setup.js +167 -0
- package/dist/examples/test-vue3/src/App.vue +962 -0
- package/dist/examples/test-vue3/src/components/BroadcastAPI.vue +636 -0
- package/dist/examples/test-vue3/src/components/CameraAPI.vue +376 -0
- package/dist/examples/test-vue3/src/components/GlobalConfig.vue +213 -0
- package/dist/examples/test-vue3/src/components/InfoCards.vue +288 -0
- package/dist/examples/test-vue3/src/components/InitAPI.vue +339 -0
- package/dist/examples/test-vue3/src/components/LogPanel.vue +236 -0
- package/dist/examples/test-vue3/src/components/MotionControlAPI.vue +373 -0
- package/dist/examples/test-vue3/src/components/UnityPreview.vue +189 -0
- package/dist/examples/test-vue3/src/main.ts +12 -0
- package/dist/examples/test-vue3/src/types.ts +9 -0
- package/dist/examples/test-vue3/tsconfig.json +44 -0
- package/dist/examples/test-vue3/tsconfig.node.json +14 -0
- package/dist/examples/test-vue3/vite.config.ts +75 -0
- package/dist/index.d.ts +15 -9
- package/dist/index.es5.js +64 -17
- package/dist/index.es5.umd.js +64 -17
- package/dist/index.esm.js +71 -16
- package/dist/index.umd.cjs +71 -16
- package/package.json +4 -3
|
@@ -0,0 +1,762 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>ZEE Avatar SDK - UMD+CDN 示例</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
10
|
+
max-width: 1200px;
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
padding: 20px;
|
|
13
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
14
|
+
min-height: 100vh;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.header {
|
|
18
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
19
|
+
color: white;
|
|
20
|
+
padding: 30px;
|
|
21
|
+
border-radius: 15px;
|
|
22
|
+
text-align: center;
|
|
23
|
+
margin-bottom: 30px;
|
|
24
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.header h1 {
|
|
28
|
+
margin: 0 0 10px 0;
|
|
29
|
+
font-size: 2.5rem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.header p {
|
|
33
|
+
margin: 0;
|
|
34
|
+
font-size: 1.2rem;
|
|
35
|
+
opacity: 0.9;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cdn-info {
|
|
39
|
+
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
|
40
|
+
color: white;
|
|
41
|
+
padding: 20px;
|
|
42
|
+
border-radius: 10px;
|
|
43
|
+
margin-bottom: 20px;
|
|
44
|
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.cdn-info h3 {
|
|
48
|
+
margin: 0 0 15px 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.cdn-info code {
|
|
52
|
+
background: rgba(255, 255, 255, 0.2);
|
|
53
|
+
padding: 2px 6px;
|
|
54
|
+
border-radius: 4px;
|
|
55
|
+
font-family: 'Courier New', monospace;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.container {
|
|
59
|
+
display: grid;
|
|
60
|
+
grid-template-columns: 400px 1fr;
|
|
61
|
+
gap: 30px;
|
|
62
|
+
margin-bottom: 30px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.panel {
|
|
66
|
+
background: white;
|
|
67
|
+
padding: 25px;
|
|
68
|
+
border-radius: 15px;
|
|
69
|
+
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.panel h3 {
|
|
73
|
+
margin: 0 0 20px 0;
|
|
74
|
+
color: #333;
|
|
75
|
+
border-bottom: 2px solid #667eea;
|
|
76
|
+
padding-bottom: 10px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#unity-container {
|
|
80
|
+
width: 100%;
|
|
81
|
+
height: 450px;
|
|
82
|
+
background: linear-gradient(45deg, #000 25%, #333 25%, #333 50%, #000 50%, #000 75%, #333 75%, #333);
|
|
83
|
+
background-size: 20px 20px;
|
|
84
|
+
border-radius: 10px;
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
color: white;
|
|
89
|
+
font-size: 18px;
|
|
90
|
+
text-align: center;
|
|
91
|
+
border: 2px solid #ddd;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.btn {
|
|
95
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
96
|
+
color: white;
|
|
97
|
+
border: none;
|
|
98
|
+
padding: 12px 24px;
|
|
99
|
+
border-radius: 8px;
|
|
100
|
+
cursor: pointer;
|
|
101
|
+
margin: 8px 4px;
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
font-weight: 600;
|
|
104
|
+
transition: all 0.3s ease;
|
|
105
|
+
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.btn:hover:not(:disabled) {
|
|
109
|
+
transform: translateY(-2px);
|
|
110
|
+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.btn:disabled {
|
|
114
|
+
background: #ccc;
|
|
115
|
+
cursor: not-allowed;
|
|
116
|
+
transform: none;
|
|
117
|
+
box-shadow: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.btn-group {
|
|
121
|
+
margin: 20px 0;
|
|
122
|
+
display: flex;
|
|
123
|
+
flex-wrap: wrap;
|
|
124
|
+
gap: 8px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.input-group {
|
|
128
|
+
margin: 15px 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.input-group label {
|
|
132
|
+
display: block;
|
|
133
|
+
margin-bottom: 8px;
|
|
134
|
+
font-weight: 600;
|
|
135
|
+
color: #333;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.input-group input,
|
|
139
|
+
.input-group textarea {
|
|
140
|
+
width: 100%;
|
|
141
|
+
padding: 12px;
|
|
142
|
+
border: 2px solid #ddd;
|
|
143
|
+
border-radius: 8px;
|
|
144
|
+
font-size: 14px;
|
|
145
|
+
transition: border-color 0.3s ease;
|
|
146
|
+
box-sizing: border-box;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.input-group input:focus,
|
|
150
|
+
.input-group textarea:focus {
|
|
151
|
+
outline: none;
|
|
152
|
+
border-color: #667eea;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.log-panel {
|
|
156
|
+
background: #f8f9fa;
|
|
157
|
+
border: 2px solid #dee2e6;
|
|
158
|
+
border-radius: 10px;
|
|
159
|
+
padding: 20px;
|
|
160
|
+
height: 300px;
|
|
161
|
+
overflow-y: auto;
|
|
162
|
+
font-family: 'Courier New', monospace;
|
|
163
|
+
font-size: 13px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.log-entry {
|
|
167
|
+
margin: 3px 0;
|
|
168
|
+
padding: 4px 0;
|
|
169
|
+
border-bottom: 1px solid #eee;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.log-info {
|
|
173
|
+
color: #007bff;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.log-success {
|
|
177
|
+
color: #28a745;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.log-error {
|
|
181
|
+
color: #dc3545;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.log-warning {
|
|
185
|
+
color: #ffc107;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.status-badge {
|
|
189
|
+
display: inline-block;
|
|
190
|
+
padding: 4px 12px;
|
|
191
|
+
border-radius: 20px;
|
|
192
|
+
font-size: 12px;
|
|
193
|
+
font-weight: bold;
|
|
194
|
+
margin: 5px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.status-ready {
|
|
198
|
+
background: #d4edda;
|
|
199
|
+
color: #155724;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.status-loading {
|
|
203
|
+
background: #fff3cd;
|
|
204
|
+
color: #856404;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.status-error {
|
|
208
|
+
background: #f8d7da;
|
|
209
|
+
color: #721c24;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@media (max-width: 768px) {
|
|
213
|
+
.container {
|
|
214
|
+
grid-template-columns: 1fr;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.header h1 {
|
|
218
|
+
font-size: 2rem;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
</style>
|
|
222
|
+
</head>
|
|
223
|
+
<body>
|
|
224
|
+
<div class="header">
|
|
225
|
+
<h1>🚀 ZEE Avatar SDK</h1>
|
|
226
|
+
<p>UMD + CDN 在线示例</p>
|
|
227
|
+
</div>
|
|
228
|
+
<div class="cdn-info">
|
|
229
|
+
<h3>📦 CDN 引入方式</h3>
|
|
230
|
+
<p><strong>🌐 当前使用:</strong> <code>https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1</code></p>
|
|
231
|
+
<p><strong>📋 全局变量:</strong> <code>window.ZEEAvatarSDKLib.ZEEAvatarSDK</code></p>
|
|
232
|
+
<p><strong>🔗 WebGL文件:</strong> 使用 CDN 资源文件</p>
|
|
233
|
+
</div>
|
|
234
|
+
<div class="container">
|
|
235
|
+
<div class="panel">
|
|
236
|
+
<h3>🎮 控制面板</h3>
|
|
237
|
+
<div class="input-group">
|
|
238
|
+
<label>🔑 认证Token:</label>
|
|
239
|
+
<input type="password" id="token" placeholder="请输入认证 token"/>
|
|
240
|
+
</div>
|
|
241
|
+
<div class="input-group">
|
|
242
|
+
<label>👤 数字人编码:</label>
|
|
243
|
+
<input type="text" id="avatarCode" placeholder="请输入数字人编码" value="DH_HUMAN_MODEL103_000003">
|
|
244
|
+
</div>
|
|
245
|
+
<div class="btn-group">
|
|
246
|
+
<button class="btn" onclick="initSDK()" id="initBtn">🚀 初始化SDK</button>
|
|
247
|
+
<button class="btn" onclick="loadAvatar()" disabled id="loadAvatarBtn">👤 加载数字人</button>
|
|
248
|
+
</div>
|
|
249
|
+
<div class="input-group">
|
|
250
|
+
<label>🗣️ 播报文本:</label>
|
|
251
|
+
<textarea id="broadcastText" rows="3" placeholder="请输入要播报的文本">欢迎使用紫为云3D数字人SDK!这是一个简单的演示示例。</textarea>
|
|
252
|
+
</div>
|
|
253
|
+
<div class="btn-group">
|
|
254
|
+
<button class="btn" onclick="startBroadcast()" disabled id="broadcastBtn">🗣️ 开始播报</button>
|
|
255
|
+
<button class="btn" onclick="stopBroadcast()" disabled id="stopBtn">⏹️ 停止播报</button>
|
|
256
|
+
</div>
|
|
257
|
+
<div class="input-group">
|
|
258
|
+
<label>🎭 动作编码:</label>
|
|
259
|
+
<input type="text" id="motionCode" placeholder="请输入动作编码" value="DH_ACTION_MODEL103_000023">
|
|
260
|
+
</div>
|
|
261
|
+
<div class="btn-group">
|
|
262
|
+
<button class="btn" onclick="playMotion()" disabled id="playMotionBtn">🎭 播放动作</button>
|
|
263
|
+
<button class="btn" onclick="setCameraType()" disabled id="setCameraBtn">📷 切换相机</button>
|
|
264
|
+
</div>
|
|
265
|
+
<div class="btn-group" style="border-top: 1px solid #eee; padding-top: 15px; margin-top: 20px;">
|
|
266
|
+
<button class="btn" onclick="unloadAvatar()" disabled id="unloadBtn">🗑️ 卸载数字人</button>
|
|
267
|
+
<button class="btn" onclick="destroySDK()" disabled id="destroyBtn">💥 销毁SDK</button>
|
|
268
|
+
</div>
|
|
269
|
+
<!-- 状态指示器 -->
|
|
270
|
+
<div style="margin-top: 20px;">
|
|
271
|
+
<div id="sdkStatus" class="status-badge status-error">SDK未初始化</div>
|
|
272
|
+
<div id="avatarStatus" class="status-badge status-error">数字人未加载</div>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
<div class="panel">
|
|
276
|
+
<h3>🖥️ Unity 渲染区域</h3>
|
|
277
|
+
<div id="unity-container">
|
|
278
|
+
<div class="unity-container-placeholder">
|
|
279
|
+
<div>🎮 Unity WebGL 容器</div>
|
|
280
|
+
<div style="font-size: 14px; margin-top: 10px; opacity: 0.7;"> 请先点击"初始化SDK"开始加载 </div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
<div class="panel">
|
|
286
|
+
<h3>📋 操作日志</h3>
|
|
287
|
+
<div class="log-panel" id="logPanel"></div>
|
|
288
|
+
<div class="btn-group">
|
|
289
|
+
<button class="btn" onclick="clearLogs()">🧹 清除日志</button>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
<!-- 使用 CDN 引入 SDK -->
|
|
293
|
+
<script src="https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1/dist/index.umd.cjs"></script>
|
|
294
|
+
<script>
|
|
295
|
+
// =====================================================
|
|
296
|
+
// 全局变量
|
|
297
|
+
// =====================================================
|
|
298
|
+
let sdk = null;
|
|
299
|
+
let currentCameraType = 'WHOLE'; // 当前相机类型
|
|
300
|
+
|
|
301
|
+
// 状态管理
|
|
302
|
+
const AppState = {
|
|
303
|
+
sdkInitialized: false,
|
|
304
|
+
avatarLoaded: false,
|
|
305
|
+
broadcasting: false
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// =====================================================
|
|
309
|
+
// 工具函数
|
|
310
|
+
// =====================================================
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* 添加日志条目
|
|
314
|
+
* @param {string} message - 日志消息
|
|
315
|
+
* @param {string} type - 日志类型 (info|success|error|warning)
|
|
316
|
+
*/
|
|
317
|
+
function addLog(message, type = 'info')
|
|
318
|
+
{
|
|
319
|
+
const logPanel = document.getElementById('logPanel');
|
|
320
|
+
const logEntry = document.createElement('div');
|
|
321
|
+
logEntry.className = `log-entry log-${type}`;
|
|
322
|
+
logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
|
|
323
|
+
logPanel.appendChild(logEntry);
|
|
324
|
+
logPanel.scrollTop = logPanel.scrollHeight;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* 清除所有日志
|
|
329
|
+
*/
|
|
330
|
+
function clearLogs()
|
|
331
|
+
{
|
|
332
|
+
document.getElementById('logPanel').innerHTML = '';
|
|
333
|
+
addLog('📝 日志已清除', 'info');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 更新状态指示器
|
|
338
|
+
*/
|
|
339
|
+
function updateStatus()
|
|
340
|
+
{
|
|
341
|
+
const sdkStatusEl = document.getElementById('sdkStatus');
|
|
342
|
+
const avatarStatusEl = document.getElementById('avatarStatus');
|
|
343
|
+
|
|
344
|
+
// 更新SDK状态
|
|
345
|
+
if (AppState.sdkInitialized)
|
|
346
|
+
{
|
|
347
|
+
sdkStatusEl.textContent = 'SDK已就绪';
|
|
348
|
+
sdkStatusEl.className = 'status-badge status-ready';
|
|
349
|
+
}
|
|
350
|
+
else
|
|
351
|
+
{
|
|
352
|
+
sdkStatusEl.textContent = 'SDK未初始化';
|
|
353
|
+
sdkStatusEl.className = 'status-badge status-error';
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 更新数字人状态
|
|
357
|
+
if (AppState.avatarLoaded)
|
|
358
|
+
{
|
|
359
|
+
avatarStatusEl.textContent = '数字人已加载';
|
|
360
|
+
avatarStatusEl.className = 'status-badge status-ready';
|
|
361
|
+
}
|
|
362
|
+
else
|
|
363
|
+
{
|
|
364
|
+
avatarStatusEl.textContent = '数字人未加载';
|
|
365
|
+
avatarStatusEl.className = 'status-badge status-error';
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
updateButtons();
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* 更新按钮状态
|
|
373
|
+
*/
|
|
374
|
+
function updateButtons()
|
|
375
|
+
{
|
|
376
|
+
const buttons = {
|
|
377
|
+
initBtn: document.getElementById('initBtn'),
|
|
378
|
+
loadAvatarBtn: document.getElementById('loadAvatarBtn'),
|
|
379
|
+
playMotionBtn: document.getElementById('playMotionBtn'),
|
|
380
|
+
broadcastBtn: document.getElementById('broadcastBtn'),
|
|
381
|
+
stopBtn: document.getElementById('stopBtn'),
|
|
382
|
+
setCameraBtn: document.getElementById('setCameraBtn'),
|
|
383
|
+
unloadBtn: document.getElementById('unloadBtn'),
|
|
384
|
+
destroyBtn: document.getElementById('destroyBtn')
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// 初始化按钮:SDK未初始化时才可用
|
|
388
|
+
buttons.initBtn.disabled = AppState.sdkInitialized;
|
|
389
|
+
|
|
390
|
+
// 加载数字人按钮:SDK已初始化但数字人未加载时可用
|
|
391
|
+
buttons.loadAvatarBtn.disabled = !AppState.sdkInitialized || AppState.avatarLoaded;
|
|
392
|
+
|
|
393
|
+
// 功能按钮:需要数字人已加载
|
|
394
|
+
buttons.playMotionBtn.disabled = !AppState.avatarLoaded;
|
|
395
|
+
buttons.setCameraBtn.disabled = !AppState.avatarLoaded;
|
|
396
|
+
|
|
397
|
+
// 播报按钮:需要数字人已加载且当前未在播报
|
|
398
|
+
buttons.broadcastBtn.disabled = !AppState.avatarLoaded || AppState.broadcasting;
|
|
399
|
+
|
|
400
|
+
// 停止播报按钮:仅在播报中可用
|
|
401
|
+
buttons.stopBtn.disabled = !AppState.broadcasting;
|
|
402
|
+
|
|
403
|
+
// 卸载按钮:数字人已加载时可用
|
|
404
|
+
buttons.unloadBtn.disabled = !AppState.avatarLoaded;
|
|
405
|
+
|
|
406
|
+
// 销毁按钮:SDK已初始化时可用
|
|
407
|
+
buttons.destroyBtn.disabled = !AppState.sdkInitialized;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function updateUnityPlaceholder(display)
|
|
411
|
+
{
|
|
412
|
+
const placeholder = document.querySelector('.unity-container-placeholder');
|
|
413
|
+
if (placeholder)
|
|
414
|
+
{
|
|
415
|
+
placeholder.style.display = display ? 'block' : 'none';
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// =====================================================
|
|
420
|
+
// SDK API 调用函数
|
|
421
|
+
// =====================================================
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* 初始化SDK
|
|
425
|
+
*/
|
|
426
|
+
async function initSDK()
|
|
427
|
+
{
|
|
428
|
+
try
|
|
429
|
+
{
|
|
430
|
+
addLog('🚀 开始初始化SDK...', 'info');
|
|
431
|
+
|
|
432
|
+
// 从全局变量获取SDK类
|
|
433
|
+
const {
|
|
434
|
+
ZEEAvatarSDK
|
|
435
|
+
} = window.ZEEAvatarSDKLib;
|
|
436
|
+
|
|
437
|
+
const config = {
|
|
438
|
+
// 使用CDN上的WebGL文件
|
|
439
|
+
// loaderUrl: 'https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1/dist/assets/Build/webgl.loader.js',
|
|
440
|
+
// dataUrl: 'https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1/dist/assets/Build/webgl.data.unityweb',
|
|
441
|
+
// frameworkUrl: 'https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1/dist/assets/Build/webgl.framework.js.unityweb',
|
|
442
|
+
// codeUrl: 'https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1/dist/assets/Build/webgl.wasm.unityweb',
|
|
443
|
+
// 使用本地WebGL文件
|
|
444
|
+
loaderUrl: './public/assets/Build/webgl.loader.js',
|
|
445
|
+
dataUrl: './public/assets/Build/webgl.data.unityweb',
|
|
446
|
+
frameworkUrl: './public/assets/Build/webgl.framework.js.unityweb',
|
|
447
|
+
codeUrl: './public/assets/Build/webgl.wasm.unityweb',
|
|
448
|
+
containerId: 'unity-container',
|
|
449
|
+
env: 'dev',
|
|
450
|
+
onProgress: (progress) =>
|
|
451
|
+
{
|
|
452
|
+
addLog(`📥 加载进度: ${Math.round(progress * 100)}%`, 'info');
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
sdk = new ZEEAvatarSDK(config);
|
|
457
|
+
|
|
458
|
+
AppState.sdkInitialized = true;
|
|
459
|
+
updateStatus();
|
|
460
|
+
addLog('✅ SDK初始化成功!', 'success');
|
|
461
|
+
}
|
|
462
|
+
catch (error)
|
|
463
|
+
{
|
|
464
|
+
addLog(`❌ SDK初始化失败: ${error.message}`, 'error');
|
|
465
|
+
console.error('SDK初始化失败:', error);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* 加载数字人
|
|
471
|
+
*/
|
|
472
|
+
async function loadAvatar()
|
|
473
|
+
{
|
|
474
|
+
try
|
|
475
|
+
{
|
|
476
|
+
const token = document.getElementById('token').value.trim();
|
|
477
|
+
const avatarCode = document.getElementById('avatarCode').value.trim();
|
|
478
|
+
|
|
479
|
+
if (!token || !avatarCode)
|
|
480
|
+
{
|
|
481
|
+
addLog('⚠️ 请填写认证Token和数字人编码', 'warning');
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
addLog('👤 开始加载数字人...', 'info');
|
|
486
|
+
|
|
487
|
+
// 设置token(使用正确的方法名)
|
|
488
|
+
sdk.updateToken(token);
|
|
489
|
+
|
|
490
|
+
updateUnityPlaceholder(false);
|
|
491
|
+
|
|
492
|
+
// 初始化数字人(使用正确的相机类型常量)
|
|
493
|
+
const response = await sdk.initializeAvatar(avatarCode, 'WHOLE');
|
|
494
|
+
|
|
495
|
+
if (response.success)
|
|
496
|
+
{
|
|
497
|
+
AppState.avatarLoaded = true;
|
|
498
|
+
updateStatus();
|
|
499
|
+
addLog('✅ 数字人加载成功!', 'success');
|
|
500
|
+
}
|
|
501
|
+
else
|
|
502
|
+
{
|
|
503
|
+
addLog(`❌ 数字人加载失败: ${response.message}`, 'error');
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
catch (error)
|
|
507
|
+
{
|
|
508
|
+
addLog(`❌ 数字人加载失败: ${error.message}`, 'error');
|
|
509
|
+
console.error('数字人加载失败:', error);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* 播放动作
|
|
515
|
+
*/
|
|
516
|
+
async function playMotion()
|
|
517
|
+
{
|
|
518
|
+
try
|
|
519
|
+
{
|
|
520
|
+
const motionCode = document.getElementById('motionCode').value.trim();
|
|
521
|
+
|
|
522
|
+
if (!motionCode)
|
|
523
|
+
{
|
|
524
|
+
addLog('⚠️ 请输入动作编码', 'warning');
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
addLog(`🎭 播放动作: ${motionCode}`, 'info');
|
|
529
|
+
const response = await sdk.playMotion(motionCode);
|
|
530
|
+
|
|
531
|
+
if (response.success)
|
|
532
|
+
{
|
|
533
|
+
addLog('✅ 动作播放成功!', 'success');
|
|
534
|
+
}
|
|
535
|
+
else
|
|
536
|
+
{
|
|
537
|
+
addLog(`❌ 动作播放失败: ${response.message}`, 'error');
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
catch (error)
|
|
541
|
+
{
|
|
542
|
+
addLog(`❌ 动作播放失败: ${error.message}`, 'error');
|
|
543
|
+
console.error('动作播放失败:', error);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* 开始播报
|
|
549
|
+
*/
|
|
550
|
+
async function startBroadcast()
|
|
551
|
+
{
|
|
552
|
+
try
|
|
553
|
+
{
|
|
554
|
+
const avatarCode = document.getElementById('avatarCode').value.trim();
|
|
555
|
+
const text = document.getElementById('broadcastText').value.trim();
|
|
556
|
+
|
|
557
|
+
if (!text)
|
|
558
|
+
{
|
|
559
|
+
addLog('⚠️ 请输入播报文本', 'warning');
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
addLog('🗣️ 开始文本播报...', 'info');
|
|
564
|
+
|
|
565
|
+
// 准备播报参数(按照实际接口定义)
|
|
566
|
+
const broadcastParams = {
|
|
567
|
+
type: 'text', // BroadcastType.TEXT
|
|
568
|
+
humanCode: avatarCode,
|
|
569
|
+
text,
|
|
570
|
+
voiceCode: 'woman008',
|
|
571
|
+
isSubtitle: false
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
// 设置播报回调(通过SDK配置或updateBroadcastCallbacks方法)
|
|
575
|
+
const callbacks = {
|
|
576
|
+
onStart: () =>
|
|
577
|
+
{
|
|
578
|
+
AppState.broadcasting = true;
|
|
579
|
+
updateButtons();
|
|
580
|
+
addLog('🎙️ 播报已开始', 'success');
|
|
581
|
+
},
|
|
582
|
+
onFinish: () =>
|
|
583
|
+
{
|
|
584
|
+
AppState.broadcasting = false;
|
|
585
|
+
updateButtons();
|
|
586
|
+
addLog('✅ 播报已结束', 'success');
|
|
587
|
+
},
|
|
588
|
+
onError: (error) =>
|
|
589
|
+
{
|
|
590
|
+
AppState.broadcasting = false;
|
|
591
|
+
updateButtons();
|
|
592
|
+
addLog(`❌ 播报出错: ${error.message}`, 'error');
|
|
593
|
+
},
|
|
594
|
+
onStop: () =>
|
|
595
|
+
{
|
|
596
|
+
AppState.broadcasting = false;
|
|
597
|
+
updateButtons();
|
|
598
|
+
addLog('⏹️ 播报已停止', 'success');
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
// 更新播报回调
|
|
603
|
+
sdk.updateBroadcastCallbacks(callbacks);
|
|
604
|
+
|
|
605
|
+
// 开始播报(只传递一个参数)
|
|
606
|
+
await sdk.startBroadcast(broadcastParams);
|
|
607
|
+
}
|
|
608
|
+
catch (error)
|
|
609
|
+
{
|
|
610
|
+
AppState.broadcasting = false;
|
|
611
|
+
updateButtons();
|
|
612
|
+
addLog(`❌ 播报失败: ${error.message}`, 'error');
|
|
613
|
+
console.error('播报失败:', error);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* 停止播报
|
|
619
|
+
*/
|
|
620
|
+
async function stopBroadcast()
|
|
621
|
+
{
|
|
622
|
+
try
|
|
623
|
+
{
|
|
624
|
+
addLog('⏹️ 停止播报...', 'info');
|
|
625
|
+
await sdk.stopBroadcast();
|
|
626
|
+
AppState.broadcasting = false;
|
|
627
|
+
updateButtons();
|
|
628
|
+
addLog('✅ 播报已停止', 'success');
|
|
629
|
+
}
|
|
630
|
+
catch (error)
|
|
631
|
+
{
|
|
632
|
+
addLog(`❌ 停止播报失败: ${error.message}`, 'error');
|
|
633
|
+
console.error('停止播报失败:', error);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* 切换相机类型
|
|
639
|
+
*/
|
|
640
|
+
async function setCameraType()
|
|
641
|
+
{
|
|
642
|
+
try
|
|
643
|
+
{
|
|
644
|
+
// 循环切换相机类型
|
|
645
|
+
const cameraTypes = ['whole', 'half', 'face'];
|
|
646
|
+
const currentIndex = cameraTypes.indexOf(currentCameraType);
|
|
647
|
+
const nextIndex = (currentIndex + 1) % cameraTypes.length;
|
|
648
|
+
const nextCameraType = cameraTypes[nextIndex];
|
|
649
|
+
|
|
650
|
+
addLog(`📷 切换相机类型: ${currentCameraType} → ${nextCameraType}`, 'info');
|
|
651
|
+
|
|
652
|
+
// 使用正确的方法名 setCamera
|
|
653
|
+
const response = await sdk.setCamera(nextCameraType);
|
|
654
|
+
|
|
655
|
+
if (response.success)
|
|
656
|
+
{
|
|
657
|
+
currentCameraType = nextCameraType;
|
|
658
|
+
addLog(`✅ 相机类型已切换为: ${nextCameraType}`, 'success');
|
|
659
|
+
}
|
|
660
|
+
else
|
|
661
|
+
{
|
|
662
|
+
addLog(`❌ 相机切换失败: ${response.message}`, 'error');
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
catch (error)
|
|
666
|
+
{
|
|
667
|
+
addLog(`❌ 相机切换失败: ${error.message}`, 'error');
|
|
668
|
+
console.error('相机切换失败:', error);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* 卸载数字人
|
|
674
|
+
*/
|
|
675
|
+
async function unloadAvatar()
|
|
676
|
+
{
|
|
677
|
+
try
|
|
678
|
+
{
|
|
679
|
+
addLog('🗑️ 卸载数字人...', 'info');
|
|
680
|
+
|
|
681
|
+
const response = await sdk.unloadAvatar();
|
|
682
|
+
|
|
683
|
+
if (response.success)
|
|
684
|
+
{
|
|
685
|
+
AppState.avatarLoaded = false;
|
|
686
|
+
AppState.broadcasting = false;
|
|
687
|
+
currentCameraType = 'WHOLE';
|
|
688
|
+
updateStatus();
|
|
689
|
+
updateUnityPlaceholder(true);
|
|
690
|
+
addLog('✅ 数字人已卸载!', 'success');
|
|
691
|
+
}
|
|
692
|
+
else
|
|
693
|
+
{
|
|
694
|
+
addLog(`❌ 卸载失败: ${response.message}`, 'error');
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
catch (error)
|
|
698
|
+
{
|
|
699
|
+
addLog(`❌ 卸载失败: ${error.message}`, 'error');
|
|
700
|
+
console.error('卸载失败:', error);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* 销毁SDK
|
|
706
|
+
*/
|
|
707
|
+
function destroySDK()
|
|
708
|
+
{
|
|
709
|
+
try
|
|
710
|
+
{
|
|
711
|
+
if (sdk)
|
|
712
|
+
{
|
|
713
|
+
addLog('💥 销毁SDK...', 'warning');
|
|
714
|
+
sdk.destroy();
|
|
715
|
+
sdk = null;
|
|
716
|
+
|
|
717
|
+
// 重置所有状态
|
|
718
|
+
AppState.sdkInitialized = false;
|
|
719
|
+
AppState.avatarLoaded = false;
|
|
720
|
+
AppState.broadcasting = false;
|
|
721
|
+
currentCameraType = 'WHOLE';
|
|
722
|
+
updateUnityPlaceholder(true);
|
|
723
|
+
updateStatus();
|
|
724
|
+
addLog('✅ SDK已销毁!', 'warning');
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
catch (error)
|
|
728
|
+
{
|
|
729
|
+
addLog(`❌ 销毁失败: ${error.message}`, 'error');
|
|
730
|
+
console.error('销毁失败:', error);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// =====================================================
|
|
735
|
+
// 页面生命周期
|
|
736
|
+
// =====================================================
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* 页面加载完成事件处理
|
|
740
|
+
*/
|
|
741
|
+
document.addEventListener('DOMContentLoaded', () =>
|
|
742
|
+
{
|
|
743
|
+
addLog('🌐 页面加载完成', 'info');
|
|
744
|
+
addLog('📦 SDK版本: 通过CDN加载', 'info');
|
|
745
|
+
addLog('🔗 CDN地址: https://unpkg.com/@zeewain/3d-avatar-sdk@1.2.1', 'info');
|
|
746
|
+
addLog('📖 请按顺序操作:初始化SDK → 加载数字人 → 测试功能', 'info');
|
|
747
|
+
|
|
748
|
+
// 检查SDK是否成功加载
|
|
749
|
+
if (window.ZEEAvatarSDKLib && window.ZEEAvatarSDKLib.ZEEAvatarSDK)
|
|
750
|
+
{
|
|
751
|
+
addLog('✅ SDK库加载成功', 'success');
|
|
752
|
+
}
|
|
753
|
+
else
|
|
754
|
+
{
|
|
755
|
+
addLog('❌ SDK库加载失败,请检查网络连接', 'error');
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
updateStatus();
|
|
759
|
+
});
|
|
760
|
+
</script>
|
|
761
|
+
</body>
|
|
762
|
+
</html>
|