浏览代码

refactor!: removed useTresReady, added isReady to the renderer in the… (#1000)

* refactor!: removed useTresReady, added isReady to the renderer in the context

BREAKING CHANGE:

- useTresReady is no longer available, it has been replaced by isReady in the renderer in the context
- onTresReady is no longer available. renderer.isReady should be leveraged instead

* chore: removed playground files concerning useTresReady

* chore: removed ready pages from playground routes

* feature: made isReady dependency clearer by leveraging triggerRef
Tino Koch 3 周之前
父节点
当前提交
ff35bfce49

+ 0 - 62
playground/vue/src/pages/basic/ready/LoopCallbackWatcher.vue

@@ -1,62 +0,0 @@
-<script setup lang="ts">
-import { useLoop } from '@tresjs/core'
-import { ref, type ShallowRef, shallowRef } from 'vue'
-
-const isCalled = ref(false)
-
-interface TestResult { passed: boolean, msg: string }
-const messages = shallowRef([
-  {
-    passed: false,
-    msg: 'callback was not called',
-  },
-]) as ShallowRef<TestResult[]>
-
-const captureCallback = (renderer: any, _elapsed: number) => {
-  if (!isCalled.value) {
-    isCalled.value = true
-    const isRendererOk = !!renderer
-    const domElement = renderer?.domElement
-    const isDomElementOk = !!(domElement) && domElement.width > 0 && domElement.height > 0
-
-    messages.value = [
-      {
-        passed: true,
-        msg: 'When the callback was called for the first time ...',
-      },
-      {
-        passed: isRendererOk,
-        msg: isRendererOk ? '... the renderer existed.' : '... the renderer did not exist.',
-      },
-      {
-        passed: !!domElement,
-        msg: domElement ? '... the canvas existed.' : '... the canvas did not exist.',
-      },
-      {
-        passed: isDomElementOk,
-        msg: isDomElementOk
-          ? `... the canvas was not degenerate: ${domElement.width} px × ${domElement.height} px.`
-          : `... the canvas was degenerate.`,
-      },
-    ]
-  }
-}
-
-useLoop().onBeforeRender(({ elapsed: _elapsed, renderer }) => {
-  captureCallback(renderer, _elapsed)
-})
-
-useLoop().render(({ elapsed: _elapsed, renderer, scene, camera }) => {
-  captureCallback(renderer, _elapsed)
-  renderer.render(scene, camera)
-})
-
-useLoop().onAfterRender(({ elapsed: _elapsed, renderer }) => {
-  captureCallback(renderer, _elapsed)
-})
-
-defineExpose({
-  isCalled,
-  messages,
-})
-</script>

+ 0 - 69
playground/vue/src/pages/basic/ready/OnTresReadyWatcher.vue

@@ -1,69 +0,0 @@
-<script setup lang="ts">
-import { onTresReady, type TresContext } from '@tresjs/core'
-import { ref, type ShallowRef, shallowRef } from 'vue'
-
-const isCalled = ref(false)
-
-interface TestResult { passed: boolean, msg: string }
-const messages = shallowRef([
-  {
-    passed: false,
-    msg: 'callback was not called',
-  },
-]) as ShallowRef<TestResult[]>
-
-const captureCallback = (ctx: TresContext) => {
-  if (isCalled.value) {
-    messages.value = [
-      {
-        passed: false,
-        msg: 'Callback was called twice.',
-      },
-    ]
-  }
-  if (!isCalled.value) {
-    isCalled.value = true
-    const isCtxOk = !!(ctx && 'renderer' in ctx && 'scene' in ctx)
-    const renderer = ctx.renderer.instance.value
-    const isRendererOk = !!renderer
-    const domElement = renderer?.domElement
-    const isDomElementOk = !!(domElement) && domElement.width > 0 && domElement.height > 0
-
-    messages.value = [
-      {
-        passed: true,
-        msg: 'When the callback was called ...',
-      },
-      {
-        passed: true,
-        msg: '... it had not previously been called.',
-      },
-      {
-        passed: isCtxOk,
-        msg: isCtxOk ? '... TresContext was passed.' : '... TresContext was not passed.',
-      },
-      {
-        passed: isRendererOk,
-        msg: isRendererOk ? '... the renderer existed.' : '... the renderer did not exist.',
-      },
-      {
-        passed: !!domElement,
-        msg: domElement ? '... the canvas existed.' : '... the canvas did not exist.',
-      },
-      {
-        passed: isDomElementOk,
-        msg: isDomElementOk
-          ? `... the canvas was not degenerate: ${domElement.width} px × ${domElement.height} px.`
-          : `... the canvas was degenerate.`,
-      },
-    ]
-  }
-}
-
-onTresReady(captureCallback)
-
-defineExpose({
-  isCalled,
-  messages,
-})
-</script>

+ 0 - 165
playground/vue/src/pages/basic/ready/index.vue

@@ -1,165 +0,0 @@
-<script setup lang="ts">
-import type { TresContext } from '@tresjs/core'
-import type { ShallowRef } from 'vue'
-import { TresCanvas } from '@tresjs/core'
-import { ref } from 'vue'
-import LoopCallbackWatcher from './LoopCallbackWatcher.vue'
-import OnTresReadyWatcher from './OnTresReadyWatcher.vue'
-
-interface TestResult { passed: boolean, msg: string }
-
-const onReadyMessages = shallowRef([
-  {
-    passed: false,
-    msg: '@ready callback was not called',
-  },
-]) as ShallowRef<TestResult[]>
-
-let numOnReadyCalls = 0
-
-const onReady = function (ctx: TresContext) {
-  numOnReadyCalls++
-
-  const renderer = ctx.renderer.instance.value
-  const domElement = renderer?.domElement
-  const isPassedCanvas = domElement.width > 0 && domElement.width > 0
-  const isPassedCtx = !!renderer && 'camera' in ctx && !!(ctx.camera.value)
-
-  onReadyMessages.value = [
-    {
-      passed: true,
-      msg: 'When the callback was called ...',
-    },
-    {
-      passed: numOnReadyCalls === 1,
-      msg: '... it had not previously been called.',
-    },
-    {
-      passed: isPassedCtx,
-      msg: isPassedCtx ? '... TresContext was passed.' : '... TresContext was not passed or was missing elements',
-    },
-    {
-      passed: !!renderer,
-      msg: renderer ? '... the renderer existed.' : '... the renderer did not exist.',
-    },
-    {
-      passed: !!domElement,
-      msg: domElement ? '... the canvas existed.' : '... the canvas did not exist.',
-    },
-    {
-      passed: isPassedCanvas,
-      msg: isPassedCanvas
-        ? `... the canvas was not degenerate: ${domElement.width} px × ${domElement.height} px.`
-        : `... the canvas was degenerate.`,
-    },
-  ]
-}
-
-const onTresReadyWatcherRef = ref({
-  isCalled: false,
-  messages: [] as TestResult[],
-})
-
-const loopCallbackWatcherRef = ref({
-  isCalled: false,
-  messages: [] as TestResult[],
-})
-</script>
-
-<template>
-  <div class="overlay">
-    <h1>When is Tres ready?</h1>
-    <p>
-      Tres is "ready" if either:
-    </p>
-    <ul>
-      <li>
-        The scene can be meaningfully rendered.
-      </li>
-      <ul>
-        <li>the renderer exists</li>
-        <li>the canvas width and height are > 0</li>
-      </ul>
-      <li>Tres has waited 100 ms - assumes setup is intentionally degenerate.</li>
-    </ul>
-    <hr />
-    <h1>"ready" in user space</h1>
-    <h2><code>&lt;TresCanvas @ready="(ctx:TresContext) => {}"&gt;</code></h2>
-    <p>A callback can be defined in the <code>&lt;script setup /&gt;</code> of a &lt;TresCanvas&gt;.</p>
-    <ul>
-      <li
-        v-for="({ passed, msg }, i) of onReadyMessages"
-        :key="i"
-        :class="passed ? 'pass' : 'fail'"
-      >
-        <span>{{ passed ? "✅" : "❌" }} {{ msg }}</span>
-      </li>
-    </ul>
-    <h2><code>onTresReady((ctx:TresContext) => {})</code></h2>
-    <p><code>onTresReady</code> can only be called in a child component.</p>
-    <ul>
-      <li
-        v-for="({ passed, msg }, i) of onTresReadyWatcherRef.messages"
-        :key="i"
-        :class="passed ? 'pass' : 'fail'"
-      >
-        <span>{{ passed ? "✅" : "❌" }} {{ msg }}</span>
-      </li>
-    </ul>
-    <h2><code>useLoop()...(callback)</code></h2>
-    <p><code>useLoop</code> can only be called in a child component.</p>
-    <ul>
-      <li
-        v-for="({ passed, msg }, i) of loopCallbackWatcherRef.messages"
-        :key="i"
-        :class="passed ? 'pass' : 'fail'"
-      >
-        <span>{{ passed ? "✅" : "❌" }} {{ msg }}</span>
-      </li>
-    </ul>
-    <hr />
-    <h1>Context</h1>
-    <p>
-      <a href="https://github.com/Tresjs/tres/issues/595">See this Github issue for further explanation.</a>
-    </p>
-  </div>
-  <TresCanvas clear-color="gray" @ready="onReady">
-    <LoopCallbackWatcher ref="loopCallbackWatcherRef" />
-    <OnTresReadyWatcher ref="onTresReadyWatcherRef" />
-    <TresMesh>
-      <TresBoxGeometry />
-      <TresMeshNormalMaterial />
-    </TresMesh>
-  </TresCanvas>
-</template>
-
-<style scoped>
-.overlay {
-  position: fixed;
-  z-index: 1000;
-  margin: 10px;
-  padding: 10px;
-  border-radius: 6px;
-  max-width: 400px;
-  font-family: sans-serif;
-  font-size: small;
-  background-color: white;
-}
-
-.overlay .pass {
-  color: green;
-}
-
-.overlay .fail {
-  color: red;
-}
-
-.overlay li {
-  padding-left: 0;
-  margin-left: 0;
-}
-.overlay ul {
-  padding-left: 0;
-  margin-left: 1.5em;
-}
-</style>

+ 0 - 5
playground/vue/src/router/routes/basic.ts

@@ -44,11 +44,6 @@ export const basicRoutes = [
     name: 'Pierced Props',
     component: () => import('../../pages/basic/PiercedProps.vue'),
   },
-  {
-    path: '/basic/ready',
-    name: '@ready',
-    component: () => import('../../pages/basic/ready/index.vue'),
-  },
   {
     path: '/basic/textures',
     name: 'Textures',

+ 5 - 4
src/components/TresCanvas.vue

@@ -36,6 +36,7 @@ import { nodeOps } from '../core/nodeOps'
 
 import { disposeObject3D, kebabToCamel } from '../utils/'
 import { registerTresDevtools } from '../devtools'
+import { whenever } from '@vueuse/core'
 
 export interface TresCanvasProps
   extends Omit<WebGLRendererParameters, 'canvas'> {
@@ -244,14 +245,14 @@ onMounted(() => {
     )
   })
 
-  context.value.onReady(() => {
-    if (context.value) { emit('ready', context.value) }
-  })
-
   // HMR support
   if (import.meta.hot && context.value) { import.meta.hot.on('vite:afterUpdate', () => handleHMR(context.value as TresContext)) }
 })
 
