Procházet zdrojové kódy

fix: added logic on pathProps to re-instance nodes once `args` change (#367)

* fix: added logic on pathProps to re-instance nodes once `args` change

* chore: moved deep equal check to utils

* chore: add return on key args check
Alvaro Saburido před 1 rokem
rodič
revize
453b031b25
3 změnil soubory, kde provedl 57 přidání a 4 odebrání
  1. 9 2
      playground/src/components/DebugUI.vue
  2. 10 1
      src/core/nodeOps.ts
  3. 38 1
      src/utils/index.ts

+ 9 - 2
playground/src/components/DebugUI.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { TresCanvas } from '@tresjs/core'
 import { BasicShadowMap, SRGBColorSpace, NoToneMapping } from 'three'
+import { OrbitControls } from '@tresjs/cientos'
 
 // import { OrbitControls, Box } from '@tresjs/cientos'
 /* import { TresLeches, useControls } from '@tresjs/leches' */
@@ -19,13 +20,19 @@ const gl = reactive({
 // useControls(gl)
 // useControls('Box', boxPosition.value)
 
+const boxWidth = ref(1)
+
+setTimeout(() => {
+  boxWidth.value = 2
+}, 2000)
 </script>
 
 <template>
   <TresCanvas v-bind="gl" :window-size="true">
     <TresPerspectiveCamera :look-at="[0, 4, 0]" />
-    <TresMesh :position="[0, 4, 0]">
-      <TresBoxGeometry :args="[1, 1, 1]" />
+    <OrbitControls />
+    <TresMesh :position="[0, 1, 0]">
+      <TresBoxGeometry :args="[boxWidth, 1, 1]" />
       <TresMeshToonMaterial color="teal" />
     </TresMesh>
     <TresGridHelper />

+ 10 - 1
src/core/nodeOps.ts

@@ -3,7 +3,7 @@ import { BufferAttribute } from 'three'
 import { isFunction } from '@alvarosabu/utils'
 import { useLogger } from '../composables'
 import { catalogue } from './catalogue'
-import { isHTMLTag, kebabToCamel } from '../utils'
+import { deepArrayEqual, isHTMLTag, kebabToCamel } from '../utils'
 
 import type { Object3D, Camera } from 'three'
 import type { TresObject, TresObject3D, TresScene } from '../types'
@@ -184,6 +184,15 @@ export const nodeOps: RendererOptions<TresObject, TresObject> = {
       let finalKey = kebabToCamel(key)
       let target = root?.[finalKey]
 
+      if (key === 'args' && !deepArrayEqual(_prevValue, nextValue)) {
+        const prevNode = node as TresObject3D
+
+        if (node.type && nextValue.length > 0) {
+          root = Object.assign(prevNode, new catalogue.value[node.type](...nextValue))
+        }
+        return
+      }
+
       if (root.type === 'BufferGeometry') {
         if (key === 'args') return
         root.setAttribute(

+ 38 - 1
src/utils/index.ts

@@ -73,4 +73,41 @@ export const set = (obj: any, path: string | string[], value: any): void => {
       if (i === pathArray.length - 1) acc[key] = value;
       return acc[key];
     }, obj);
-};
+};
+
+
+export function deepEqual(a: any, b: any): boolean {
+  // If both are primitives, return true if they are equal
+  if (a === b) return true;
+
+  // If either of them is null or not an object, return false
+  if (a === null || typeof a !== "object" || b === null || typeof b !== "object") return false;
+
+  // Get the keys of both objects
+  const keysA = Object.keys(a), keysB = Object.keys(b);
+
+  // If they have different number of keys, they are not equal
+  if (keysA.length !== keysB.length) return false;
+
+  // Check each key in A to see if it exists in B and its value is the same in both
+  for (const key of keysA) {
+    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
+  }
+
+  return true;
+}
+
+export function deepArrayEqual(arr1: any[], arr2: any[]): boolean {
+  // If they're not both arrays, return false
+  if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false;
+
+  // If they don't have the same length, they're not equal
+  if (arr1.length !== arr2.length) return false;
+
+  // Check each element of arr1 against the corresponding element of arr2
+  for (let i = 0; i < arr1.length; i++) {
+    if (!deepEqual(arr1[i], arr2[i])) return false;
+  }
+
+  return true;
+}