UNPKG

@react-three/csg

Version:

Constructive solid geometry for React

187 lines (169 loc) 6.41 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _extends = require('@babel/runtime/helpers/extends'); var React = require('react'); var fiber = require('@react-three/fiber'); var threeBvhCsg = require('three-bvh-csg'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var _extends__default = /*#__PURE__*/_interopDefaultLegacy(_extends); var React__namespace = /*#__PURE__*/_interopNamespace(React); const TYPES = { subtraction: threeBvhCsg.SUBTRACTION, reverseSubtraction: threeBvhCsg.REVERSE_SUBTRACTION, addition: threeBvhCsg.ADDITION, difference: threeBvhCsg.DIFFERENCE, intersection: threeBvhCsg.INTERSECTION }; function dispose(geometry) { geometry.dispose(); geometry.attributes = {}; geometry.groups = []; geometry.boundsTree = geometry.index = geometry.boundingBox = geometry.boundingSphere = null; geometry.drawRange = { start: 0, count: Infinity }; } function resolve(op) { let currentOp = null; if (op instanceof threeBvhCsg.Brush) { op.updateMatrixWorld(); currentOp = op; } else { op.traverse(obj => { obj.updateMatrixWorld(); if (!currentOp && obj instanceof threeBvhCsg.Brush) currentOp = obj; }); } return currentOp; } const csgContext = /*#__PURE__*/React__namespace.createContext(null); const Geometry = /*#__PURE__*/React__namespace.forwardRef(({ children, computeVertexNormals = false, useGroups = false, consolidateGroups = false, showOperations = false }, fref) => { const geo = React__namespace.useRef(null); const operations = React__namespace.useRef(null); const ev = React__namespace.useMemo(() => Object.assign(new threeBvhCsg.Evaluator(), { useGroups, consolidateGroups }), [useGroups, consolidateGroups]); const update = React__namespace.useCallback(() => { try { const ops = operations.current.children.slice(); if (ops.length > 0) { // Dispose old geometry dispose(geo.current); // Set the ops groups matrix to identiy operations.current.matrixWorld.identity(); let root = resolve(ops.shift()); if (root) { var _geo$current, _geo$current$__r3f, _geo$current$__r3f$pa, _geo$current$__r3f$pa2; while (ops.length) { const op = resolve(ops.shift()); if (op) root = ev.evaluate(root, op, TYPES[op.operator] || threeBvhCsg.ADDITION); } ; geo.current.boundsTree = root.geometry.boundsTree; geo.current.index = root.geometry.index; geo.current.attributes = root.geometry.attributes; geo.current.groups = root.geometry.groups; geo.current.drawRange = root.geometry.drawRange; if (ev.useGroups && (_geo$current = geo.current) != null && (_geo$current$__r3f = _geo$current.__r3f) != null && (_geo$current$__r3f$pa = _geo$current$__r3f.parent) != null && (_geo$current$__r3f$pa2 = _geo$current$__r3f$pa.object) != null && _geo$current$__r3f$pa2.material) geo.current.__r3f.parent.object.material = root.material; if (computeVertexNormals) geo.current.computeVertexNormals(); } } } catch (e) { console.log(e); } }, [computeVertexNormals, ev]); const api = React__namespace.useMemo(() => ({ computeVertexNormals, showOperations, useGroups, consolidateGroups, update }), [computeVertexNormals, showOperations, useGroups, consolidateGroups]); React__namespace.useLayoutEffect(() => void update()); React__namespace.useImperativeHandle(fref, () => ({ geometry: geo.current, operations: operations.current, ...api }), [api]); return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("group", { matrixAutoUpdate: false, ref: operations }, /*#__PURE__*/React__namespace.createElement(csgContext.Provider, { value: api }, children)), /*#__PURE__*/React__namespace.createElement("bufferGeometry", { ref: geo })); }); const Base = /*#__PURE__*/React__namespace.forwardRef(({ showOperation = false, operator = 'addition', ...props }, fref) => { fiber.extend({ Brush: threeBvhCsg.Brush }); const { showOperations } = React__namespace.useContext(csgContext); return /*#__PURE__*/React__namespace.createElement("brush", _extends__default["default"]({ operator: operator, raycast: () => null, visible: showOperation || showOperations, ref: fref }, props)); }); const Addition = /*#__PURE__*/React__namespace.forwardRef((props, fref) => /*#__PURE__*/React__namespace.createElement(Base, _extends__default["default"]({ ref: fref, operator: "addition" }, props))); const Subtraction = /*#__PURE__*/React__namespace.forwardRef((props, fref) => /*#__PURE__*/React__namespace.createElement(Base, _extends__default["default"]({ ref: fref, operator: "subtraction" }, props))); const ReverseSubtraction = /*#__PURE__*/React__namespace.forwardRef((props, fref) => /*#__PURE__*/React__namespace.createElement(Base, _extends__default["default"]({ ref: fref, operator: "reverseSubtraction" }, props))); const Difference = /*#__PURE__*/React__namespace.forwardRef((props, fref) => /*#__PURE__*/React__namespace.createElement(Base, _extends__default["default"]({ ref: fref, operator: "difference" }, props))); const Intersection = /*#__PURE__*/React__namespace.forwardRef((props, fref) => /*#__PURE__*/React__namespace.createElement(Base, _extends__default["default"]({ ref: fref, operator: "intersection" }, props))); function useCSG() { return React__namespace.useContext(csgContext); } exports.Addition = Addition; exports.Base = Base; exports.Difference = Difference; exports.Geometry = Geometry; exports.Intersection = Intersection; exports.ReverseSubtraction = ReverseSubtraction; exports.Subtraction = Subtraction; exports.useCSG = useCSG;