+whenever(() => context.value?.renderer.isReady, () => {
+  if (context.value) { emit('ready', context.value) }
+}, { once: true })
+
 onUnmounted(unmountCanvas)
 </script>
 

+ 0 - 1
src/composables/index.ts

@@ -11,5 +11,4 @@ export * from './useRenderLoop'
 export * from './useTexture'
 export * from './useTresContextProvider'
 export * from './useTresEventManager'
-export { onTresReady } from './useTresReady'
 export { UseLoader, UseTexture }

+ 8 - 1
src/composables/useRenderer/useRendererManager.ts

@@ -11,7 +11,7 @@ import {
   useDevicePixelRatio,
 } from '@vueuse/core'
 import { ACESFilmicToneMapping, Color, WebGLRenderer } from 'three'
-import { computed, type MaybeRef, onUnmounted, ref, shallowRef, toValue, watch, watchEffect } from 'vue'
+import { computed, type MaybeRef, onUnmounted, readonly, ref, shallowRef, toValue, triggerRef, watch, watchEffect } from 'vue'
 
 // Solution taken from Thretle that actually support different versions https://github.com/threlte/threlte/blob/5fa541179460f0dadc7dc17ae5e6854d1689379e/packages/core/src/lib/lib/useRenderer.ts
 import { revision } from '../../core/revision'
