@@ -86,6 +86,8 @@ export class CloudXR2DUI {
8686 private immersiveSelect ! : HTMLSelectElement ;
8787 /** Dropdown to select device frame rate (FPS) */
8888 private deviceFrameRateSelect ! : HTMLSelectElement ;
89+ /** Dropdown for CloudXR networkLatencyMode preset */
90+ private networkLatencyModeSelect ! : HTMLSelectElement ;
8991 /** Dropdown to select max streaming bitrate (Mbps) */
9092 private maxStreamingBitrateMbpsSelect ! : HTMLSelectElement ;
9193 /** Dropdown to select preferred streaming codec */
@@ -213,6 +215,7 @@ export class CloudXR2DUI {
213215 // Set initial display value
214216 this . posePredictionFactorValue . textContent = this . posePredictionFactorInput . value ;
215217 this . updateConfiguration ( ) ;
218+ this . updateNetworkLatencyModeUi ( ) ;
216219 this . updateDeviceProfileWarning ( resolveDeviceProfileId ( this . deviceProfileSelect . value ) ) ;
217220 this . updateConnectButtonState ( ) ;
218221 this . initialized = true ;
@@ -361,6 +364,7 @@ export class CloudXR2DUI {
361364 this . proxyUrlInput = this . getElement < HTMLInputElement > ( 'proxyUrl' ) ;
362365 this . immersiveSelect = this . getElement < HTMLSelectElement > ( 'immersive' ) ;
363366 this . deviceFrameRateSelect = this . getElement < HTMLSelectElement > ( 'deviceFrameRate' ) ;
367+ this . networkLatencyModeSelect = this . getElement < HTMLSelectElement > ( 'networkLatencyMode' ) ;
364368 this . maxStreamingBitrateMbpsSelect =
365369 this . getElement < HTMLSelectElement > ( 'maxStreamingBitrateMbps' ) ;
366370 this . codecSelect = this . getElement < HTMLSelectElement > ( 'codec' ) ;
@@ -444,6 +448,7 @@ export class CloudXR2DUI {
444448 reprojectionGridRows : 0 ,
445449 deviceFrameRate : 90 ,
446450 maxStreamingBitrateMbps : 150 ,
451+ networkLatencyMode : 'DEFAULT' ,
447452 codec : 'av1' ,
448453 immersiveMode : 'ar' ,
449454 deviceProfileId : 'custom' ,
@@ -477,6 +482,7 @@ export class CloudXR2DUI {
477482 enableLocalStorage ( this . reprojectionGridRowsInput , 'reprojectionGridRows' ) ;
478483 enableLocalStorage ( this . proxyUrlInput , 'proxyUrl' ) ;
479484 enableLocalStorage ( this . deviceFrameRateSelect , 'deviceFrameRate' ) ;
485+ enableLocalStorage ( this . networkLatencyModeSelect , 'networkLatencyMode' ) ;
480486 enableLocalStorage ( this . maxStreamingBitrateMbpsSelect , 'maxStreamingBitrateMbps' ) ;
481487 enableLocalStorage ( this . codecSelect , 'codec' ) ;
482488 enableLocalStorage ( this . enablePoseSmoothingSelect , 'enablePoseSmoothing' ) ;
@@ -563,6 +569,10 @@ export class CloudXR2DUI {
563569 addListener ( this . reprojectionGridRowsInput , 'keyup' , updateGridValidation ) ;
564570 this . updateGridValidationMessage ( ) ;
565571 addListener ( this . deviceFrameRateSelect , 'change' , onProfileLinkedChange ) ;
572+ addListener ( this . networkLatencyModeSelect , 'change' , ( ) => {
573+ this . updateNetworkLatencyModeUi ( ) ;
574+ onProfileLinkedChange ( ) ;
575+ } ) ;
566576 addListener ( this . maxStreamingBitrateMbpsSelect , 'change' , onProfileLinkedChange ) ;
567577 addListener ( this . codecSelect , 'change' , onProfileLinkedChange ) ;
568578 addListener ( this . enablePoseSmoothingSelect , 'change' , onProfileLinkedChange ) ;
@@ -745,6 +755,7 @@ export class CloudXR2DUI {
745755 maxStreamingBitrateMbps :
746756 parseInt ( this . maxStreamingBitrateMbpsSelect . value ) ||
747757 this . getDefaultConfiguration ( ) . maxStreamingBitrateMbps ,
758+ networkLatencyMode : this . networkLatencyModeSelect . value === 'LOW' ? 'LOW' : 'DEFAULT' ,
748759 codec :
749760 ( this . codecSelect . value as 'h264' | 'h265' | 'av1' ) || this . getDefaultConfiguration ( ) . codec ,
750761 // Headless mode turns off the client's CloudXR frame blit but keeps tracking; the WebXR
@@ -870,6 +881,7 @@ export class CloudXR2DUI {
870881 localStorage . setItem ( 'reprojectionGridCols' , this . reprojectionGridColsInput . value ) ;
871882 localStorage . setItem ( 'reprojectionGridRows' , this . reprojectionGridRowsInput . value ) ;
872883 localStorage . setItem ( 'deviceFrameRate' , this . deviceFrameRateSelect . value ) ;
884+ localStorage . setItem ( 'networkLatencyMode' , this . networkLatencyModeSelect . value ) ;
873885 localStorage . setItem ( 'maxStreamingBitrateMbps' , this . maxStreamingBitrateMbpsSelect . value ) ;
874886 localStorage . setItem ( 'codec' , this . codecSelect . value ) ;
875887 localStorage . setItem ( 'enablePoseSmoothing' , this . enablePoseSmoothingSelect . value ) ;
@@ -881,6 +893,17 @@ export class CloudXR2DUI {
881893 }
882894 }
883895
896+ private updateNetworkLatencyModeUi ( ) : void {
897+ const low = this . networkLatencyModeSelect . value === 'LOW' ;
898+ this . maxStreamingBitrateMbpsSelect . disabled = low ;
899+ const help = document . getElementById ( 'networkLatencyModeHelp' ) ;
900+ if ( help ) {
901+ help . textContent = low
902+ ? 'Low mode sets ~15 Mbit/s max bitrate, Ragnarok DRC, ~30 Hz pose/controller uplink, and disables hand/body bulk. Settings below do not apply.'
903+ : 'Default: full-rate tracking (including hands/body), Ragnarok ALL adaptive streaming. Set max Mbps below.' ;
904+ }
905+ }
906+
884907 private updateDeviceProfileWarning ( profileId : DeviceProfileId ) : void {
885908 if ( ! this . deviceProfileWarning ) return ;
886909 const profile = getDeviceProfile ( profileId ) ;
0 commit comments