UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

151 lines (122 loc) 4.2 kB
import { LinearToneMapping, NoToneMapping } from "three" import { getExposure } from "../../states/useExposure" import { getResolution, setResolution } from "../../states/useResolution" import { createEffect, createNestedEffect } from "@lincode/reactivity" import { getWebXR } from "../../states/useWebXR" import { getRenderer } from "../../states/useRenderer" import { getPBR } from "../../states/usePBR" import { getSecondaryCamera } from "../../states/useSecondaryCamera" import { VRButton } from "./VRButton" import { getAutoMount } from "../../states/useAutoMount" import { debounce } from "@lincode/utils" import { getEditorMounted } from "../../states/useEditorMounted" import { getPixelRatio } from "../../states/usePixelRatio" const rootContainer = document.createElement("div") Object.assign(rootContainer.style, { position: "absolute", left: "0px", top: "0px", width: "100%", height: "100%" }) export const container = document.createElement("div") Object.assign(container.style, { position: "absolute", left: "0px", top: "0px", width: "100%" }) rootContainer.appendChild(container) getSecondaryCamera((cam) => (container.style.height = cam ? "50%" : "100%")) export const containerBounds = [container.getBoundingClientRect()] const useResize = (el: Element) => { createNestedEffect(() => { const handleResize = () => { containerBounds[0] = container.getBoundingClientRect() setResolution( el === document.body ? [window.innerWidth, window.innerHeight] : [el.clientWidth, el.clientHeight] ) } handleResize() const handleResizeDebounced = debounce(handleResize, 100, "both") window.addEventListener("resize", handleResizeDebounced) const handle = getEditorMounted(handleResizeDebounced) return () => { window.removeEventListener("resize", handleResize) handle.cancel() } }, [el]) } createEffect(() => { const autoMount = getAutoMount() if (!autoMount) return if (typeof autoMount === "string") { const el = document.querySelector(autoMount) if (!el) return el.prepend(rootContainer) useResize(el) return () => { el.removeChild(rootContainer) } } if (autoMount === true) { document.body.prepend(rootContainer) useResize(document.body) return () => { document.body.removeChild(rootContainer) } } autoMount.prepend(rootContainer) useResize(autoMount) return () => { autoMount.removeChild(rootContainer) } }, [getAutoMount]) createEffect(() => { const renderer = getRenderer() if (!renderer) return const canvas = renderer.domElement rootContainer.prepend(canvas) Object.assign(canvas.style, { position: "absolute", left: "0px", top: "0px" }) return () => { rootContainer.removeChild(canvas) } }, [getRenderer]) createEffect(() => { const renderer = getRenderer() if (!renderer) return const [w, h] = getResolution() renderer.setSize(w, h) renderer.setPixelRatio(Math.min(getPixelRatio(), devicePixelRatio)) }, [getRenderer, getResolution, getPixelRatio]) createEffect(() => { const renderer = getRenderer() if (!renderer) return renderer.physicallyCorrectLights = getPBR() }, [getRenderer, getPBR]) createEffect(() => { const renderer = getRenderer() if (!renderer) return const exposure = getExposure() renderer.toneMapping = exposure !== 1 ? LinearToneMapping : NoToneMapping renderer.toneMappingExposure = exposure }, [getExposure, getRenderer]) createEffect(() => { if (!getWebXR()) return const renderer = getRenderer() if (!renderer) return renderer.xr.enabled = true const button = VRButton.createButton(renderer) container.appendChild(button) button.ontouchstart = () => button.onclick?.(new MouseEvent("click")) return () => { renderer.xr.enabled = false container.removeChild(button) } }, [getWebXR, getRenderer])