Bläddra i källkod

fix: make on* callbacks settable (#672)

* fix: make on- callbacks settable

* test: test setting not calling
andretchen0 1 år sedan
förälder
incheckning
ac152dfa91

+ 72 - 0
playground/src/pages/basic/OnCallbacks.vue

@@ -0,0 +1,72 @@
+<script setup lang="ts">
+import { TresCanvas } from '@tresjs/core'
+import { Mesh, MeshBasicMaterial, SphereGeometry } from 'three'
+
+const geo = new SphereGeometry()
+const mat = new MeshBasicMaterial()
+const obj = new Mesh(geo, mat)
+
+const meshNumOnBeforeRenders = shallowRef(0)
+const meshNumOnAfterRenders = shallowRef(0)
+const primitiveNumOnBeforeRenders = shallowRef(0)
+const primitiveNumOnAfterRenders = shallowRef(0)
+const materialNumOnBeforeCompiles = shallowRef(0)
+
+const meshOnBeforeRender = () => { meshNumOnBeforeRenders.value++ }
+const meshOnAfterRender = () => { meshNumOnAfterRenders.value++ }
+const primitiveOnBeforeRender = () => { primitiveNumOnBeforeRenders.value++ }
+const primitiveOnAfterRender = () => { primitiveNumOnAfterRenders.value++ }
+const materialOnBeforeCompile = () => { materialNumOnBeforeCompiles.value++ }
+</script>
+
+<template>
+  <div class="overlay">
+    <h2>Primitive</h2>
+    <ul>
+      <li># onBeforeRender calls: {{ primitiveNumOnBeforeRenders }}</li>
+      <li># onAfterRender calls: {{ primitiveNumOnAfterRenders }}</li>
+    </ul>
+    <h2>Mesh</h2>
+    <ul>
+      <li># onBeforeRender calls: {{ meshNumOnBeforeRenders }}</li>
+      <li># onAfterRender calls: {{ meshNumOnAfterRenders }}</li>
+    </ul>
+    <h2>Material</h2>
+    <ul>
+      <li># onBeforeCompile calls: {{ materialNumOnBeforeCompiles }}</li>
+    </ul>
+  </div>
+  <TresCanvas>
+    <TresMesh
+      :position="[1, 0, 0]"
+      :scale="0.5"
+      :on-before-render="meshOnBeforeRender"
+      :on-after-render="meshOnAfterRender"
+    >
+      <TresBoxGeometry />
+      <TresMeshStandardMaterial
+        :on-before-compile="materialOnBeforeCompile"
+      />
+    </TresMesh>
+    <primitive
+      :object="obj"
+      :position="[-1, 0, 0]"
+      :scale="0.5"
+      :on-before-render="primitiveOnBeforeRender"
+      :on-after-render="primitiveOnAfterRender"
+    />
+    <TresGridHelper :args="[10, 10, 0x444444, 'teal']" />
+  </TresCanvas>
+</template>
+
+<style scoped>
+.overlay {
+  position: fixed;
+  z-index: 1;
+  font-family: sans-serif;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 10px;
+  margin: 10px;
+}
+</style>

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

@@ -34,6 +34,11 @@ export const basicRoutes = [
     name: 'Responsiveness',
     component: () => import('../../pages/basic/Responsiveness.vue'),
   },
+  {
+    path: '/basic/onCallbacks',
+    name: 'on... callbacks',
+    component: () => import('../../pages/basic/OnCallbacks.vue'),
+  },
   {
     path: '/basic/pierced-props',
     name: 'Pierced Props',

+ 21 - 0
src/core/nodeOps.test.ts

@@ -301,6 +301,27 @@ describe('nodeOps', () => {
       expect(node.defines[allCapsUnderscoresKey]).equals(allCapsUnderscoresValue)
     })
 
+    it('replaces "on*" methods on Object3D', () => {
+      // Issue: https://github.com/Tresjs/tres/issues/360
+      const { createElement, patchProp } = nodeOps
+      const object = createElement('TresObject3D', undefined, undefined, {})
+
+      const onAfterRender = () => {}
+      const onAfterShadow = () => {}
+      const onBeforeRender = () => {}
+      const onBeforeShadow = () => {}
+
+      patchProp(object, 'onAfterRender', null, onAfterRender)
+      patchProp(object, 'onAfterShadow', null, onAfterShadow)
+      patchProp(object, 'onBeforeRender', null, onBeforeRender)
+      patchProp(object, 'onBeforeShadow', null, onBeforeShadow)
+
+      expect(object.onAfterRender).toBe(onAfterRender)
+      expect(object.onAfterShadow).toBe(onAfterShadow)
+      expect(object.onBeforeRender).toBe(onBeforeRender)
+      expect(object.onBeforeShadow).toBe(onBeforeShadow)
+    })
+
     it('calls object methods', () => {
       const camera = nodeOps.createElement('TresPerspectiveCamera', undefined, undefined, {})
       const spy = vi.spyOn(camera, 'lookAt')

+ 5 - 0
src/core/nodeOps.ts

@@ -272,6 +272,11 @@ export const nodeOps: () => RendererOptions<TresObject, TresObject | null> = ()
           if (Array.isArray(value)) { node[finalKey](...value) }
           else { node[finalKey](value) }
         }
+        // NOTE: Set on* callbacks
+        // Issue: https://github.com/Tresjs/tres/issues/360
+        if (finalKey.startsWith('on') && isFunction(value)) {
+          root[finalKey] = value
+        }
         return
       }
       if (!target?.set && !isFunction(target)) { root[finalKey] = value }