Skip to content

Commit

Permalink
fix: add a way to disable VR button (important for android users) (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
Valery-a authored Oct 17, 2024
1 parent af0d7d1 commit bdcde9a
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 14 deletions.
22 changes: 13 additions & 9 deletions src/optionsGuiScheme.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useState } from 'react'
import { useRef, useState } from 'react'
import { useSnapshot } from 'valtio'
import { openURL } from 'prismarine-viewer/viewer/lib/simpleUtils'
import { noCase } from 'change-case'
import { titleCase } from 'title-case'
import { loadedGameState, miscUiState, openOptionsMenu, showModal } from './globalState'
import { AppOptions, options } from './optionsStorage'
import Button from './react/Button'
Expand All @@ -14,7 +13,6 @@ import { completeTexturePackInstall, getResourcePackNames, resourcePackState, un
import { downloadPacketsReplay, packetsReplaceSessionState } from './packetsReplay'
import { showOptionsModal } from './react/SelectOption'


export const guiOptionsScheme: {
[t in OptionsGroupType]: Array<{ [K in keyof AppOptions]?: Partial<OptionMeta<AppOptions[K]>> } & { custom? }>
} = {
Expand Down Expand Up @@ -368,15 +366,21 @@ export const guiOptionsScheme: {
}
// { ignoreSilentSwitch: {} },
],

VR: [
{
custom () {
return <>
<span style={{ fontSize: 9, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>VR currently has basic support</span>
<div />
</>
},
}
return (
<>
<span style={{ fontSize: 9, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
VR currently has basic support
</span>
<div />
</>
)
},
vrSupport: {}
},
],
advanced: [
{
Expand Down
1 change: 1 addition & 0 deletions src/optionsStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const defaultOptions = {
chatSelect: true,
autoJump: 'auto' as 'auto' | 'always' | 'never',
autoParkour: false,
vrSupport: true, // doesn't directly affect the VR mode, should only disable the button which is annoying to android users

// advanced bot options
autoRespawn: false,
Expand Down
3 changes: 2 additions & 1 deletion src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ body {
#VRButton {
background: rgba(0, 0, 0, 0.3) !important;
opacity: 0.7 !important;
position: fixed !important;
position: static !important;
bottom: 60px !important;
z-index: unset !important;
}

.dirt-bg {
Expand Down
100 changes: 96 additions & 4 deletions src/vr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,103 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js'
import { buttonMap as standardButtonsMap } from 'contro-max/build/gamepad'
import * as THREE from 'three'
import { subscribeKey } from 'valtio/utils'
import { subscribe } from 'valtio'
import { activeModalStack, hideModal } from './globalState'
import { watchUnloadForCleanup } from './gameUnload'
import { options } from './optionsStorage'

export async function initVR () {
options.vrSupport = true
const { renderer } = viewer
if (!('xr' in navigator)) return
const isSupported = await navigator.xr?.isSessionSupported('immersive-vr') && !!XRSession.prototype.updateRenderState // e.g. android webview doesn't support updateRenderState

const isSupported = await checkVRSupport()
if (!isSupported) return

// VR
document.body.appendChild(VRButton.createButton(renderer))
renderer.xr.enabled = true
enableVr(renderer)

const vrButtonContainer = createVrButtonContainer(renderer)
const updateVrButtons = () => {
vrButtonContainer.hidden = !options.vrSupport || activeModalStack.length !== 0
}

const unsubWatchSetting = subscribeKey(options, 'vrSupport', updateVrButtons)
const unsubWatchModals = subscribe(activeModalStack, updateVrButtons)

function enableVr (renderer) {
renderer.xr.enabled = true
}

function disableVr () {
renderer.xr.enabled = false
viewer.cameraObjectOverride = undefined
viewer.scene.remove(user)
vrButtonContainer.hidden = true
unsubWatchSetting()
unsubWatchModals()
}

function createVrButtonContainer (renderer) {
const container = document.createElement('div')
const vrButton = VRButton.createButton(renderer)
styleContainer(container)

const closeButton = createCloseButton(container)

container.appendChild(vrButton)
container.appendChild(closeButton)
document.body.appendChild(container)

return container
}

function styleContainer (container: HTMLElement) {
typedAssign(container.style, {
position: 'absolute',
bottom: '80px',
left: '0',
right: '0',
display: 'flex',
justifyContent: 'center',
zIndex: '8',
gap: '8px',
})
}

function createCloseButton (container: HTMLElement) {
const closeButton = document.createElement('button')
closeButton.textContent = 'X'
typedAssign(closeButton.style, {
padding: '0 12px',
color: 'white',
fontSize: '14px',
lineHeight: '20px',
cursor: 'pointer',
background: 'transparent',
border: '1px solid rgb(255, 255, 255)',
borderRadius: '4px',
opacity: '0.7',
})

closeButton.addEventListener('click', () => {
container.hidden = true
options.vrSupport = false
})

return closeButton
}


async function checkVRSupport () {
try {
const supported = await navigator.xr?.isSessionSupported('immersive-vr')
return supported && !!XRSession.prototype.updateRenderState
} catch (err) {
console.error('Error checking if VR is supported', err)
return false
}
}

// hack for vr camera
const user = new THREE.Group()
Expand Down Expand Up @@ -129,6 +215,8 @@ export async function initVR () {
renderer.xr.addEventListener('sessionend', () => {
viewer.cameraObjectOverride = undefined
})

watchUnloadForCleanup(disableVr)
}

const xrStandardRightButtonsMap = [
Expand Down Expand Up @@ -169,3 +257,7 @@ const remapAxes = (axesRight, axesLeft) => {
axesRight[3]
]
}

function typedAssign<T extends Record<string, any>> (target: T, source: Partial<T>) {
Object.assign(target, source)
}

0 comments on commit bdcde9a

Please # to comment.