@react-three/drei
Version:
useful add-ons for react-three-fiber
101 lines (96 loc) • 2.9 kB
JavaScript
import _extends from '@babel/runtime/helpers/esm/extends';
import * as THREE from 'three';
import * as React from 'react';
import { SkeletonUtils } from 'three-stdlib';
function createSpread(child, {
keys = ['near', 'far', 'color', 'distance', 'decay', 'penumbra', 'angle', 'intensity', 'skeleton', 'visible', 'castShadow', 'receiveShadow', 'morphTargetDictionary', 'morphTargetInfluences', 'name', 'geometry', 'material', 'position', 'rotation', 'scale', 'up', 'userData', 'bindMode', 'bindMatrix', 'bindMatrixInverse', 'skeleton'],
deep,
inject,
castShadow,
receiveShadow
}) {
let spread = {};
for (const key of keys) {
spread[key] = child[key];
}
if (deep) {
if (spread.geometry && deep !== 'materialsOnly') spread.geometry = spread.geometry.clone();
if (spread.material && deep !== 'geometriesOnly') spread.material = spread.material.clone();
}
if (inject) {
if (typeof inject === 'function') spread = {
...spread,
children: inject(child)
};else if (/*#__PURE__*/React.isValidElement(inject)) spread = {
...spread,
children: inject
};else spread = {
...spread,
...inject
};
}
if (child instanceof THREE.Mesh) {
if (castShadow) spread.castShadow = true;
if (receiveShadow) spread.receiveShadow = true;
}
return spread;
}
const Clone = /* @__PURE__ */React.forwardRef(({
isChild = false,
object,
children,
deep,
castShadow,
receiveShadow,
inject,
keys,
...props
}, forwardRef) => {
const config = {
keys,
deep,
inject,
castShadow,
receiveShadow
};
object = React.useMemo(() => {
if (isChild === false && !Array.isArray(object)) {
let isSkinned = false;
object.traverse(object => {
if (object.isSkinnedMesh) isSkinned = true;
});
if (isSkinned) return SkeletonUtils.clone(object);
}
return object;
}, [object, isChild]);
// Deal with arrayed clones
if (Array.isArray(object)) {
return /*#__PURE__*/React.createElement("group", _extends({}, props, {
ref: forwardRef
}), object.map(o => /*#__PURE__*/React.createElement(Clone, _extends({
key: o.uuid,
object: o
}, config))), children);
}
// Singleton clones
const {
children: injectChildren,
...spread
} = createSpread(object, config);
const Element = object.type[0].toLowerCase() + object.type.slice(1);
return /*#__PURE__*/React.createElement(Element, _extends({}, spread, props, {
ref: forwardRef
}), object.children.map(child => {
if (child.type === 'Bone') return /*#__PURE__*/React.createElement("primitive", _extends({
key: child.uuid,
object: child
}, config));
return /*#__PURE__*/React.createElement(Clone, _extends({
key: child.uuid,
object: child
}, config, {
isChild: true
}));
}), children, injectChildren);
});
export { Clone };