@spatialwalk/avatarkit 1.0.0-beta.69 → 1.0.0-beta.70
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/CHANGELOG.md +6 -0
- package/dist/{StreamingAudioPlayer-DiIRp5nx.js → StreamingAudioPlayer-Bi2685bX.js} +1 -1
- package/dist/config/app-config.d.ts +3 -3
- package/dist/config/sdk-config-loader.d.ts +4 -13
- package/dist/core/Avatar.d.ts +0 -8
- package/dist/core/AvatarController.d.ts +0 -82
- package/dist/core/AvatarManager.d.ts +0 -8
- package/dist/core/AvatarSDK.d.ts +0 -13
- package/dist/core/AvatarView.d.ts +0 -141
- package/dist/{index-BT9yxWW8.js → index-CvW_c7G-.js} +273 -196
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/renderer/covariance.d.ts +3 -10
- package/dist/renderer/sortSplats.d.ts +3 -9
- package/dist/renderer/webgl/reorderData.d.ts +4 -10
- package/dist/types/character.d.ts +3 -3
- package/dist/types/index.d.ts +0 -8
- package/dist/utils/animation-interpolation.d.ts +4 -34
- package/dist/utils/client-id.d.ts +2 -2
- package/dist/utils/conversationId.d.ts +6 -15
- package/dist/utils/id-manager.d.ts +3 -33
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/posthog-tracker.d.ts +6 -31
- package/dist/utils/pwa-cache-manager.d.ts +0 -35
- package/dist/utils/usage-tracker.d.ts +3 -17
- package/dist/wasm/avatarCoreAdapter.d.ts +4 -175
- package/package.json +1 -1
|
@@ -3,10 +3,11 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
class Avatar {
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @param id
|
|
8
|
-
* @param characterMeta
|
|
9
|
-
* @param resources
|
|
6
|
+
* Constructor (internal use)
|
|
7
|
+
* @param id Avatar ID
|
|
8
|
+
* @param characterMeta Character metadata
|
|
9
|
+
* @param resources Resource data
|
|
10
|
+
* @internal
|
|
10
11
|
*/
|
|
11
12
|
constructor(id, characterMeta, resources) {
|
|
12
13
|
__publicField(this, "id");
|
|
@@ -24,7 +25,7 @@ class Avatar {
|
|
|
24
25
|
return this.characterMeta;
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
+
* Update character metadata (internal use)
|
|
28
29
|
* @internal
|
|
29
30
|
*/
|
|
30
31
|
updateCharacterMeta(newMeta) {
|
|
@@ -34,7 +35,7 @@ class Avatar {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
|
-
*
|
|
38
|
+
* Get resource data (internal use)
|
|
38
39
|
* @internal
|
|
39
40
|
*/
|
|
40
41
|
getResources() {
|
|
@@ -1433,14 +1434,14 @@ const APP_CONFIG = {
|
|
|
1433
1434
|
},
|
|
1434
1435
|
animation: {
|
|
1435
1436
|
fps: 25
|
|
1436
|
-
//
|
|
1437
|
+
// Animation frame rate (load animation resources from CharacterMeta)
|
|
1437
1438
|
},
|
|
1438
1439
|
audio: {
|
|
1439
1440
|
sampleRate: 16e3
|
|
1440
|
-
//
|
|
1441
|
+
// Audio sample rate (backend requires 16kHz)
|
|
1441
1442
|
},
|
|
1442
|
-
// FLAME
|
|
1443
|
-
//
|
|
1443
|
+
// FLAME global template resource CDN
|
|
1444
|
+
// These resources are base templates shared by all characters
|
|
1444
1445
|
flame: {
|
|
1445
1446
|
cdnBaseUrl: "https://cdn.spatialwalk.top/public",
|
|
1446
1447
|
resources: {
|
|
@@ -7482,7 +7483,7 @@ class IdManager {
|
|
|
7482
7483
|
});
|
|
7483
7484
|
this.ids.clientId = getOrCreateClientId();
|
|
7484
7485
|
}
|
|
7485
|
-
// ==========
|
|
7486
|
+
// ========== Global IDs ==========
|
|
7486
7487
|
getClientId() {
|
|
7487
7488
|
return this.ids.clientId;
|
|
7488
7489
|
}
|
|
@@ -7504,16 +7505,18 @@ class IdManager {
|
|
|
7504
7505
|
getSessionToken() {
|
|
7505
7506
|
return this.ids.sessionToken;
|
|
7506
7507
|
}
|
|
7507
|
-
// ==========
|
|
7508
|
+
// ========== Connection Level IDs ==========
|
|
7508
7509
|
/**
|
|
7509
|
-
*
|
|
7510
|
+
* Generate new connectionId (for WebSocket connection)
|
|
7511
|
+
* @internal
|
|
7510
7512
|
*/
|
|
7511
7513
|
generateConnectionId() {
|
|
7512
7514
|
this.ids.connectionId = generateConversationId();
|
|
7513
7515
|
return this.ids.connectionId;
|
|
7514
7516
|
}
|
|
7515
7517
|
/**
|
|
7516
|
-
*
|
|
7518
|
+
* Set connectionId (for connectionId received from server)
|
|
7519
|
+
* @internal
|
|
7517
7520
|
*/
|
|
7518
7521
|
setConnectionId(connectionId) {
|
|
7519
7522
|
this.ids.connectionId = connectionId;
|
|
@@ -7524,9 +7527,10 @@ class IdManager {
|
|
|
7524
7527
|
clearConnectionId() {
|
|
7525
7528
|
this.ids.connectionId = null;
|
|
7526
7529
|
}
|
|
7527
|
-
// ==========
|
|
7530
|
+
// ========== Session Level IDs ==========
|
|
7528
7531
|
/**
|
|
7529
|
-
*
|
|
7532
|
+
* Generate new conversationId (for each conversation)
|
|
7533
|
+
* @internal
|
|
7530
7534
|
*/
|
|
7531
7535
|
generateNewConversationId() {
|
|
7532
7536
|
this.ids.conversationId = generateConversationId();
|
|
@@ -7541,15 +7545,17 @@ class IdManager {
|
|
|
7541
7545
|
clearConversationId() {
|
|
7542
7546
|
this.ids.conversationId = null;
|
|
7543
7547
|
}
|
|
7544
|
-
// ==========
|
|
7548
|
+
// ========== Batch Get (for PostHog logging) ==========
|
|
7545
7549
|
/**
|
|
7546
|
-
*
|
|
7550
|
+
* Get all IDs (for log reporting)
|
|
7551
|
+
* @internal
|
|
7547
7552
|
*/
|
|
7548
7553
|
getAllIds() {
|
|
7549
7554
|
return { ...this.ids };
|
|
7550
7555
|
}
|
|
7551
7556
|
/**
|
|
7552
|
-
*
|
|
7557
|
+
* Get public log parameters (contains all necessary IDs)
|
|
7558
|
+
* @internal
|
|
7553
7559
|
*/
|
|
7554
7560
|
getLogContext() {
|
|
7555
7561
|
return {
|
|
@@ -7561,7 +7567,8 @@ class IdManager {
|
|
|
7561
7567
|
};
|
|
7562
7568
|
}
|
|
7563
7569
|
/**
|
|
7564
|
-
*
|
|
7570
|
+
* Clear all IDs (for testing or reset)
|
|
7571
|
+
* @internal
|
|
7565
7572
|
*/
|
|
7566
7573
|
clear() {
|
|
7567
7574
|
this.ids.userId = null;
|
|
@@ -7604,15 +7611,15 @@ function initializePostHog(environment, version) {
|
|
|
7604
7611
|
api_host: host,
|
|
7605
7612
|
person_profiles: "identified_only",
|
|
7606
7613
|
capture_pageview: false,
|
|
7607
|
-
// SDK
|
|
7614
|
+
// SDK doesn't need automatic page view capture
|
|
7608
7615
|
capture_pageleave: false,
|
|
7609
|
-
// SDK
|
|
7616
|
+
// SDK doesn't need automatic page leave capture
|
|
7610
7617
|
disable_compression: disableCompression,
|
|
7611
|
-
//
|
|
7618
|
+
// Configure compression based on environment: disabled in CN, enabled in INT
|
|
7612
7619
|
disable_session_recording: true,
|
|
7613
|
-
//
|
|
7620
|
+
// Disable Session Recording to avoid additional requests and errors
|
|
7614
7621
|
autocapture: false,
|
|
7615
|
-
//
|
|
7622
|
+
// Disable autocapture, only report SDK custom events
|
|
7616
7623
|
loaded: (posthogInstance) => {
|
|
7617
7624
|
logger.log(`[PostHog] Initialized successfully - environment: ${environment}, host: ${host}, instance: ${SDK_POSTHOG_INSTANCE_NAME}`);
|
|
7618
7625
|
isInitialized = true;
|
|
@@ -7698,19 +7705,19 @@ function trackEvent(event, level = "info", contents = {}) {
|
|
|
7698
7705
|
try {
|
|
7699
7706
|
const logContext = idManager.getLogContext();
|
|
7700
7707
|
const properties = {
|
|
7701
|
-
//
|
|
7708
|
+
// Basic properties
|
|
7702
7709
|
service_module: "sdk",
|
|
7703
7710
|
platform: "Web",
|
|
7704
7711
|
sdk_version: sdkVersion,
|
|
7705
7712
|
level,
|
|
7706
7713
|
environment: currentEnvironment || "unknown",
|
|
7707
|
-
// ID
|
|
7714
|
+
// ID information
|
|
7708
7715
|
app_id: logContext.app_id,
|
|
7709
7716
|
user_id: logContext.user_id,
|
|
7710
7717
|
client_id: logContext.client_id,
|
|
7711
|
-
//
|
|
7718
|
+
// Timestamp
|
|
7712
7719
|
timestamp: Date.now(),
|
|
7713
|
-
//
|
|
7720
|
+
// Custom contents
|
|
7714
7721
|
...contents
|
|
7715
7722
|
};
|
|
7716
7723
|
if (logContext.connection_id) {
|
|
@@ -7845,7 +7852,7 @@ const _AnimationPlayer = class _AnimationPlayer {
|
|
|
7845
7852
|
if (this.streamingPlayer) {
|
|
7846
7853
|
return;
|
|
7847
7854
|
}
|
|
7848
|
-
const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-
|
|
7855
|
+
const { StreamingAudioPlayer } = await import("./StreamingAudioPlayer-Bi2685bX.js");
|
|
7849
7856
|
const { AvatarSDK: AvatarSDK2 } = await Promise.resolve().then(() => AvatarSDK$1);
|
|
7850
7857
|
const audioFormat = AvatarSDK2.getAudioFormat();
|
|
7851
7858
|
this.streamingPlayer = new StreamingAudioPlayer({
|
|
@@ -8039,7 +8046,7 @@ async function fetchSdkConfig(version) {
|
|
|
8039
8046
|
logger.log(`[SdkConfigLoader] Fetching SDK config from: ${configUrl}`);
|
|
8040
8047
|
const response = await fetch(configUrl, {
|
|
8041
8048
|
method: "GET"
|
|
8042
|
-
// GET
|
|
8049
|
+
// GET request doesn't need Content-Type header, avoid triggering CORS preflight
|
|
8043
8050
|
});
|
|
8044
8051
|
if (!response.ok) {
|
|
8045
8052
|
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
@@ -8486,17 +8493,18 @@ class AvatarCoreAdapter {
|
|
|
8486
8493
|
};
|
|
8487
8494
|
}
|
|
8488
8495
|
/**
|
|
8489
|
-
*
|
|
8490
|
-
*
|
|
8496
|
+
* Load WASM module and setup API
|
|
8497
|
+
* Creates a completely new WASM instance each time, ensuring C++ memory is clean
|
|
8491
8498
|
*
|
|
8492
|
-
*
|
|
8493
|
-
* Vite
|
|
8494
|
-
*
|
|
8499
|
+
* Note: Uses dynamic import() to import WASM module.
|
|
8500
|
+
* Vite automatically adds hash to WASM files and JS glue code during build (e.g., avatar_core_wasm-CxWuw7eS.wasm),
|
|
8501
|
+
* ensuring browser cache is consistent with version, no cache issues.
|
|
8495
8502
|
*
|
|
8496
|
-
* Hash
|
|
8497
|
-
* - WASM
|
|
8498
|
-
* - WASM
|
|
8499
|
-
* - Emscripten
|
|
8503
|
+
* Hash mechanism:
|
|
8504
|
+
* - WASM file content changes → hash automatically changes → URL changes → browser fetches new version
|
|
8505
|
+
* - WASM file content unchanged → hash remains same → URL unchanged → browser uses cache
|
|
8506
|
+
* - Emscripten-generated JS internally uses hard-coded hash path to load .wasm file
|
|
8507
|
+
* @internal
|
|
8500
8508
|
*/
|
|
8501
8509
|
async loadWASMModule() {
|
|
8502
8510
|
try {
|
|
@@ -8516,7 +8524,8 @@ class AvatarCoreAdapter {
|
|
|
8516
8524
|
}
|
|
8517
8525
|
}
|
|
8518
8526
|
/**
|
|
8519
|
-
*
|
|
8527
|
+
* Validate WASM module functionality
|
|
8528
|
+
* @internal
|
|
8520
8529
|
*/
|
|
8521
8530
|
validateWASMModule() {
|
|
8522
8531
|
const requiredFunctions = ["cwrap", "_malloc", "_free", "setValue", "getValue", "writeArrayToMemory"];
|
|
@@ -8528,7 +8537,8 @@ class AvatarCoreAdapter {
|
|
|
8528
8537
|
this.initializeMemoryViews();
|
|
8529
8538
|
}
|
|
8530
8539
|
/**
|
|
8531
|
-
*
|
|
8540
|
+
* Initialize memory views
|
|
8541
|
+
* @internal
|
|
8532
8542
|
*/
|
|
8533
8543
|
initializeMemoryViews() {
|
|
8534
8544
|
try {
|
|
@@ -8549,13 +8559,14 @@ class AvatarCoreAdapter {
|
|
|
8549
8559
|
}
|
|
8550
8560
|
}
|
|
8551
8561
|
/**
|
|
8552
|
-
*
|
|
8562
|
+
* Setup C API function wrappers
|
|
8563
|
+
* @internal
|
|
8553
8564
|
*/
|
|
8554
8565
|
setupCAPIFunctions() {
|
|
8555
8566
|
this.api = {
|
|
8556
|
-
//
|
|
8567
|
+
// Core system management
|
|
8557
8568
|
initialize: this.wasmModule.cwrap("avatar_core_initialize", "number", ["number"]),
|
|
8558
|
-
//
|
|
8569
|
+
// Returns handle
|
|
8559
8570
|
release: this.wasmModule.cwrap("avatar_core_release", null, ["number"]),
|
|
8560
8571
|
getVersion: this.wasmModule.cwrap("avatar_core_get_version", "string", []),
|
|
8561
8572
|
getErrorString: this.wasmModule.cwrap("avatar_core_get_error_string", "string", ["number"]),
|
|
@@ -8587,17 +8598,15 @@ class AvatarCoreAdapter {
|
|
|
8587
8598
|
setGazeTarget: this.wasmModule.cwrap("avatar_core_set_gaze_target", "number", ["number", "number", "number", "number", "number"]),
|
|
8588
8599
|
// core, character, x, y, z
|
|
8589
8600
|
resetEyeTracking: this.wasmModule.cwrap("avatar_core_reset_eye_tracking", "number", ["number"]),
|
|
8590
|
-
// FLAME
|
|
8601
|
+
// FLAME information query
|
|
8591
8602
|
getFlameInfo: this.wasmModule.cwrap("avatar_core_get_flame_info", "number", ["number", "number", "number", "number"])
|
|
8592
8603
|
};
|
|
8593
8604
|
}
|
|
8594
8605
|
/**
|
|
8595
|
-
*
|
|
8596
|
-
*/
|
|
8597
|
-
/**
|
|
8598
|
-
* Get current frame parameters
|
|
8606
|
+
* Get current frame parameters (for transitions or debugging)
|
|
8599
8607
|
* @param frameIndex Frame index
|
|
8600
8608
|
* @param characterId Optional character ID for multi-character support
|
|
8609
|
+
* @internal
|
|
8601
8610
|
*/
|
|
8602
8611
|
async getCurrentFrameParams(frameIndex = 0, characterId) {
|
|
8603
8612
|
const paramsPtr = await this.getAnimationFrameParams(frameIndex, characterId);
|
|
@@ -8609,7 +8618,8 @@ class AvatarCoreAdapter {
|
|
|
8609
8618
|
}
|
|
8610
8619
|
}
|
|
8611
8620
|
/**
|
|
8612
|
-
*
|
|
8621
|
+
* Initialize Avatar Core
|
|
8622
|
+
* @internal
|
|
8613
8623
|
*/
|
|
8614
8624
|
async initializeAvatarCore(templateResources) {
|
|
8615
8625
|
try {
|
|
@@ -8626,7 +8636,8 @@ class AvatarCoreAdapter {
|
|
|
8626
8636
|
}
|
|
8627
8637
|
}
|
|
8628
8638
|
/**
|
|
8629
|
-
*
|
|
8639
|
+
* Load template resources (from preloaded ArrayBuffers)
|
|
8640
|
+
* @internal
|
|
8630
8641
|
*/
|
|
8631
8642
|
async loadTemplateResourcesFromBuffers(templateResources) {
|
|
8632
8643
|
const formattedResources = {
|
|
@@ -8652,14 +8663,13 @@ class AvatarCoreAdapter {
|
|
|
8652
8663
|
}
|
|
8653
8664
|
}
|
|
8654
8665
|
/**
|
|
8655
|
-
*
|
|
8656
|
-
*/
|
|
8657
|
-
/**
|
|
8666
|
+
* Load character data (from preloaded ArrayBuffers)
|
|
8658
8667
|
* Load character from buffers and return handle
|
|
8659
8668
|
* @param shapeBuffer Shape data buffer
|
|
8660
8669
|
* @param pointCloudBuffer Point cloud data buffer
|
|
8661
8670
|
* @param characterId Optional character ID for multi-character support
|
|
8662
8671
|
* @returns Character handle
|
|
8672
|
+
* @internal
|
|
8663
8673
|
*/
|
|
8664
8674
|
async loadCharacterFromBuffers(shapeBuffer, pointCloudBuffer, characterId) {
|
|
8665
8675
|
if (!this.isInitialized) {
|
|
@@ -8762,8 +8772,9 @@ class AvatarCoreAdapter {
|
|
|
8762
8772
|
}
|
|
8763
8773
|
}
|
|
8764
8774
|
/**
|
|
8765
|
-
*
|
|
8775
|
+
* Get total animation frames
|
|
8766
8776
|
* @param animationHandle Optional animation handle (for multi-character support)
|
|
8777
|
+
* @internal
|
|
8767
8778
|
*/
|
|
8768
8779
|
async getAnimationTotalFrames(animationHandle) {
|
|
8769
8780
|
const handle = animationHandle || this.animationHandle;
|
|
@@ -8791,9 +8802,10 @@ class AvatarCoreAdapter {
|
|
|
8791
8802
|
}
|
|
8792
8803
|
}
|
|
8793
8804
|
/**
|
|
8794
|
-
*
|
|
8805
|
+
* Get specified frame parameters from animation
|
|
8795
8806
|
* @param frameIndex Frame index
|
|
8796
8807
|
* @param characterId Optional character ID for multi-character support
|
|
8808
|
+
* @internal
|
|
8797
8809
|
*/
|
|
8798
8810
|
async getAnimationFrameParams(frameIndex = 0, characterId) {
|
|
8799
8811
|
const id = characterId || "default";
|
|
@@ -8832,9 +8844,10 @@ class AvatarCoreAdapter {
|
|
|
8832
8844
|
}
|
|
8833
8845
|
}
|
|
8834
8846
|
/**
|
|
8835
|
-
*
|
|
8847
|
+
* Set eye tracking configuration (aligned with app implementation)
|
|
8836
8848
|
* @param config Eye tracking configuration
|
|
8837
8849
|
* @param characterId Optional character ID for multi-character support
|
|
8850
|
+
* @internal
|
|
8838
8851
|
*/
|
|
8839
8852
|
async setEyeTrackingConfig(config, characterId) {
|
|
8840
8853
|
if (!this.isCharacterLoaded) {
|
|
@@ -8861,11 +8874,12 @@ class AvatarCoreAdapter {
|
|
|
8861
8874
|
}
|
|
8862
8875
|
}
|
|
8863
8876
|
/**
|
|
8864
|
-
*
|
|
8877
|
+
* Set eye tracking target (advanced feature)
|
|
8865
8878
|
* @param x Target X coordinate
|
|
8866
8879
|
* @param y Target Y coordinate
|
|
8867
8880
|
* @param z Target Z coordinate
|
|
8868
8881
|
* @param characterId Optional character ID for multi-character support
|
|
8882
|
+
* @internal
|
|
8869
8883
|
*/
|
|
8870
8884
|
async setGazeTarget(x2, y2, z2, characterId) {
|
|
8871
8885
|
if (!this.isCharacterLoaded) {
|
|
@@ -8887,7 +8901,8 @@ class AvatarCoreAdapter {
|
|
|
8887
8901
|
}
|
|
8888
8902
|
}
|
|
8889
8903
|
/**
|
|
8890
|
-
*
|
|
8904
|
+
* Reset eye tracking
|
|
8905
|
+
* @internal
|
|
8891
8906
|
*/
|
|
8892
8907
|
async resetEyeTracking() {
|
|
8893
8908
|
if (!this.isCharacterLoaded) {
|
|
@@ -8904,7 +8919,8 @@ class AvatarCoreAdapter {
|
|
|
8904
8919
|
}
|
|
8905
8920
|
}
|
|
8906
8921
|
/**
|
|
8907
|
-
*
|
|
8922
|
+
* Query FLAME model information
|
|
8923
|
+
* @internal
|
|
8908
8924
|
*/
|
|
8909
8925
|
async queryFlameInfo() {
|
|
8910
8926
|
try {
|
|
@@ -8931,7 +8947,8 @@ class AvatarCoreAdapter {
|
|
|
8931
8947
|
}
|
|
8932
8948
|
}
|
|
8933
8949
|
/**
|
|
8934
|
-
*
|
|
8950
|
+
* Query character information
|
|
8951
|
+
* @internal
|
|
8935
8952
|
*/
|
|
8936
8953
|
async queryCharacterInfo() {
|
|
8937
8954
|
try {
|
|
@@ -8954,7 +8971,8 @@ class AvatarCoreAdapter {
|
|
|
8954
8971
|
}
|
|
8955
8972
|
}
|
|
8956
8973
|
/**
|
|
8957
|
-
*
|
|
8974
|
+
* Check error code and throw exception
|
|
8975
|
+
* @internal
|
|
8958
8976
|
*/
|
|
8959
8977
|
checkError(errorCode, functionName) {
|
|
8960
8978
|
if (errorCode !== 0) {
|
|
@@ -8965,7 +8983,8 @@ class AvatarCoreAdapter {
|
|
|
8965
8983
|
}
|
|
8966
8984
|
}
|
|
8967
8985
|
/**
|
|
8968
|
-
*
|
|
8986
|
+
* Update progress callback
|
|
8987
|
+
* @internal
|
|
8969
8988
|
*/
|
|
8970
8989
|
async updateProgress(callback, message, progress) {
|
|
8971
8990
|
if (callback && typeof callback === "function") {
|
|
@@ -8973,7 +8992,8 @@ class AvatarCoreAdapter {
|
|
|
8973
8992
|
}
|
|
8974
8993
|
}
|
|
8975
8994
|
/**
|
|
8976
|
-
*
|
|
8995
|
+
* Get performance metrics
|
|
8996
|
+
* @internal
|
|
8977
8997
|
*/
|
|
8978
8998
|
getPerformanceMetrics() {
|
|
8979
8999
|
var _a, _b;
|
|
@@ -8985,9 +9005,10 @@ class AvatarCoreAdapter {
|
|
|
8985
9005
|
};
|
|
8986
9006
|
}
|
|
8987
9007
|
/**
|
|
8988
|
-
*
|
|
8989
|
-
* @param characterHandle
|
|
8990
|
-
* @returns
|
|
9008
|
+
* Get character point cloud count
|
|
9009
|
+
* @param characterHandle Character handle (optional, defaults to current character)
|
|
9010
|
+
* @returns Point cloud count, or null if character not loaded
|
|
9011
|
+
* @internal
|
|
8991
9012
|
*/
|
|
8992
9013
|
getPointCount(characterHandle) {
|
|
8993
9014
|
if (!this.isCharacterLoaded) {
|
|
@@ -9016,12 +9037,11 @@ class AvatarCoreAdapter {
|
|
|
9016
9037
|
}
|
|
9017
9038
|
}
|
|
9018
9039
|
/**
|
|
9019
|
-
*
|
|
9020
|
-
*/
|
|
9021
|
-
/**
|
|
9040
|
+
* Release current character and animation resources (but keep core)
|
|
9022
9041
|
* Remove a specific character by handle
|
|
9023
9042
|
* @param characterHandle Character handle to remove
|
|
9024
9043
|
* @param characterId Optional character ID for cleanup
|
|
9044
|
+
* @internal
|
|
9025
9045
|
*/
|
|
9026
9046
|
removeCharacter(characterHandle, characterId) {
|
|
9027
9047
|
try {
|
|
@@ -9056,7 +9076,8 @@ class AvatarCoreAdapter {
|
|
|
9056
9076
|
}
|
|
9057
9077
|
}
|
|
9058
9078
|
/**
|
|
9059
|
-
*
|
|
9079
|
+
* Release all resources (including core)
|
|
9080
|
+
* @internal
|
|
9060
9081
|
*/
|
|
9061
9082
|
release() {
|
|
9062
9083
|
try {
|
|
@@ -9081,29 +9102,29 @@ class AvatarCoreAdapter {
|
|
|
9081
9102
|
}
|
|
9082
9103
|
}
|
|
9083
9104
|
/**
|
|
9084
|
-
*
|
|
9105
|
+
* Compatibility interface: provides same interface as FlameComplete3DGSManager
|
|
9106
|
+
* @internal
|
|
9085
9107
|
*/
|
|
9086
|
-
//
|
|
9108
|
+
// Compatible with loadFlameModel
|
|
9087
9109
|
// eslint-disable-next-line ts/no-explicit-any
|
|
9088
9110
|
async loadFlameModel(_modelData) {
|
|
9089
9111
|
return true;
|
|
9090
9112
|
}
|
|
9091
|
-
//
|
|
9113
|
+
// Compatible with load3DGSData
|
|
9092
9114
|
// eslint-disable-next-line ts/no-explicit-any
|
|
9093
9115
|
async load3DGSData(_original3DGSPoints, _binding, _flameFaces) {
|
|
9094
9116
|
return true;
|
|
9095
9117
|
}
|
|
9096
9118
|
/**
|
|
9097
|
-
*
|
|
9098
|
-
* 🚀
|
|
9099
|
-
* - C++
|
|
9100
|
-
* -
|
|
9101
|
-
* -
|
|
9102
|
-
*/
|
|
9103
|
-
/**
|
|
9119
|
+
* Compute frame and return GPU-friendly flat format (zero-copy, covariance pre-computed)
|
|
9120
|
+
* 🚀 Performance optimized version:
|
|
9121
|
+
* - C++ pre-computes covariance matrix
|
|
9122
|
+
* - Zero-copy direct access to WASM memory
|
|
9123
|
+
* - Direct output GPU format [pos3, color4, cov6]
|
|
9104
9124
|
* Compute complete frame from animation
|
|
9105
9125
|
* @param params Frame parameters
|
|
9106
9126
|
* @param characterHandle Optional character handle (for multi-character support)
|
|
9127
|
+
* @internal
|
|
9107
9128
|
*/
|
|
9108
9129
|
async computeCompleteFrameFlat(params, characterHandle) {
|
|
9109
9130
|
if (!this.isCharacterLoaded) {
|
|
@@ -9161,13 +9182,12 @@ class AvatarCoreAdapter {
|
|
|
9161
9182
|
}
|
|
9162
9183
|
}
|
|
9163
9184
|
/**
|
|
9164
|
-
*
|
|
9165
|
-
* 🔑
|
|
9166
|
-
*/
|
|
9167
|
-
/**
|
|
9185
|
+
* Compute frame and return GPU-friendly flat format (from FLAME parameters)
|
|
9186
|
+
* 🔑 Used for Realtime: accepts custom FLAME parameters and computes Splat
|
|
9168
9187
|
* Compute frame from Flame parameters
|
|
9169
9188
|
* @param flameParams Flame parameters
|
|
9170
9189
|
* @param characterHandle Optional character handle (for multi-character support)
|
|
9190
|
+
* @internal
|
|
9171
9191
|
*/
|
|
9172
9192
|
async computeFrameFlatFromParams(flameParams, characterHandle) {
|
|
9173
9193
|
if (!this.isCharacterLoaded) {
|
|
@@ -9212,8 +9232,9 @@ class AvatarCoreAdapter {
|
|
|
9212
9232
|
}
|
|
9213
9233
|
}
|
|
9214
9234
|
/**
|
|
9215
|
-
*
|
|
9216
|
-
* @returns WASM
|
|
9235
|
+
* Get WASM memory usage (MB)
|
|
9236
|
+
* @returns WASM memory usage (MB), or null if module not loaded
|
|
9237
|
+
* @internal
|
|
9217
9238
|
*/
|
|
9218
9239
|
getWASMMemoryMB() {
|
|
9219
9240
|
if (!this.wasmModule) {
|
|
@@ -9285,7 +9306,8 @@ class AvatarSDK {
|
|
|
9285
9306
|
}
|
|
9286
9307
|
}
|
|
9287
9308
|
/**
|
|
9288
|
-
*
|
|
9309
|
+
* Initialize WASM module (follows entire SDK lifecycle)
|
|
9310
|
+
* @internal
|
|
9289
9311
|
*/
|
|
9290
9312
|
static async initializeWASMModule() {
|
|
9291
9313
|
try {
|
|
@@ -9322,8 +9344,9 @@ class AvatarSDK {
|
|
|
9322
9344
|
}
|
|
9323
9345
|
}
|
|
9324
9346
|
/**
|
|
9325
|
-
*
|
|
9326
|
-
*
|
|
9347
|
+
* Initialize template resources (loaded during SDK initialization)
|
|
9348
|
+
* Load template resources from global CDN, throw error on failure to prevent SDK initialization
|
|
9349
|
+
* @internal
|
|
9327
9350
|
*/
|
|
9328
9351
|
static async initializeTemplateResources() {
|
|
9329
9352
|
if (!this._avatarCore) {
|
|
@@ -9431,7 +9454,8 @@ class AvatarSDK {
|
|
|
9431
9454
|
}
|
|
9432
9455
|
}
|
|
9433
9456
|
/**
|
|
9434
|
-
*
|
|
9457
|
+
* Fetch SDK configuration from remote config endpoint (simplified, logic moved to config/sdk-config-loader.ts)
|
|
9458
|
+
* @internal
|
|
9435
9459
|
*/
|
|
9436
9460
|
static async _fetchSdkConfig() {
|
|
9437
9461
|
try {
|
|
@@ -9472,7 +9496,7 @@ class AvatarSDK {
|
|
|
9472
9496
|
}
|
|
9473
9497
|
__publicField(AvatarSDK, "_isInitialized", false);
|
|
9474
9498
|
__publicField(AvatarSDK, "_configuration", null);
|
|
9475
|
-
__publicField(AvatarSDK, "_version", "1.0.0-beta.
|
|
9499
|
+
__publicField(AvatarSDK, "_version", "1.0.0-beta.70");
|
|
9476
9500
|
__publicField(AvatarSDK, "_avatarCore", null);
|
|
9477
9501
|
__publicField(AvatarSDK, "_dynamicSdkConfig", null);
|
|
9478
9502
|
const AvatarSDK$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -11185,8 +11209,8 @@ class NetworkLayer {
|
|
|
11185
11209
|
});
|
|
11186
11210
|
}
|
|
11187
11211
|
/**
|
|
11188
|
-
*
|
|
11189
|
-
* @
|
|
11212
|
+
* Start driving service heartbeat check (check connection status every 2 minutes)
|
|
11213
|
+
* @internal
|
|
11190
11214
|
*/
|
|
11191
11215
|
startHeartbeatCheck() {
|
|
11192
11216
|
this.stopHeartbeatCheck();
|
|
@@ -11198,8 +11222,8 @@ class NetworkLayer {
|
|
|
11198
11222
|
this.setupVisibilityListener();
|
|
11199
11223
|
}
|
|
11200
11224
|
/**
|
|
11201
|
-
*
|
|
11202
|
-
* @
|
|
11225
|
+
* Stop driving service heartbeat check
|
|
11226
|
+
* @internal
|
|
11203
11227
|
*/
|
|
11204
11228
|
stopHeartbeatCheck() {
|
|
11205
11229
|
if (this.heartbeatTimer !== null) {
|
|
@@ -11210,9 +11234,9 @@ class NetworkLayer {
|
|
|
11210
11234
|
this.heartbeatFailureCount = 0;
|
|
11211
11235
|
}
|
|
11212
11236
|
/**
|
|
11213
|
-
*
|
|
11214
|
-
*
|
|
11215
|
-
* @
|
|
11237
|
+
* Perform heartbeat check: detect WebSocket connection status
|
|
11238
|
+
* If connection fails 3 times, report heartbeat_failed event
|
|
11239
|
+
* @internal
|
|
11216
11240
|
*/
|
|
11217
11241
|
performHeartbeatCheck() {
|
|
11218
11242
|
try {
|
|
@@ -11243,8 +11267,8 @@ class NetworkLayer {
|
|
|
11243
11267
|
}
|
|
11244
11268
|
}
|
|
11245
11269
|
/**
|
|
11246
|
-
*
|
|
11247
|
-
* @
|
|
11270
|
+
* Setup page visibility listener (for immediately performing heartbeat check when page becomes visible)
|
|
11271
|
+
* @internal
|
|
11248
11272
|
*/
|
|
11249
11273
|
setupVisibilityListener() {
|
|
11250
11274
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
@@ -11259,8 +11283,8 @@ class NetworkLayer {
|
|
|
11259
11283
|
document.addEventListener("visibilitychange", this.visibilityChangeHandler);
|
|
11260
11284
|
}
|
|
11261
11285
|
/**
|
|
11262
|
-
*
|
|
11263
|
-
* @
|
|
11286
|
+
* Remove page visibility listener
|
|
11287
|
+
* @internal
|
|
11264
11288
|
*/
|
|
11265
11289
|
removeVisibilityListener() {
|
|
11266
11290
|
if (typeof window === "undefined" || typeof document === "undefined" || !this.visibilityChangeHandler) {
|
|
@@ -11387,7 +11411,7 @@ class AvatarController {
|
|
|
11387
11411
|
return this.currentState;
|
|
11388
11412
|
}
|
|
11389
11413
|
/**
|
|
11390
|
-
*
|
|
11414
|
+
* Map internal AvatarState to external ConversationState
|
|
11391
11415
|
* @internal
|
|
11392
11416
|
*/
|
|
11393
11417
|
mapToConversationState(avatarState) {
|
|
@@ -11468,6 +11492,7 @@ class AvatarController {
|
|
|
11468
11492
|
/**
|
|
11469
11493
|
* Check if audio context is initialized
|
|
11470
11494
|
* @throws AvatarError if audio context is not initialized
|
|
11495
|
+
* @internal
|
|
11471
11496
|
*/
|
|
11472
11497
|
checkAudioContextInitialized() {
|
|
11473
11498
|
var _a;
|
|
@@ -11854,7 +11879,7 @@ class AvatarController {
|
|
|
11854
11879
|
// ========== Internal Helper Methods ==========
|
|
11855
11880
|
/**
|
|
11856
11881
|
* Generate new conversation ID and log conversation started event
|
|
11857
|
-
* @
|
|
11882
|
+
* @internal
|
|
11858
11883
|
*/
|
|
11859
11884
|
generateAndLogNewConversationId() {
|
|
11860
11885
|
const conversationId = idManager.generateNewConversationId();
|
|
@@ -11867,7 +11892,7 @@ class AvatarController {
|
|
|
11867
11892
|
}
|
|
11868
11893
|
/**
|
|
11869
11894
|
* Clear playback data (keyframes, audio chunks, and playback state)
|
|
11870
|
-
* @
|
|
11895
|
+
* @internal
|
|
11871
11896
|
*/
|
|
11872
11897
|
clearPlaybackData() {
|
|
11873
11898
|
this.currentKeyframes = [];
|
|
@@ -11891,7 +11916,7 @@ class AvatarController {
|
|
|
11891
11916
|
}
|
|
11892
11917
|
/**
|
|
11893
11918
|
* Reset conversation ID state (for both network and external modes)
|
|
11894
|
-
* @
|
|
11919
|
+
* @internal
|
|
11895
11920
|
*/
|
|
11896
11921
|
resetConversationIdState() {
|
|
11897
11922
|
if (this.networkLayer) {
|
|
@@ -11915,7 +11940,7 @@ class AvatarController {
|
|
|
11915
11940
|
}
|
|
11916
11941
|
/**
|
|
11917
11942
|
* Get effective conversation ID (handles both SDK and host modes)
|
|
11918
|
-
* @
|
|
11943
|
+
* @internal
|
|
11919
11944
|
*/
|
|
11920
11945
|
getEffectiveConversationId() {
|
|
11921
11946
|
var _a;
|
|
@@ -11978,8 +12003,8 @@ class AvatarController {
|
|
|
11978
12003
|
}
|
|
11979
12004
|
}
|
|
11980
12005
|
/**
|
|
11981
|
-
*
|
|
11982
|
-
* @
|
|
12006
|
+
* Set complete eye tracking configuration to C++
|
|
12007
|
+
* @internal
|
|
11983
12008
|
*/
|
|
11984
12009
|
async setEyeTrackingConfig(eyefocus) {
|
|
11985
12010
|
const avatarCore = AvatarSDK.getAvatarCore();
|
|
@@ -12041,8 +12066,8 @@ class AvatarController {
|
|
|
12041
12066
|
}
|
|
12042
12067
|
}
|
|
12043
12068
|
/**
|
|
12044
|
-
*
|
|
12045
|
-
* @
|
|
12069
|
+
* Rerender current frame (for updating post-processing parameters when paused)
|
|
12070
|
+
* @internal
|
|
12046
12071
|
*/
|
|
12047
12072
|
async rerenderCurrentFrame() {
|
|
12048
12073
|
await this.rerenderCurrentFrameIfPaused();
|
|
@@ -12105,6 +12130,7 @@ class AvatarController {
|
|
|
12105
12130
|
// ========== Private Methods ==========
|
|
12106
12131
|
/**
|
|
12107
12132
|
* Start streaming playback (internal implementation)
|
|
12133
|
+
* @internal
|
|
12108
12134
|
*/
|
|
12109
12135
|
async startStreamingPlaybackInternal() {
|
|
12110
12136
|
var _a, _b, _c;
|
|
@@ -12246,6 +12272,10 @@ class AvatarController {
|
|
|
12246
12272
|
}
|
|
12247
12273
|
return false;
|
|
12248
12274
|
}
|
|
12275
|
+
/**
|
|
12276
|
+
* Start playback loop
|
|
12277
|
+
* @internal
|
|
12278
|
+
*/
|
|
12249
12279
|
startPlaybackLoop() {
|
|
12250
12280
|
if (this.playbackLoopId) {
|
|
12251
12281
|
return;
|
|
@@ -12340,6 +12370,7 @@ class AvatarController {
|
|
|
12340
12370
|
}
|
|
12341
12371
|
/**
|
|
12342
12372
|
* Stop playback loop
|
|
12373
|
+
* @internal
|
|
12343
12374
|
*/
|
|
12344
12375
|
stopPlaybackLoop() {
|
|
12345
12376
|
if (this.playbackLoopId) {
|
|
@@ -12349,10 +12380,10 @@ class AvatarController {
|
|
|
12349
12380
|
}
|
|
12350
12381
|
// ========== Audio Only Mode ==========
|
|
12351
12382
|
/**
|
|
12352
|
-
*
|
|
12353
|
-
*
|
|
12354
|
-
*
|
|
12355
|
-
* @
|
|
12383
|
+
* Enable audio-only playback mode (called when server error or timeout occurs)
|
|
12384
|
+
* In this mode, audio plays independently without animation data
|
|
12385
|
+
* Once enabled, subsequent animation data in this session will be ignored
|
|
12386
|
+
* @internal
|
|
12356
12387
|
*/
|
|
12357
12388
|
enableAudioOnlyMode() {
|
|
12358
12389
|
if (this.isAudioOnlyMode) {
|
|
@@ -12368,8 +12399,8 @@ class AvatarController {
|
|
|
12368
12399
|
}
|
|
12369
12400
|
}
|
|
12370
12401
|
/**
|
|
12371
|
-
*
|
|
12372
|
-
* @
|
|
12402
|
+
* Audio-only playback (completely independent logic, does not affect normal playback flow)
|
|
12403
|
+
* @internal
|
|
12373
12404
|
*/
|
|
12374
12405
|
async startAudioOnlyPlayback() {
|
|
12375
12406
|
var _a, _b;
|
|
@@ -12418,9 +12449,9 @@ class AvatarController {
|
|
|
12418
12449
|
}
|
|
12419
12450
|
}
|
|
12420
12451
|
/**
|
|
12421
|
-
*
|
|
12422
|
-
*
|
|
12423
|
-
* @
|
|
12452
|
+
* Audio monitoring loop (only for audio-only mode)
|
|
12453
|
+
* Only detects if audio has ended, does not render animation
|
|
12454
|
+
* @internal
|
|
12424
12455
|
*/
|
|
12425
12456
|
startAudioMonitoringLoop() {
|
|
12426
12457
|
if (this.playbackLoopId) {
|
|
@@ -12470,6 +12501,10 @@ class AvatarController {
|
|
|
12470
12501
|
* Add audio chunk to buffer
|
|
12471
12502
|
* Note: animationPlayer should already be initialized before calling this method
|
|
12472
12503
|
*/
|
|
12504
|
+
/**
|
|
12505
|
+
* Add audio chunk to buffer
|
|
12506
|
+
* @internal
|
|
12507
|
+
*/
|
|
12473
12508
|
addAudioChunkToBuffer(data, isLast) {
|
|
12474
12509
|
if (!this.animationPlayer) {
|
|
12475
12510
|
logger.warn("[AvatarController] animationPlayer is null in addAudioChunkToBuffer, this should not happen");
|
|
@@ -12485,6 +12520,10 @@ class AvatarController {
|
|
|
12485
12520
|
/**
|
|
12486
12521
|
* Event system
|
|
12487
12522
|
*/
|
|
12523
|
+
/**
|
|
12524
|
+
* Register event listener
|
|
12525
|
+
* @internal
|
|
12526
|
+
*/
|
|
12488
12527
|
registerEventListener(event, callback) {
|
|
12489
12528
|
if (!this.eventListeners.has(event)) {
|
|
12490
12529
|
this.eventListeners.set(event, /* @__PURE__ */ new Set());
|
|
@@ -12515,7 +12554,7 @@ class AvatarController {
|
|
|
12515
12554
|
}
|
|
12516
12555
|
/**
|
|
12517
12556
|
* Apply post-processing parameters to animation parameters
|
|
12518
|
-
* @
|
|
12557
|
+
* @internal
|
|
12519
12558
|
*/
|
|
12520
12559
|
applyPostProcessingToParams(baseParams) {
|
|
12521
12560
|
if (!this.postProcessingConfig) {
|
|
@@ -12591,9 +12630,9 @@ class AvatarController {
|
|
|
12591
12630
|
return result2;
|
|
12592
12631
|
}
|
|
12593
12632
|
/**
|
|
12594
|
-
*
|
|
12595
|
-
*
|
|
12596
|
-
* @
|
|
12633
|
+
* Report driving_service_latency event (Host mode)
|
|
12634
|
+
* Report once per session (when first frame is received)
|
|
12635
|
+
* @internal
|
|
12597
12636
|
*/
|
|
12598
12637
|
reportDrivingServiceLatency(conversationId) {
|
|
12599
12638
|
if (!conversationId || this.playbackMode !== DrivingServiceMode.host) {
|
|
@@ -12636,19 +12675,22 @@ function errorToMessage(err) {
|
|
|
12636
12675
|
}
|
|
12637
12676
|
const _PwaCacheManager = class _PwaCacheManager {
|
|
12638
12677
|
/**
|
|
12639
|
-
*
|
|
12678
|
+
* Check if Cache API is supported
|
|
12679
|
+
* @internal
|
|
12640
12680
|
*/
|
|
12641
12681
|
static isSupported() {
|
|
12642
12682
|
return typeof caches !== "undefined";
|
|
12643
12683
|
}
|
|
12644
12684
|
/**
|
|
12645
|
-
*
|
|
12685
|
+
* Get character cache name
|
|
12686
|
+
* @internal
|
|
12646
12687
|
*/
|
|
12647
12688
|
static getCharacterCacheName(characterId) {
|
|
12648
12689
|
return `${_PwaCacheManager.CHARACTER_CACHE_PREFIX}${characterId}${_PwaCacheManager.CHARACTER_CACHE_SUFFIX}`;
|
|
12649
12690
|
}
|
|
12650
12691
|
/**
|
|
12651
|
-
*
|
|
12692
|
+
* Get character resource from cache
|
|
12693
|
+
* @internal
|
|
12652
12694
|
*/
|
|
12653
12695
|
static async getCharacterResource(characterId, url) {
|
|
12654
12696
|
if (!_PwaCacheManager.isSupported()) {
|
|
@@ -12670,7 +12712,8 @@ const _PwaCacheManager = class _PwaCacheManager {
|
|
|
12670
12712
|
}
|
|
12671
12713
|
}
|
|
12672
12714
|
/**
|
|
12673
|
-
*
|
|
12715
|
+
* Put character resource into cache
|
|
12716
|
+
* @internal
|
|
12674
12717
|
*/
|
|
12675
12718
|
static async putCharacterResource(characterId, url, data) {
|
|
12676
12719
|
if (!_PwaCacheManager.isSupported()) {
|
|
@@ -12692,7 +12735,8 @@ const _PwaCacheManager = class _PwaCacheManager {
|
|
|
12692
12735
|
}
|
|
12693
12736
|
}
|
|
12694
12737
|
/**
|
|
12695
|
-
*
|
|
12738
|
+
* Get template resource from cache
|
|
12739
|
+
* @internal
|
|
12696
12740
|
*/
|
|
12697
12741
|
static async getTemplateResource(url) {
|
|
12698
12742
|
if (!_PwaCacheManager.isSupported()) {
|
|
@@ -12713,8 +12757,9 @@ const _PwaCacheManager = class _PwaCacheManager {
|
|
|
12713
12757
|
}
|
|
12714
12758
|
}
|
|
12715
12759
|
/**
|
|
12716
|
-
*
|
|
12717
|
-
*
|
|
12760
|
+
* Put template resource into cache
|
|
12761
|
+
* Template resources have no quantity limit, permanently retained until version update
|
|
12762
|
+
* @internal
|
|
12718
12763
|
*/
|
|
12719
12764
|
static async putTemplateResource(url, data) {
|
|
12720
12765
|
if (!_PwaCacheManager.isSupported()) {
|
|
@@ -12729,7 +12774,8 @@ const _PwaCacheManager = class _PwaCacheManager {
|
|
|
12729
12774
|
}
|
|
12730
12775
|
}
|
|
12731
12776
|
/**
|
|
12732
|
-
*
|
|
12777
|
+
* Clear character cache
|
|
12778
|
+
* @internal
|
|
12733
12779
|
*/
|
|
12734
12780
|
static async clearCharacterCache(characterId) {
|
|
12735
12781
|
if (!_PwaCacheManager.isSupported()) {
|
|
@@ -12744,9 +12790,10 @@ const _PwaCacheManager = class _PwaCacheManager {
|
|
|
12744
12790
|
}
|
|
12745
12791
|
}
|
|
12746
12792
|
/**
|
|
12747
|
-
*
|
|
12748
|
-
*
|
|
12749
|
-
* @returns true
|
|
12793
|
+
* Check template cache version, clear cache if version changed
|
|
12794
|
+
* Uses independent template resource version (not dependent on SDK version), allowing different SDK versions to share the same template resource cache
|
|
12795
|
+
* @returns true if version changed and cache was cleared, false otherwise
|
|
12796
|
+
* @internal
|
|
12750
12797
|
*/
|
|
12751
12798
|
static async checkTemplateCacheVersion() {
|
|
12752
12799
|
if (!_PwaCacheManager.isSupported()) {
|
|
@@ -12772,14 +12819,14 @@ const _PwaCacheManager = class _PwaCacheManager {
|
|
|
12772
12819
|
}
|
|
12773
12820
|
}
|
|
12774
12821
|
};
|
|
12775
|
-
//
|
|
12822
|
+
// Template cache version (independent of SDK version, manually update when template resources change)
|
|
12776
12823
|
__publicField(_PwaCacheManager, "TEMPLATE_RESOURCE_VERSION", "1.0.0");
|
|
12777
12824
|
__publicField(_PwaCacheManager, "TEMPLATE_CACHE_NAME", `spatialwalk-sdk-template-cache-${_PwaCacheManager.TEMPLATE_RESOURCE_VERSION}`);
|
|
12778
12825
|
__publicField(_PwaCacheManager, "TEMPLATE_VERSION_STORAGE_KEY", "spatialwalk-sdk-template-cache-version");
|
|
12779
|
-
//
|
|
12826
|
+
// Character cache prefix and suffix
|
|
12780
12827
|
__publicField(_PwaCacheManager, "CHARACTER_CACHE_PREFIX", "spatialwalk-sdk-character-");
|
|
12781
12828
|
__publicField(_PwaCacheManager, "CHARACTER_CACHE_SUFFIX", "-cache");
|
|
12782
|
-
//
|
|
12829
|
+
// Character cache LRU limit: maximum 1000 resource entries (supports ~250 characters, 4 resources per character)
|
|
12783
12830
|
__publicField(_PwaCacheManager, "MAX_CHARACTER_CACHE_ENTRIES", 1e3);
|
|
12784
12831
|
let PwaCacheManager = _PwaCacheManager;
|
|
12785
12832
|
const pwaCacheManager = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -13335,7 +13382,8 @@ const _AvatarManager = class _AvatarManager {
|
|
|
13335
13382
|
return loadPromise;
|
|
13336
13383
|
}
|
|
13337
13384
|
/**
|
|
13338
|
-
*
|
|
13385
|
+
* Process download queue (ensure serial execution)
|
|
13386
|
+
* @internal
|
|
13339
13387
|
*/
|
|
13340
13388
|
async processDownloadQueue() {
|
|
13341
13389
|
if (this.isDownloading || this.downloadQueue.length === 0) {
|
|
@@ -13355,7 +13403,8 @@ const _AvatarManager = class _AvatarManager {
|
|
|
13355
13403
|
}
|
|
13356
13404
|
}
|
|
13357
13405
|
/**
|
|
13358
|
-
*
|
|
13406
|
+
* Execute actual loading logic (private method)
|
|
13407
|
+
* @internal
|
|
13359
13408
|
*/
|
|
13360
13409
|
async doLoad(id, characterMeta, onProgress) {
|
|
13361
13410
|
try {
|
|
@@ -15128,26 +15177,26 @@ function createBezierEasing(x1, y1, x2, y2) {
|
|
|
15128
15177
|
};
|
|
15129
15178
|
}
|
|
15130
15179
|
const BEZIER_CURVES = {
|
|
15131
|
-
// jaw:
|
|
15180
|
+
// jaw: fast start, smooth stop
|
|
15132
15181
|
jaw: createBezierEasing(0.2, 0.8, 0.3, 1),
|
|
15133
|
-
// expression:
|
|
15182
|
+
// expression: smooth S curve
|
|
15134
15183
|
expression: createBezierEasing(0.4, 0, 0.2, 1),
|
|
15135
|
-
// eye:
|
|
15184
|
+
// eye: softer S curve
|
|
15136
15185
|
eye: createBezierEasing(0.3, 0, 0.1, 1),
|
|
15137
|
-
// neck:
|
|
15186
|
+
// neck: slow start, inertial stop
|
|
15138
15187
|
neck: createBezierEasing(0.1, 0.2, 0.2, 1),
|
|
15139
|
-
// global:
|
|
15188
|
+
// global: standard ease-in-out
|
|
15140
15189
|
global: createBezierEasing(0.42, 0, 0.58, 1)
|
|
15141
15190
|
};
|
|
15142
15191
|
const TIME_SCALE = {
|
|
15143
15192
|
jaw: 2.5,
|
|
15144
|
-
// 40%
|
|
15193
|
+
// 40% time to complete
|
|
15145
15194
|
expression: 1.6,
|
|
15146
|
-
// 62.5%
|
|
15195
|
+
// 62.5% time to complete
|
|
15147
15196
|
eye: 1.3,
|
|
15148
|
-
// 77%
|
|
15197
|
+
// 77% time to complete
|
|
15149
15198
|
neck: 1,
|
|
15150
|
-
// 100%
|
|
15199
|
+
// 100% time to complete
|
|
15151
15200
|
global: 1
|
|
15152
15201
|
};
|
|
15153
15202
|
function bezierLerp(from, to2, progress) {
|
|
@@ -15258,7 +15307,8 @@ class AvatarView {
|
|
|
15258
15307
|
}
|
|
15259
15308
|
// 10分钟 = 600000ms
|
|
15260
15309
|
/**
|
|
15261
|
-
*
|
|
15310
|
+
* Align Flame dimensions at both ends: unify scalar lengths, take max length for expression and zero-pad
|
|
15311
|
+
* @internal
|
|
15262
15312
|
*/
|
|
15263
15313
|
alignFlamePair(from, to2) {
|
|
15264
15314
|
const ensureLen = (arr, len) => {
|
|
@@ -15292,11 +15342,12 @@ class AvatarView {
|
|
|
15292
15342
|
return { from: fromFixed, to: toFixed };
|
|
15293
15343
|
}
|
|
15294
15344
|
/**
|
|
15295
|
-
*
|
|
15296
|
-
* @param from
|
|
15297
|
-
* @param to
|
|
15298
|
-
* @param durationMs
|
|
15299
|
-
* @param useLinearInterpolation
|
|
15345
|
+
* Generate and align transition frames, ensuring first and last frames match start and end frames exactly
|
|
15346
|
+
* @param from Start frame
|
|
15347
|
+
* @param to Target frame
|
|
15348
|
+
* @param durationMs Transition duration (start or end)
|
|
15349
|
+
* @param useLinearInterpolation Whether to use linear interpolation (legacy implementation), true for idle->speaking, false for speaking->idle (uses Bezier curve)
|
|
15350
|
+
* @internal
|
|
15300
15351
|
*/
|
|
15301
15352
|
generateAndAlignTransitionFrames(from, to2, durationMs, useLinearInterpolation = false) {
|
|
15302
15353
|
const aligned = this.alignFlamePair(from, to2);
|
|
@@ -15319,7 +15370,8 @@ class AvatarView {
|
|
|
15319
15370
|
return keyframes;
|
|
15320
15371
|
}
|
|
15321
15372
|
/**
|
|
15322
|
-
*
|
|
15373
|
+
* Get cached Idle first frame, fetch and cache if not cached
|
|
15374
|
+
* @internal
|
|
15323
15375
|
*/
|
|
15324
15376
|
async getCachedIdleFirstFrame() {
|
|
15325
15377
|
if (!this.cachedIdleFirstFrame) {
|
|
@@ -15342,7 +15394,8 @@ class AvatarView {
|
|
|
15342
15394
|
return this.avatarController;
|
|
15343
15395
|
}
|
|
15344
15396
|
/**
|
|
15345
|
-
*
|
|
15397
|
+
* Create canvas element
|
|
15398
|
+
* @internal
|
|
15346
15399
|
*/
|
|
15347
15400
|
createCanvas(container) {
|
|
15348
15401
|
const canvas = document.createElement("canvas");
|
|
@@ -15388,7 +15441,8 @@ class AvatarView {
|
|
|
15388
15441
|
return this.canvas;
|
|
15389
15442
|
}
|
|
15390
15443
|
/**
|
|
15391
|
-
*
|
|
15444
|
+
* Initialize view system
|
|
15445
|
+
* @internal
|
|
15392
15446
|
*/
|
|
15393
15447
|
async initializeView(avatar) {
|
|
15394
15448
|
var _a;
|
|
@@ -15458,7 +15512,8 @@ class AvatarView {
|
|
|
15458
15512
|
}
|
|
15459
15513
|
}
|
|
15460
15514
|
/**
|
|
15461
|
-
*
|
|
15515
|
+
* Initialize render system
|
|
15516
|
+
* @internal
|
|
15462
15517
|
*/
|
|
15463
15518
|
async initializeRenderSystem(cameraInfo) {
|
|
15464
15519
|
this.cameraConfig = cameraInfo || this.getDefaultCameraConfig();
|
|
@@ -15480,13 +15535,15 @@ class AvatarView {
|
|
|
15480
15535
|
logger.log("[AvatarView] Render system initialized successfully");
|
|
15481
15536
|
}
|
|
15482
15537
|
/**
|
|
15483
|
-
*
|
|
15538
|
+
* Get default camera configuration
|
|
15539
|
+
* @internal
|
|
15484
15540
|
*/
|
|
15485
15541
|
getDefaultCameraConfig() {
|
|
15486
15542
|
return { ...APP_CONFIG.camera };
|
|
15487
15543
|
}
|
|
15488
15544
|
/**
|
|
15489
|
-
*
|
|
15545
|
+
* Resolve final camera configuration from resources, prioritize character settings, then camera.json
|
|
15546
|
+
* @internal
|
|
15490
15547
|
*/
|
|
15491
15548
|
resolveCameraConfig(resources) {
|
|
15492
15549
|
var _a, _b;
|
|
@@ -15502,7 +15559,8 @@ class AvatarView {
|
|
|
15502
15559
|
return this.deriveCameraConfigFromSettings(candidateSettings, defaultCamera, source);
|
|
15503
15560
|
}
|
|
15504
15561
|
/**
|
|
15505
|
-
*
|
|
15562
|
+
* Derive camera configuration from character settings
|
|
15563
|
+
* @internal
|
|
15506
15564
|
*/
|
|
15507
15565
|
deriveCameraConfigFromSettings(cameraSettings, fallback, source) {
|
|
15508
15566
|
const safeValue = (value, fallbackValue) => Number.isFinite(value) ? value : fallbackValue;
|
|
@@ -15561,7 +15619,8 @@ class AvatarView {
|
|
|
15561
15619
|
return derivedCamera;
|
|
15562
15620
|
}
|
|
15563
15621
|
/**
|
|
15564
|
-
*
|
|
15622
|
+
* Render first frame
|
|
15623
|
+
* @internal
|
|
15565
15624
|
*/
|
|
15566
15625
|
async renderFirstFrame() {
|
|
15567
15626
|
var _a;
|
|
@@ -15595,7 +15654,8 @@ class AvatarView {
|
|
|
15595
15654
|
}
|
|
15596
15655
|
}
|
|
15597
15656
|
/**
|
|
15598
|
-
*
|
|
15657
|
+
* Update FPS statistics (called in requestAnimationFrame callback)
|
|
15658
|
+
* @internal
|
|
15599
15659
|
*/
|
|
15600
15660
|
updateFPS() {
|
|
15601
15661
|
this.frameCount++;
|
|
@@ -15607,14 +15667,16 @@ class AvatarView {
|
|
|
15607
15667
|
}
|
|
15608
15668
|
}
|
|
15609
15669
|
/**
|
|
15610
|
-
*
|
|
15670
|
+
* Initialize FPS calculation
|
|
15671
|
+
* @internal
|
|
15611
15672
|
*/
|
|
15612
15673
|
initFPS() {
|
|
15613
15674
|
this.frameCount = 0;
|
|
15614
15675
|
this.lastFpsUpdate = performance.now();
|
|
15615
15676
|
}
|
|
15616
15677
|
/**
|
|
15617
|
-
*
|
|
15678
|
+
* Start idle animation loop
|
|
15679
|
+
* @internal
|
|
15618
15680
|
*/
|
|
15619
15681
|
startIdleAnimationLoop() {
|
|
15620
15682
|
if (this.idleAnimationLoopId) {
|
|
@@ -15676,7 +15738,8 @@ class AvatarView {
|
|
|
15676
15738
|
logger.log("[AvatarView] Idle animation loop started");
|
|
15677
15739
|
}
|
|
15678
15740
|
/**
|
|
15679
|
-
*
|
|
15741
|
+
* Start realtime conversation animation loop
|
|
15742
|
+
* @internal
|
|
15680
15743
|
*/
|
|
15681
15744
|
startRealtimeAnimationLoop() {
|
|
15682
15745
|
if (this.realtimeAnimationLoopId) {
|
|
@@ -15779,7 +15842,8 @@ class AvatarView {
|
|
|
15779
15842
|
logger.log("[AvatarView] Realtime animation loop started");
|
|
15780
15843
|
}
|
|
15781
15844
|
/**
|
|
15782
|
-
*
|
|
15845
|
+
* Stop idle animation loop
|
|
15846
|
+
* @internal
|
|
15783
15847
|
*/
|
|
15784
15848
|
stopIdleAnimationLoop() {
|
|
15785
15849
|
if (this.idleAnimationLoopId) {
|
|
@@ -15790,7 +15854,8 @@ class AvatarView {
|
|
|
15790
15854
|
}
|
|
15791
15855
|
}
|
|
15792
15856
|
/**
|
|
15793
|
-
*
|
|
15857
|
+
* Stop realtime conversation animation loop
|
|
15858
|
+
* @internal
|
|
15794
15859
|
*/
|
|
15795
15860
|
stopRealtimeAnimationLoop() {
|
|
15796
15861
|
if (this.realtimeAnimationLoopId) {
|
|
@@ -15801,14 +15866,16 @@ class AvatarView {
|
|
|
15801
15866
|
}
|
|
15802
15867
|
}
|
|
15803
15868
|
/**
|
|
15804
|
-
*
|
|
15869
|
+
* Stop all animation loops
|
|
15870
|
+
* @internal
|
|
15805
15871
|
*/
|
|
15806
15872
|
stopAllAnimationLoops() {
|
|
15807
15873
|
this.stopIdleAnimationLoop();
|
|
15808
15874
|
this.stopRealtimeAnimationLoop();
|
|
15809
15875
|
}
|
|
15810
15876
|
/**
|
|
15811
|
-
*
|
|
15877
|
+
* Render realtime frame (called by playback layer callback)
|
|
15878
|
+
* @internal
|
|
15812
15879
|
*/
|
|
15813
15880
|
renderRealtimeFrame(splatData, frameIndex) {
|
|
15814
15881
|
if (!this.renderSystem || this.renderingState !== "speaking") {
|
|
@@ -15823,8 +15890,9 @@ class AvatarView {
|
|
|
15823
15890
|
}
|
|
15824
15891
|
}
|
|
15825
15892
|
/**
|
|
15826
|
-
*
|
|
15827
|
-
*
|
|
15893
|
+
* State transition method
|
|
15894
|
+
* Unified state transition management to ensure state consistency
|
|
15895
|
+
* @internal
|
|
15828
15896
|
*/
|
|
15829
15897
|
setState(newState) {
|
|
15830
15898
|
const oldState = this.renderingState;
|
|
@@ -15845,26 +15913,30 @@ class AvatarView {
|
|
|
15845
15913
|
}
|
|
15846
15914
|
}
|
|
15847
15915
|
/**
|
|
15848
|
-
*
|
|
15916
|
+
* Check if in realtime playing state (Speaking or transitioning to Speaking)
|
|
15917
|
+
* @internal
|
|
15849
15918
|
*/
|
|
15850
15919
|
get isRealtimePlaying() {
|
|
15851
15920
|
return this.renderingState === "speaking" || this.renderingState === "transitioningToSpeaking";
|
|
15852
15921
|
}
|
|
15853
15922
|
/**
|
|
15854
|
-
*
|
|
15923
|
+
* Check if in transition state
|
|
15924
|
+
* @internal
|
|
15855
15925
|
*/
|
|
15856
15926
|
get isTransitioning() {
|
|
15857
15927
|
return this.renderingState === "transitioningToSpeaking" || this.renderingState === "transitioningToIdle";
|
|
15858
15928
|
}
|
|
15859
15929
|
/**
|
|
15860
|
-
*
|
|
15930
|
+
* Check if will return to Idle after transition ends
|
|
15931
|
+
* @internal
|
|
15861
15932
|
*/
|
|
15862
15933
|
get endToIdleAfterTransition() {
|
|
15863
15934
|
return this.renderingState === "transitioningToIdle";
|
|
15864
15935
|
}
|
|
15865
15936
|
/**
|
|
15866
|
-
*
|
|
15867
|
-
*
|
|
15937
|
+
* Handle interrupt
|
|
15938
|
+
* When interrupted, should generate transition animation instead of directly jumping back to Idle
|
|
15939
|
+
* @internal
|
|
15868
15940
|
*/
|
|
15869
15941
|
handleInterrupt() {
|
|
15870
15942
|
const state = this.renderingState;
|
|
@@ -15886,7 +15958,8 @@ class AvatarView {
|
|
|
15886
15958
|
}
|
|
15887
15959
|
}
|
|
15888
15960
|
/**
|
|
15889
|
-
*
|
|
15961
|
+
* Setup AvatarController event listeners
|
|
15962
|
+
* @internal
|
|
15890
15963
|
*/
|
|
15891
15964
|
setupControllerEventListeners() {
|
|
15892
15965
|
this.avatarController.setupInternalEventListeners({
|
|
@@ -15905,8 +15978,9 @@ class AvatarView {
|
|
|
15905
15978
|
});
|
|
15906
15979
|
}
|
|
15907
15980
|
/**
|
|
15908
|
-
*
|
|
15909
|
-
*
|
|
15981
|
+
* Prepare realtime rendering (generate transition to Speaking)
|
|
15982
|
+
* Unified logic: from current playing frame -> Speaking first frame
|
|
15983
|
+
* @internal
|
|
15910
15984
|
*/
|
|
15911
15985
|
async prepareRealtimeRendering(keyframes) {
|
|
15912
15986
|
const state = this.renderingState;
|
|
@@ -15977,7 +16051,8 @@ class AvatarView {
|
|
|
15977
16051
|
this.startRealtimeAnimationLoop();
|
|
15978
16052
|
}
|
|
15979
16053
|
/**
|
|
15980
|
-
*
|
|
16054
|
+
* Start realtime rendering loop
|
|
16055
|
+
* @internal
|
|
15981
16056
|
*/
|
|
15982
16057
|
startRealtimeRendering() {
|
|
15983
16058
|
if (APP_CONFIG.debug)
|
|
@@ -15989,7 +16064,8 @@ class AvatarView {
|
|
|
15989
16064
|
});
|
|
15990
16065
|
}
|
|
15991
16066
|
/**
|
|
15992
|
-
*
|
|
16067
|
+
* Stop realtime conversation rendering
|
|
16068
|
+
* @internal
|
|
15993
16069
|
*/
|
|
15994
16070
|
stopRealtimeRendering() {
|
|
15995
16071
|
var _a, _b;
|
|
@@ -16235,10 +16311,10 @@ class AvatarView {
|
|
|
16235
16311
|
}
|
|
16236
16312
|
}
|
|
16237
16313
|
/**
|
|
16238
|
-
*
|
|
16239
|
-
*
|
|
16240
|
-
*
|
|
16241
|
-
* @
|
|
16314
|
+
* Rerender current frame with new camera configuration (for updating camera when paused)
|
|
16315
|
+
* Reuses AvatarController's rerender logic, as renderCallback will call renderRealtimeFrame,
|
|
16316
|
+
* which uses the updated camera configuration (via renderSystem.updateCamera)
|
|
16317
|
+
* @internal
|
|
16242
16318
|
*/
|
|
16243
16319
|
async rerenderCurrentFrameWithNewCamera() {
|
|
16244
16320
|
if (this.avatarController.state !== AvatarState.paused || this.renderingState !== "speaking" || !this.renderSystem) {
|
|
@@ -16247,7 +16323,8 @@ class AvatarView {
|
|
|
16247
16323
|
await this.avatarController.rerenderCurrentFrameIfPaused();
|
|
16248
16324
|
}
|
|
16249
16325
|
/**
|
|
16250
|
-
*
|
|
16326
|
+
* Handle size change: notify render system to update viewport and projection
|
|
16327
|
+
* @internal
|
|
16251
16328
|
*/
|
|
16252
16329
|
handleResize() {
|
|
16253
16330
|
if (this.renderSystem) {
|
|
@@ -16299,8 +16376,8 @@ class AvatarView {
|
|
|
16299
16376
|
}
|
|
16300
16377
|
}
|
|
16301
16378
|
/**
|
|
16302
|
-
*
|
|
16303
|
-
* @
|
|
16379
|
+
* Report avatar_active event
|
|
16380
|
+
* @internal
|
|
16304
16381
|
*/
|
|
16305
16382
|
reportAvatarActive() {
|
|
16306
16383
|
var _a, _b;
|
|
@@ -16311,8 +16388,8 @@ class AvatarView {
|
|
|
16311
16388
|
});
|
|
16312
16389
|
}
|
|
16313
16390
|
/**
|
|
16314
|
-
*
|
|
16315
|
-
* @
|
|
16391
|
+
* Start avatar_active heartbeat event (every 10 minutes)
|
|
16392
|
+
* @internal
|
|
16316
16393
|
*/
|
|
16317
16394
|
startAvatarActiveHeartbeat() {
|
|
16318
16395
|
this.stopAvatarActiveHeartbeat();
|
|
@@ -16323,8 +16400,8 @@ class AvatarView {
|
|
|
16323
16400
|
}, this.AVATAR_ACTIVE_INTERVAL);
|
|
16324
16401
|
}
|
|
16325
16402
|
/**
|
|
16326
|
-
*
|
|
16327
|
-
* @
|
|
16403
|
+
* Stop avatar_active heartbeat event
|
|
16404
|
+
* @internal
|
|
16328
16405
|
*/
|
|
16329
16406
|
stopAvatarActiveHeartbeat() {
|
|
16330
16407
|
if (this.avatarActiveTimer !== null) {
|