pmndrs / react-three-fiber

🇨🇭 A React renderer for Three.js
https://docs.pmnd.rs/react-three-fiber
MIT License
27.62k stars 1.6k forks source link

feat: add childadded event dispatch #3214

Closed rubeniskov closed 8 months ago

rubeniskov commented 8 months ago

Three r0.162.0 has now support for childadded event in Object3D's

https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L345-L349

Example of implementation for get added objects

import { useEffect, useMemo, useState } from 'react';
import { Layers, Object3D, Object3DEventMap } from 'three';

import { useThree } from '@react-three/fiber';
import useEventCallback from 'use-event-callback';

/**
 * Get all objects in the scene,
 *
 * Inspired in https://github.com/mrdoob/three.js/pull/16934#issuecomment-506793917
 */
export const useSceneObjects = () => {
  const [sceneObjects, setSceneObjects] = useState<Object3D[]>([]);
  const scene = useThree(({ scene }) => scene);

  const addNode = useEventCallback((evt: Object3DEventMap['childadded']) => {
    evt.child.traverse((node) => {
      node.addEventListener('childadded', addNode);
      node.addEventListener('childremoved', removeNode);
        setSceneObjects((prev) => [...prev, node]);
    });
  });

  const removeNode = useEventCallback((evt: Object3DEventMap['childremoved']) => {
    evt.child.traverse((node) => {
      node.removeEventListener('childadded', addNode);
      node.removeEventListener('childremoved', removeNode);
      setSceneObjects((prev) => prev.filter((n) => n !== node));
    });
  });

  useEffect(() => {
    addNode({ child: scene });
  }, [addNode, scene]);

  return sceneObjects;
};

export default useSceneObjects;
codesandbox-ci[bot] commented 8 months ago

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit a08dfb62315ea654d507cf52395b87c8512fee05:

Sandbox Source
example Configuration