UNPKG

@react-three/drei

Version:

useful add-ons for react-three-fiber

97 lines (94 loc) 3.43 kB
import _extends from '@babel/runtime/helpers/esm/extends'; import * as THREE from 'three'; import * as React from 'react'; import { extend, useFrame } from '@react-three/fiber'; import { Line2, LineMaterial, LineSegmentsGeometry } from 'three-stdlib'; const context = /* @__PURE__ */React.createContext(null); const Segments = /* @__PURE__ */React.forwardRef((props, forwardedRef) => { React.useMemo(() => extend({ SegmentObject }), []); const { limit = 1000, lineWidth = 1.0, children, ...rest } = props; const [segments, setSegments] = React.useState([]); const [line] = React.useState(() => new Line2()); const [material] = React.useState(() => new LineMaterial()); const [geometry] = React.useState(() => new LineSegmentsGeometry()); const [resolution] = React.useState(() => new THREE.Vector2(512, 512)); const [positions] = React.useState(() => Array(limit * 6).fill(0)); const [colors] = React.useState(() => Array(limit * 6).fill(0)); const api = React.useMemo(() => ({ subscribe: ref => { setSegments(segments => [...segments, ref]); return () => setSegments(segments => segments.filter(item => item.current !== ref.current)); } }), []); useFrame(() => { for (let i = 0; i < limit; i++) { var _segments$i; const segment = (_segments$i = segments[i]) == null ? void 0 : _segments$i.current; if (segment) { positions[i * 6 + 0] = segment.start.x; positions[i * 6 + 1] = segment.start.y; positions[i * 6 + 2] = segment.start.z; positions[i * 6 + 3] = segment.end.x; positions[i * 6 + 4] = segment.end.y; positions[i * 6 + 5] = segment.end.z; colors[i * 6 + 0] = segment.color.r; colors[i * 6 + 1] = segment.color.g; colors[i * 6 + 2] = segment.color.b; colors[i * 6 + 3] = segment.color.r; colors[i * 6 + 4] = segment.color.g; colors[i * 6 + 5] = segment.color.b; } } geometry.setColors(colors); geometry.setPositions(positions); line.computeLineDistances(); }); return /*#__PURE__*/React.createElement("primitive", { object: line, ref: forwardedRef }, /*#__PURE__*/React.createElement("primitive", { object: geometry, attach: "geometry" }), /*#__PURE__*/React.createElement("primitive", _extends({ object: material, attach: "material", vertexColors: true, resolution: resolution, linewidth: lineWidth }, rest)), /*#__PURE__*/React.createElement(context.Provider, { value: api }, children)); }); class SegmentObject { constructor() { this.color = new THREE.Color('white'); this.start = new THREE.Vector3(0, 0, 0); this.end = new THREE.Vector3(0, 0, 0); } } const normPos = pos => pos instanceof THREE.Vector3 ? pos : new THREE.Vector3(...(typeof pos === 'number' ? [pos, pos, pos] : pos)); const Segment = /* @__PURE__ */React.forwardRef(({ color, start, end }, forwardedRef) => { const api = React.useContext(context); if (!api) throw 'Segment must used inside Segments component.'; const ref = React.useRef(null); React.useImperativeHandle(forwardedRef, () => ref.current, []); React.useLayoutEffect(() => api.subscribe(ref), []); return /*#__PURE__*/React.createElement("segmentObject", { ref: ref, color: color, start: normPos(start), end: normPos(end) }); }); export { Segment, SegmentObject, Segments };