@@ -196,9 +196,15 @@ export function useRendererManager(
     invalidateOnDemand()
   })
 
+  const isReady = computed(() =>
+    !!(instance.value.domElement.width && instance.value.domElement.height),
+  )
+
   watch([sizes.width, sizes.height], () => {
     instance.value.setSize(sizes.width.value, sizes.height.value)
     invalidateOnDemand()
+
+    triggerRef(instance)
   }, {
     immediate: true,
   })
@@ -305,6 +311,7 @@ export function useRendererManager(
   return {
     instance,
 
+    isReady: readonly(isReady),
     advance,
     onRender,
     invalidate,

+ 7 - 12
src/composables/useTresContextProvider/index.ts

@@ -12,8 +12,7 @@ import { useCamera } from '../useCamera'
 import { useRendererManager } from '../useRenderer/useRendererManager'
 import useSizes, { type SizesType } from '../useSizes'
 import { type TresEventManager, useTresEventManager } from '../useTresEventManager'
-import { useTresReady } from '../useTresReady'
-import { createEventHook, type EventHookOff } from '@vueuse/core'
+import { whenever } from '@vueuse/core'
 
 export interface PerformanceState {
   maxFrames: number
@@ -52,7 +51,6 @@ export interface TresContext {
   deregisterObjectAtPointerEventHandler?: (object: TresObject) => void
   registerBlockingObjectAtPointerEventHandler?: (object: TresObject) => void
   deregisterBlockingObjectAtPointerEventHandler?: (object: TresObject) => void
-  onReady: EventHookOff<TresContext> // TODO #980 consider removing this
 }
 
 export function useTresContextProvider({
@@ -88,8 +86,6 @@ export function useTresContextProvider({
     },
   )
 
-  const readyEventHook = createEventHook<TresContext>() // TODO #980 consider removing this
-
   const ctx: TresContext = {
     sizes,
     scene: localScene,
@@ -115,7 +111,6 @@ export function useTresContextProvider({
     setCameraActive,
     deregisterCamera,
     loop,
-    onReady: readyEventHook.on,
   }
 
   provide('useTres', ctx)
@@ -125,19 +120,19 @@ export function useTresContextProvider({
     root: ctx,
   }
 
-  const { on: onTresReady, cancel: cancelTresReady } = useTresReady(ctx)!
-
   ctx.loop.setReady(false)
   ctx.loop.start()
 
-  onTresReady(() => {
-    readyEventHook.trigger(ctx)
+  whenever(renderer.isReady, () => { // TODO #994 This does not belong here, see https://github.com/Tresjs/tres/issues/595
     ctx.loop.setReady(true)
-    useTresEventManager(scene, ctx)
+  }, {
+    once: true,
+    immediate: true,
   })
 
+  useTresEventManager(scene, ctx)
+
   onUnmounted(() => {
-    cancelTresReady()
     ctx.loop.stop()
   })
 

+ 0 - 187
src/composables/useTresReady/createReadyEventHook/createReadyHook.test.ts

@@ -1,187 +0,0 @@
-import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
-import { createReadyEventHook } from './index'
-
-describe('createReadyEventHook', () => {
-  beforeEach(() => {
-    vi.useFakeTimers()
-  })
-
-  afterEach(() => {
-    vi.restoreAllMocks()
-  })
-
-  describe('createReadyEventHook(getIsReady)', () => {
-    it('calls getIsReady when created', () => {
-      const getIsReady = vi.fn(() => true)
-      createReadyEventHook(getIsReady, null)
-      expect(getIsReady).toBeCalled()
-    })
-
-    it('calls getIsReady periodically', () => {
-      const fn = vi.fn(() => false)
-      createReadyEventHook(fn, null, 1)
-      vi.advanceTimersByTime(1000)
-      expect(fn).toHaveBeenCalledTimes(1000 + 1)
-    })
-
-    it('calls getIsReady periodically, but only until `getIsReady()` is truthy', () => {
-      let i = 0
-      const fn0 = () => {
-        i++
-        return i === 5
-      }
-      createReadyEventHook(fn0, null)
-      vi.advanceTimersByTime(1000)
-      expect(i).toBe(5)
-
-      i = -1
-      const fn1 = () => {
-        i++
-        return i
-      }
-      createReadyEventHook(fn1 as any, null)
-      vi.advanceTimersByTime(1000)
-      expect(i).toBe(1)
-    })
-
-    it('calls getIsReady periodically, but only while not cancelled', () => {
-      const fn = vi.fn(() => false)
-      const { cancel } = createReadyEventHook(fn, null, 1)
-      vi.advanceTimersByTime(99)
-      cancel()
-      vi.advanceTimersByTime(1000)
-      expect(fn).toHaveBeenCalledTimes(100)
-    })
-  })
-
-  describe('createReadyEventHook(getIsReady, intervalMs)', () => {
-    it('calls getIsReady at the provided interval', () => {
-      const fn = vi.fn(() => false)
-      createReadyEventHook(fn, null, 100)
-      expect(fn).toHaveBeenCalledTimes(1)
-      vi.advanceTimersByTime(99)
-      expect(fn).toHaveBeenCalledTimes(1)
-      vi.advanceTimersByTime(1000)
-      expect(fn).toHaveBeenCalledTimes(10 + 1)
-      vi.advanceTimersByTime(5000)
-      expect(fn).toHaveBeenCalledTimes(50 + 10 + 1)
-    })
-  })
-
-  describe('createReadyEventHook().on', () => {
-    it('registers a function and calls it once `getIsReady() === true`', () => {
-      const fn = vi.fn()
-      const { on } = createReadyEventHook(trueIfCalledNTimes(10), null)
-
-      on(fn)
-      vi.advanceTimersByTime(10000)
-
-      expect(fn).toHaveBeenCalledTimes(1)
-    })
-
-    it('calls registered functions with args', () => {
-      const fn0 = vi.fn()
-      const fn1 = vi.fn()
-      const arg0 = { foo: 'bar' }
-      const arg1 = { baz: 'boo' }
-      const { on } = createReadyEventHook(() => true, [arg0, arg1])
-
-      on(fn0)
-      on(fn1)
-
-      expect(fn0).toHaveBeenCalledWith([{ foo: 'bar' }, { baz: 'boo' }])
-      expect(fn1).toHaveBeenCalledWith([{ foo: 'bar' }, { baz: 'boo' }])
-    })
-
-    it('calls a function immediately if `getIsReady() === true`', () => {
-      const fn = vi.fn()
-      const { on } = createReadyEventHook(() => true, null)
-
-      on(fn)
-
-      expect(fn).toHaveBeenCalledTimes(1)
-    })
-
-    it('calls functions with arg immediately if `getIsReady() === true`', () => {
-      const fn0 = vi.fn()
-      const fn1 = vi.fn()
-      const arg = { foo: 'bar' }
-      const { on } = createReadyEventHook(() => true, arg)
-
-      on(fn0)
-      on(fn1)
-
-      expect(fn0).toHaveBeenCalledWith({ foo: 'bar' })
-      expect(fn1).toHaveBeenCalledWith({ foo: 'bar' })
-    })
-
-    it('can register many functions, one at a time', () => {
-      const fns = Array.from({ length: 100 })
-        .fill(0)
-        .map(_ => vi.fn())
-
-      const { on } = createReadyEventHook(trueIfCalledNTimes(10), null)
-      fns.forEach(fn => on(fn))
-      vi.advanceTimersByTime(10000)
-
-      for (const fn of fns) {
-        expect(fn).toHaveBeenCalledTimes(1)
-      }
-    })
-  })
-
-  describe('createReadyEventHook().off(fn)', () => {
-    it('unregisters a function', () => {
-      const fns = Array.from({ length: 100 })
-        .fill(0)
-        .map(_ => vi.fn())
-
-      const { on, off } = createReadyEventHook(trueIfCalledNTimes(10), null)
-      fns.forEach(fn => on(fn))
-
-      const offedFns = new Set()
-      fns.forEach((fn) => {
-        if (Math.random() < 0.5) {
-          offedFns.add(fn)
-          off(fn)
-        }
-      })
-      vi.advanceTimersByTime(10000)
-
-      fns.forEach((fn) => {
-        expect(fn).toHaveBeenCalledTimes(offedFns.has(fn) ? 0 : 1)
-      })
-    })
-  })
-
-  describe('createReadyEventHook().on(fn).off()', () => {
-    it('unregisters a function', () => {
-      const fns = Array.from({ length: 100 })
-        .fill(0)
-        .map(_ => vi.fn())
-
-      const { on } = createReadyEventHook(trueIfCalledNTimes(10), null)
-
-      const offedFns = new Set()
-      fns.forEach((fn) => {
-        const { off } = on(fn)
-        if (Math.random() < 0.5) {
-          offedFns.add(fn)
-          off()
-        }
-      })
-      vi.advanceTimersByTime(1000)
-
-      fns.forEach((fn) => {
-        expect(fn).toHaveBeenCalledTimes(offedFns.has(fn) ? 0 : 1)
-      })
-    })
-  })
-})
-
-function trueIfCalledNTimes(n: number) {
-  return () => {
-    n = Math.max(n - 1, 0)
-    return n === 0
-  }
-}

+ 0 - 87
src/composables/useTresReady/createReadyEventHook/index.ts

@@ -1,87 +0,0 @@
-import type { EventHook, EventHookOn, IsAny } from '@vueuse/core'
-import { createEventHook } from '@vueuse/core'
-
-type Callback<T> =
-  IsAny<T> extends true
-    ? (param: any) => void
-    : [T] extends [void]
-        ? () => void
-        : (param: T) => void
-
-export function createReadyEventHook<T>(
-  getIsReady: () => boolean,
-  triggerParams: T,
-  pollIntervalMs = 100,
-): EventHook<T> & { cancel: () => void } {
-  pollIntervalMs = pollIntervalMs <= 0 ? 100 : pollIntervalMs
-  const hook = createEventHook()
-  // NOTE: This hook will likely be long-lived and
-  // we don't want to interfere with garbage collection
-  // in the meantime.
-  // Keep a set of `offFns` and call them after `getIsReady`
-  // in order to remove them from the `hook`.
-  const offFns = new Set<() => void>()
-  let ready = false
-  let cancelled = false
-  let timeoutId: ReturnType<typeof setTimeout> | null = null
-
-  function doReadyTest() {
-    if (timeoutId) {
-      clearTimeout(timeoutId)
-    }
-    if (!cancelled && !ready && getIsReady()) {
-      hook.trigger(triggerParams)
-      offFns.forEach(offFn => offFn())
-      offFns.clear()
-      ready = true
-    }
-    else if (!cancelled && !ready) {
-      timeoutId = setTimeout(doReadyTest, pollIntervalMs)
-    }
-  }
-
-  function cancel() {
-    cancelled = true
-    if (timeoutId) {
-      clearTimeout(timeoutId)
-    }
-  }
-
-  if (import.meta.hot) {
-    import.meta.hot.on('vite:afterUpdate', () => {
-      ready = false
-      doReadyTest()
-    })
-  }
-
-  doReadyTest()
-
-  const triggerSingleCallback = (callback: Callback<T>, ...args: [T]) => {
-    callback(...args)
-  }
-
-  const onOrCall: EventHookOn<T> = (callback) => {
-    if (!ready) {
-      const onFn = hook.on(callback)
-
-      if (!import.meta.hot) {
-        // NOTE: We must keep callbacks around for HMR.
-        // But if it doesn't exist, remove callbacks.
-        offFns.add(onFn.off)
-      }
-      return hook.on(callback)
-    }
-    else {
-      triggerSingleCallback(callback as Callback<T>, triggerParams)
-      return { off: () => {} }
-    }
-  }
-
-  return {
-    on: onOrCall,
-    off: hook.off,
-    trigger: hook.trigger,
-    clear: hook.clear,
-    cancel,
-  }
-}

+ 0 - 53
src/composables/useTresReady/index.ts

@@ -1,53 +0,0 @@
-import type { TresContext } from '../useTresContextProvider'
-import { useTresContext } from '../useTresContextProvider'
-import { createReadyEventHook } from './createReadyEventHook'
-
-const ctxToUseTresReady = new WeakMap<
-  TresContext,
-  ReturnType<typeof createReadyEventHook<TresContext>>
->()
-
-export function useTresReady(ctx?: TresContext) {
-  ctx = ctx || useTresContext()
-  if (ctxToUseTresReady.has(ctx)) {
-    return ctxToUseTresReady.get(ctx)!
-  }
-
-  const MAX_READY_WAIT_MS = 100
-  const start = Date.now()
-
-  // NOTE: Consider Tres to be "ready" if either is true:
-  // - MAX_READY_WAIT_MS has passed (assume Tres is intentionally degenerate)
-  // - Tres is not degenerate
-  //     - A renderer exists
-  //     - A DOM element exists
-  //     - The DOM element's height/width is not 0
-  const getTresIsReady = () => {
-    if (Date.now() - start >= MAX_READY_WAIT_MS) {
-      return true
-    }
-    else {
-      const renderer = ctx.renderer.instance.value
-      const domElement = renderer?.domElement || { width: 0, height: 0 }
-      return !!(renderer && domElement.width > 0 && domElement.height > 0)
-    }
-  }
-
-  const args = ctx as TresContext
-  const result = createReadyEventHook(getTresIsReady, args)
-  ctxToUseTresReady.set(ctx, result)
-
-  return result
-}
-
-export function onTresReady(fn: (ctx: TresContext) => void) {
-  const ctx = useTresContext()
-  if (ctx) {
-    if (ctxToUseTresReady.has(ctx)) {
-      return ctxToUseTresReady.get(ctx)!.on(fn)
-    }
-    else {
-      return useTresReady(ctx).on(fn)
-    }
-  }
-}