Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instance switching / constructor argument changes for Object3Ds do not work properly #3317

Open
Omxjep3434 opened this issue Jul 31, 2024 · 0 comments

Comments

@Omxjep3434
Copy link

Omxjep3434 commented Jul 31, 2024

Description

There is a bug in the switchInstance() method in renderer.ts when invoked on a class deriving from Object3D. Not all children will be preserved during the switch due to the nature of the for..of loop, and removing children of the instance within that loop. The loop needs to be modified to support instance.children having elements removed during iteration.

Code example:

In the following code example, you'll see that the second mesh gets lost when the Group is reconstructed.

function InstanceSwitchingIssue() {
  const [constructorArg, setConstructorArg] = useState(0);

  return (
    <>
      <button onClick={() => setConstructorArg(constructorArg + 1)}>Reconstruct Group</button>

      <Canvas>
        <group args={[constructorArg]}>
          <mesh width={1} geometry={new BoxGeometry()} position={[-1, 0, 0]} material-color="red">
          </mesh>

          <mesh width={1} geometry={new BoxGeometry()} position={[1, 0, 0]} material-color="green">
          </mesh>
        </group>
      </Canvas>
    </>
  );
}

Problematic code (renderer.ts)

    // https://github.com/pmndrs/react-three-fiber/issues/1348
    // When args change the instance has to be re-constructed, which then
    // forces r3f to re-parent the children and non-scene objects
    if (instance.children) {
      for (const child of instance.children) {
        // MY NOTE: Appending to the new instance will also remove from the old instance, causing the iteration problem.
        if (child.__r3f) appendChild(newInstance, child)
      }
      instance.children = instance.children.filter((child) => !child.__r3f)
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant