101 lines
2.8 KiB
JavaScript
101 lines
2.8 KiB
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 };
|