Quellcode durchsuchen

feat: on-demand automatic invalidation with prop changes

alvarosabu vor 1 Jahr
Ursprung
Commit
b2cfa4a92b

+ 7 - 1
playground/src/pages/rendering-modes/scene.vue

@@ -8,13 +8,19 @@ function onControlChange() {
   invalidate()
 }
 
+const positionX = ref(0)
+
+setTimeout(() => {
+  positionX.value = 1
+}, 3000)
+
 invalidate()
 </script>
 
 <template>
   <OrbitControls @change="onControlChange" />
   <TresGridHelper />
-  <TresMesh>
+  <TresMesh :position-x="positionX">
     <TresBoxGeometry />
     <TresMeshNormalMaterial />
   </TresMesh>

+ 1 - 1
src/components/TresCanvas.vue

@@ -45,7 +45,7 @@ export interface TresCanvasProps
   useLegacyLights?: boolean
   outputColorSpace?: ColorSpace
   toneMappingExposure?: number
-  renderMode?: 'always' | 'on-demand' 
+  renderMode?: 'always' | 'on-demand' | 'manual' 
 
   // required by useTresContextProvider
   camera?: TresCamera

+ 1 - 1
src/composables/useRenderer/index.ts

@@ -96,7 +96,7 @@ export interface UseRendererOptions extends TransformToMaybeRefOrGetter<WebGLRen
   clearColor?: MaybeRefOrGetter<TresColor>
   windowSize?: MaybeRefOrGetter<boolean | string>
   preset?: MaybeRefOrGetter<RendererPresetsType>
-  renderMode?: MaybeRefOrGetter<'always' | 'on-demand'>
+  renderMode?: MaybeRefOrGetter<'always' | 'on-demand' | 'manual'>
 }
 
 /**

+ 6 - 1
src/composables/useTresContextProvider/index.ts

@@ -38,6 +38,7 @@ export interface TresContext {
   renderer: ShallowRef<WebGLRenderer>
   raycaster: ShallowRef<Raycaster>
   perf: PerformanceState
+  renderMode: MaybeRefOrGetter<'always' | 'on-demand' | 'manual'>
   internal: InternalState
   invalidate: () => void
   registerCamera: (camera: Camera) => void
@@ -125,6 +126,7 @@ export function useTresContextProvider({
         accumulator: [],
       },
     },
+    renderMode: ref(rendererOptions.renderMode || 'always'),
     internal,
     extend,
     invalidate,
@@ -135,6 +137,9 @@ export function useTresContextProvider({
 
   provide('useTres', toProvide)
 
+  // Add context to scene.userData
+  toProvide.scene.value.userData.tres__context = toProvide
+
   // Performance
   const updateInterval = 100 // Update interval in milliseconds
   const fps = useFps({ every: updateInterval }) 
@@ -182,7 +187,7 @@ export function useTresContextProvider({
   let accumulatedTime = 0
   const interval = 1 // Interval in milliseconds, e.g., 1000 ms = 1 second
     
-  const { pause, resume } = useRafFn(({ delta }) => {
+  const { pause } = useRafFn(({ delta }) => {
     if (!window.__TRES__DEVTOOLS__) return
 
     updatePerformanceData({ timestamp: performance.now() })

+ 21 - 1
src/core/nodeOps.ts

@@ -23,6 +23,17 @@ const supportedPointerEvents = [
   'onPointerLeave',
 ]
 
+export function invalidateInstance(instance: TresObject) {
+  const ctx = instance.userData.tres__root?.userData?.tres__context
+  
+  if (!ctx) return
+  
+  if (ctx.renderMode.value === 'on-demand' && ctx.internal.frames.value === 0) {
+    ctx.invalidate()
+  }
+
+}
+
 export const nodeOps: RendererOptions<TresObject, TresObject> = {
   createElement(tag, _isSVG, _anchor, props) {
     if (!props) props = {}
@@ -81,11 +92,17 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
     return instance
   },
   insert(child, parent) {
-    if (parent && parent.isScene) scene = parent as unknown as TresScene
+    if (parent && parent.isScene) {
+      scene = parent as unknown as TresScene
+      if (child) {
+        child.userData.tres__root = scene
+      }
+    }
 
     const parentObject = parent || scene
 
     if (child?.isObject3D) {
+
       if (child?.isCamera) {
         if (!scene?.userData.tres__registerCamera)
           throw 'could not find tres__registerCamera on scene\'s userData'
@@ -180,6 +197,7 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
       deregisterAtPointerEventHandlerIfRequired?.(object3D as TresObject)
     }
 
+    invalidateInstance(node as TresObject)
     node.dispose?.()
   },
   patchProp(node, prop, _prevValue, nextValue) {
@@ -243,6 +261,8 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
       else if (Array.isArray(value)) target.set(...value)
       else if (!target.isColor && target.setScalar) target.setScalar(value)
       else target.set(value)
+
+      invalidateInstance(node as TresObject)
     }
   },
 

+ 4 - 1
src/devtools/plugin.ts

@@ -271,12 +271,15 @@ export function registerTresDevtools(app: DevtoolsApp, tres: TresContext) {
                 key: 'matrixWorld',
                 value: instance.matrixWorld,
               },
-                
               {
                 key: 'visible',
                 editable: true,
                 value: instance.visible,
               },
+              {
+                key: 'userData',
+                value: instance.userData,
+              },
             ],
           }
         }