浏览代码

Merge pull request #175 from Tresjs/feature/174-useseek-composable

feat: 174 useseek composable
Alvaro Saburido 2 年之前
父节点
当前提交
795b99df6e
共有 5 个文件被更改,包括 123 次插入0 次删除
  1. 0 0
      .prettierrc.cjs
  2. 29 0
      docs/api/composables.md
  3. 1 0
      src/composables/index.ts
  4. 62 0
      src/composables/useSeek/index.ts
  5. 31 0
      src/composables/useSeek/useSeek.test.ts

+ 0 - 0
.prettierrc.js → .prettierrc.cjs


+ 29 - 0
docs/api/composables.md

@@ -170,6 +170,35 @@ Then you can use the new component in your template. Notice that the new compone
 </template>
 ```
 
+## useSeek
+
+The `useSeek` composable provides utilities to easily traverse and navigate through complex ThreeJS scenes and object children graphs. It exports two functions, `seek` and `seekByName`, which allow you to find child objects based on specific properties.
+
+```ts
+const { seek, seekbyName } = useSeek()
+```
+
+The seek function accepts three parameters:
+
+- `parent`: A ThreeJS scene or Object3D.
+- `property`: The property to be used in the search condition.
+- `value`: The value of the property to match.
+
+Both function traverses the object and returns the child object with the specified property and value. If no child with the given property and value is found, it returns null and logs a warning.
+
+```ts
+const carRef = ref(null)
+
+watch(carRef, ({ model }) => {
+  if (model) {
+    const car = model.children[0]
+
+    const body = seek(car, 'name', 'Octane_Octane_Body_0')
+    body.color.set(new Color('blue'))
+  }
+)
+```
+
 ## useTres
 
 This composable aims to provide access to the state model which contains the default renderer, camera, scene, and other useful properties.

+ 1 - 0
src/composables/index.ts

@@ -6,3 +6,4 @@ export * from './useTexture'
 export * from './useTres'
 export * from './useRaycaster'
 export * from './useLogger'
+export * from './useSeek'

+ 62 - 0
src/composables/useSeek/index.ts

@@ -0,0 +1,62 @@
+import { useLogger } from '/@/composables'
+
+/**
+ * Seek composable return type
+ *
+ * @export
+ * @interface UseSeekReturn
+ */
+export interface UseSeekReturn {
+  seek: (parent: THREE.Scene | THREE.Object3D, property: string, value: string) => THREE.Object3D | null
+  seekByName: (parent: THREE.Scene | THREE.Object3D, value: string) => THREE.Object3D | null
+}
+
+/**
+ * Composable that provides utilities to easily traverse and navigate through complex scenes and object children graphs
+ *
+ * @export
+ * @return {*}  {UseSeekReturn}
+ */
+export function useSeek(): UseSeekReturn {
+  const { logWarning } = useLogger()
+
+  /**
+   * Returns a child object of the parent given a property
+   *
+   * @param {(THREE.Scene | THREE.Object3D)} parent
+   * @param {string} property
+   * @param {string} value
+   * @return {*}  {(THREE.Object3D | null)}
+   */
+  function seek(parent: THREE.Scene | THREE.Object3D, property: string, value: string): THREE.Object3D | null {
+    let foundChild: THREE.Object3D | null = null
+
+    parent.traverse(child => {
+      if ((child as any)[property] === value) {
+        foundChild = child
+      }
+    })
+
+    if (!foundChild) {
+      logWarning(`Child with ${property} '${value}' not found.`)
+    }
+
+    return foundChild
+  }
+
+  /**
+   * Returns a child object of the parent given a child.name
+   *
+   * @param {(THREE.Scene | THREE.Object3D)} parent
+   * @param {string} value
+   * @return {*}  {(THREE.Object3D | null)}
+   */
+  function seekByName(parent: THREE.Scene | THREE.Object3D, value: string): THREE.Object3D | null {
+    return seek(parent, 'name', value)
+  }
+
+  return {
+    seek,
+    seekByName,
+  }
+}

+ 31 - 0
src/composables/useSeek/useSeek.test.ts

@@ -0,0 +1,31 @@
+import { Object3D } from 'three'
+import { useSeek } from '.'
+import { withSetup } from '/@/utils/test-utils'
+
+const [composable, app] = withSetup(() => useSeek())
+
+describe('useRaycaster', () => {
+  afterEach(() => {
+    app.unmount()
+  })
+  test('should find a child by a property', () => {
+    const { seek } = composable
+    const parent = new Object3D()
+    const child = new Object3D()
+    ;(child as any).customProperty = 'customValue'
+    parent.add(child)
+
+    const result = seek(parent, 'customProperty', 'customValue')
+    expect(result).toBe(child)
+  })
+  test('should find a child by a property', () => {
+    const { seekByName } = composable
+    const parent = new Object3D()
+    const child = new Object3D()
+    child.name = 'testChild'
+    parent.add(child)
+
+    const result = seekByName(parent, 'testChild')
+    expect(result).toBe(child)
+  })
+})