Skip to content

Commit

Permalink
fix: view component supports non-fullscreen for v8.1.0, logs warning …
Browse files Browse the repository at this point in the history
…if older version detected
  • Loading branch information
kmannislands committed Jul 12, 2022
1 parent c7fa011 commit f012910
Showing 1 changed file with 52 additions and 5 deletions.
57 changes: 52 additions & 5 deletions src/web/View.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,34 @@ const isOrthographicCamera = (def: any): def is THREE.OrthographicCamera =>
def && (def as THREE.OrthographicCamera).isOrthographicCamera
const col = new THREE.Color()

/**
* In `@react-three/fiber` after `v8.0.0` but prior to `v8.1.0`, `state.size` contained only dimension
* information. After `v8.1.0`, position information (`top`, `left`) was added
*
* @todo remove this when drei supports v9 and up
*/
type LegacyCanvasSize = {
height: number
width: number
}

type CanvasSize = LegacyCanvasSize & {
top: number
left: number
}

function isNonLegacyCanvasSize(size: Record<string, number>): size is CanvasSize {
return 'top' in size
}

export type ContainerProps = {
scene: THREE.Scene
index: number
children?: React.ReactNode
frames: number
rect: React.MutableRefObject<DOMRect>
track: React.MutableRefObject<HTMLElement>
canvasSize: Size
canvasSize: LegacyCanvasSize | CanvasSize
}

export type ViewProps = {
Expand All @@ -27,6 +47,23 @@ export type ViewProps = {
children?: React.ReactNode
}

function computeContainerPosition(canvasSize: LegacyCanvasSize | CanvasSize, trackRect: DOMRect): any {
const { right, top, left: trackLeft, bottom: trackBottom, width, height } = trackRect

if (isNonLegacyCanvasSize(canvasSize)) {
const canvasBottom = canvasSize.top + canvasSize.height
const bottom = canvasBottom - trackBottom
const left = trackLeft - canvasSize.left

return { left, right, top, bottom, width, height }
}

// Fall back on old behavior if r3f < 8.1.0
const bottom = canvasSize.height - trackBottom

return { left: trackLeft, right, top, bottom, width, height }
}

function Container({ canvasSize, scene, index, children, frames, rect, track }: ContainerProps) {
const get = useThree((state) => state.get)
const camera = useThree((state) => state.camera)
Expand All @@ -41,9 +78,9 @@ function Container({ canvasSize, scene, index, children, frames, rect, track }:
}

if (rect.current) {
const { left, right, top, bottom, width, height } = rect.current
const { left, right, top, bottom, width, height } = computeContainerPosition(canvasSize, rect.current)
const isOffscreen = bottom < 0 || top > canvasSize.height || right < 0 || left > canvasSize.width
const positiveYUpBottom = canvasSize.height - bottom

const aspect = width / height

if (isOrthographicCamera(camera)) {
Expand All @@ -61,8 +98,8 @@ function Container({ canvasSize, scene, index, children, frames, rect, track }:
camera.updateProjectionMatrix()
}

state.gl.setViewport(left, positiveYUpBottom, width, height)
state.gl.setScissor(left, positiveYUpBottom, width, height)
state.gl.setViewport(left, bottom, width, height)
state.gl.setScissor(left, bottom, width, height)
state.gl.setScissorTest(true)

if (isOffscreen) {
Expand All @@ -84,6 +121,16 @@ function Container({ canvasSize, scene, index, children, frames, rect, track }:
return () => setEvents({ connected: old })
}, [])

React.useEffect(() => {
if (isNonLegacyCanvasSize(canvasSize)) {
return
}
console.warn(
'Detected @react-three/fiber canvas size does not include position information. <View /> may not work as expected. ' +
'Upgrade to @react-three/fiber ^8.1.0 for support.\n See https://github.com/pmndrs/drei/issues/944'
)
}, [])

return <>{children}</>
}

Expand Down

0 comments on commit f012910

Please sign in to comment.