summit/frontend/node_modules/@react-three/fiber/native/dist/react-three-fiber-native.cj...

555 lines
18 KiB
JavaScript

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var events = require('../../dist/events-d0566a2e.cjs.dev.js');
var React = require('react');
var THREE = require('three');
var reactNative = require('react-native');
var expoGl = require('expo-gl');
var itsFine = require('its-fine');
var jsxRuntime = require('react/jsx-runtime');
var expoAsset = require('expo-asset');
var fs = require('expo-file-system');
var base64Js = require('base64-js');
var buffer = require('buffer');
require('react-reconciler/constants');
require('zustand');
require('suspend-react');
require('react-reconciler');
require('scheduler');
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 React__namespace = /*#__PURE__*/_interopNamespace(React);
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
/**
* A native canvas which accepts threejs elements as children.
* @see https://docs.pmnd.rs/react-three-fiber/api/canvas
*/
const CanvasImpl = /*#__PURE__*/React__namespace.forwardRef(({
children,
style,
gl,
events: events$1 = events.createPointerEvents,
shadows,
linear,
flat,
legacy,
orthographic,
frameloop,
performance,
raycaster,
camera,
scene,
onPointerMissed,
onCreated,
...props
}, forwardedRef) => {
// Create a known catalogue of Threejs-native elements
// This will include the entire THREE namespace by default, users can extend
// their own elements by using the createRoot API instead
React__namespace.useMemo(() => events.extend(THREE__namespace), []);
const Bridge = itsFine.useContextBridge();
const [{
width,
height,
top,
left
}, setSize] = React__namespace.useState({
width: 0,
height: 0,
top: 0,
left: 0
});
const [canvas, setCanvas] = React__namespace.useState(null);
const [bind, setBind] = React__namespace.useState();
React__namespace.useImperativeHandle(forwardedRef, () => viewRef.current);
const handlePointerMissed = events.useMutableCallback(onPointerMissed);
const [block, setBlock] = React__namespace.useState(false);
const [error, setError] = React__namespace.useState(undefined);
// Suspend this component if block is a promise (2nd run)
if (block) throw block;
// Throw exception outwards if anything within canvas throws
if (error) throw error;
const viewRef = React__namespace.useRef(null);
const root = React__namespace.useRef(null);
const [antialias, setAntialias] = React__namespace.useState(true);
const onLayout = React__namespace.useCallback(e => {
const {
width,
height,
x,
y
} = e.nativeEvent.layout;
setSize({
width,
height,
top: y,
left: x
});
}, []);
// Called on context create or swap
// https://github.com/pmndrs/react-three-fiber/pull/2297
const onContextCreate = React__namespace.useCallback(context => {
const listeners = new Map();
const canvas = {
style: {},
width: context.drawingBufferWidth,
height: context.drawingBufferHeight,
clientWidth: context.drawingBufferWidth,
clientHeight: context.drawingBufferHeight,
getContext: (_, {
antialias = false
}) => {
setAntialias(antialias);
return context;
},
addEventListener(type, listener) {
let callbacks = listeners.get(type);
if (!callbacks) {
callbacks = [];
listeners.set(type, callbacks);
}
callbacks.push(listener);
},
removeEventListener(type, listener) {
const callbacks = listeners.get(type);
if (callbacks) {
const index = callbacks.indexOf(listener);
if (index !== -1) callbacks.splice(index, 1);
}
},
dispatchEvent(event) {
Object.assign(event, {
target: this
});
const callbacks = listeners.get(event.type);
if (callbacks) {
for (const callback of callbacks) {
callback(event);
}
}
},
setPointerCapture() {
// TODO
},
releasePointerCapture() {
// TODO
}
};
// TODO: this is wrong but necessary to trick controls
// @ts-ignore
canvas.ownerDocument = canvas;
canvas.getRootNode = () => canvas;
root.current = events.createRoot(canvas);
setCanvas(canvas);
function handleTouch(gestureEvent, type) {
gestureEvent.persist();
canvas.dispatchEvent(Object.assign(gestureEvent.nativeEvent, {
type,
offsetX: gestureEvent.nativeEvent.locationX,
offsetY: gestureEvent.nativeEvent.locationY,
pointerType: 'touch',
pointerId: gestureEvent.nativeEvent.identifier
}));
return true;
}
const responder = reactNative.PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onStartShouldSetPanResponderCapture: e => handleTouch(e, 'pointercapture'),
onPanResponderStart: e => handleTouch(e, 'pointerdown'),
onPanResponderMove: e => handleTouch(e, 'pointermove'),
onPanResponderEnd: (e, state) => {
handleTouch(e, 'pointerup');
if (Math.hypot(state.dx, state.dy) < 20) handleTouch(e, 'click');
},
onPanResponderRelease: e => handleTouch(e, 'pointerleave'),
onPanResponderTerminate: e => handleTouch(e, 'lostpointercapture'),
onPanResponderReject: e => handleTouch(e, 'lostpointercapture')
});
setBind(responder.panHandlers);
}, []);
if (root.current && width > 0 && height > 0) {
root.current.configure({
gl,
events: events$1,
shadows,
linear,
flat,
legacy,
orthographic,
frameloop,
performance,
raycaster,
camera,
scene,
// expo-gl can only render at native dpr/resolution
// https://github.com/expo/expo-three/issues/39
dpr: reactNative.PixelRatio.get(),
size: {
width,
height,
top,
left
},
// Pass mutable reference to onPointerMissed so it's free to update
onPointerMissed: (...args) => handlePointerMissed.current == null ? void 0 : handlePointerMissed.current(...args),
// Overwrite onCreated to apply RN bindings
onCreated: state => {
// Bind render to RN bridge
const context = state.gl.getContext();
const renderFrame = state.gl.render.bind(state.gl);
state.gl.render = (scene, camera) => {
renderFrame(scene, camera);
context.endFrameEXP();
};
return onCreated == null ? void 0 : onCreated(state);
}
});
root.current.render( /*#__PURE__*/jsxRuntime.jsx(Bridge, {
children: /*#__PURE__*/jsxRuntime.jsx(events.ErrorBoundary, {
set: setError,
children: /*#__PURE__*/jsxRuntime.jsx(React__namespace.Suspense, {
fallback: /*#__PURE__*/jsxRuntime.jsx(events.Block, {
set: setBlock
}),
children: children != null ? children : null
})
})
}));
}
React__namespace.useEffect(() => {
if (canvas) {
return () => events.unmountComponentAtNode(canvas);
}
}, [canvas]);
return /*#__PURE__*/jsxRuntime.jsx(reactNative.View, {
...props,
ref: viewRef,
onLayout: onLayout,
style: {
flex: 1,
...style
},
...bind,
children: width > 0 && /*#__PURE__*/jsxRuntime.jsx(expoGl.GLView, {
msaaSamples: antialias ? 4 : 0,
onContextCreate: onContextCreate,
style: reactNative.StyleSheet.absoluteFill
})
});
});
/**
* A native canvas which accepts threejs elements as children.
* @see https://docs.pmnd.rs/react-three-fiber/api/canvas
*/
const Canvas = /*#__PURE__*/React__namespace.forwardRef(function CanvasWrapper(props, ref) {
return /*#__PURE__*/jsxRuntime.jsx(itsFine.FiberProvider, {
children: /*#__PURE__*/jsxRuntime.jsx(CanvasImpl, {
...props,
ref: ref
})
});
});
/** Default R3F event manager for react-native */
function createTouchEvents(store) {
const {
handlePointer
} = events.createEvents(store);
const handleTouch = (event, name) => {
event.persist()
// Apply offset
;
event.nativeEvent.offsetX = event.nativeEvent.locationX;
event.nativeEvent.offsetY = event.nativeEvent.locationY;
// Emulate DOM event
const callback = handlePointer(name);
callback(event.nativeEvent);
return true;
};
const responder = reactNative.PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onStartShouldSetPanResponderCapture: e => handleTouch(e, 'onPointerCapture'),
onPanResponderStart: e => handleTouch(e, 'onPointerDown'),
onPanResponderMove: e => handleTouch(e, 'onPointerMove'),
onPanResponderEnd: (e, state) => {
handleTouch(e, 'onPointerUp');
if (Math.hypot(state.dx, state.dy) < 20) handleTouch(e, 'onClick');
},
onPanResponderRelease: e => handleTouch(e, 'onPointerLeave'),
onPanResponderTerminate: e => handleTouch(e, 'onLostPointerCapture'),
onPanResponderReject: e => handleTouch(e, 'onLostPointerCapture')
});
return {
priority: 1,
enabled: true,
compute(event, state, previous) {
// https://github.com/pmndrs/react-three-fiber/pull/782
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
state.raycaster.setFromCamera(state.pointer, state.camera);
},
connected: undefined,
handlers: responder.panHandlers,
update: () => {
var _internal$lastEvent;
const {
events,
internal
} = store.getState();
if ((_internal$lastEvent = internal.lastEvent) != null && _internal$lastEvent.current && events.handlers) {
handlePointer('onPointerMove')(internal.lastEvent.current);
}
},
connect: () => {
const {
set,
events
} = store.getState();
events.disconnect == null ? void 0 : events.disconnect();
set(state => ({
events: {
...state.events,
connected: true
}
}));
},
disconnect: () => {
const {
set
} = store.getState();
set(state => ({
events: {
...state.events,
connected: false
}
}));
}
};
}
// http://stackoverflow.com/questions/105034
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random() * 16 | 0,
v = c == 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
}
async function getAsset(input) {
if (typeof input === 'string') {
var _NativeModules$BlobMo;
// Don't process storage
if (input.startsWith('file:')) return input;
// Unpack Blobs from react-native BlobManager
// https://github.com/facebook/react-native/issues/22681#issuecomment-523258955
if (input.startsWith('blob:') || input.startsWith((_NativeModules$BlobMo = reactNative.NativeModules.BlobModule) == null ? void 0 : _NativeModules$BlobMo.BLOB_URI_SCHEME)) {
const blob = await new Promise((res, rej) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', input);
xhr.responseType = 'blob';
xhr.onload = () => res(xhr.response);
xhr.onerror = rej;
xhr.send();
});
const data = await new Promise((res, rej) => {
const reader = new FileReader();
reader.onload = () => res(reader.result);
reader.onerror = rej;
reader.readAsText(blob);
});
input = `data:${blob.type};base64,${data}`;
}
// Create safe URI for JSI serialization
if (input.startsWith('data:')) {
const [header, data] = input.split(';base64,');
const [, type] = header.split('/');
const uri = fs__namespace.cacheDirectory + uuidv4() + `.${type}`;
await fs__namespace.writeAsStringAsync(uri, data, {
encoding: fs__namespace.EncodingType.Base64
});
return uri;
}
}
// Download bundler module or external URL
const asset = await expoAsset.Asset.fromModule(input).downloadAsync();
let uri = asset.localUri || asset.uri;
// Unpack assets in Android Release Mode
if (!uri.includes(':')) {
const file = `${fs__namespace.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}`;
await fs__namespace.copyAsync({
from: uri,
to: file
});
uri = file;
}
return uri;
}
function polyfills() {
// Patch Blob for ArrayBuffer and URL if unsupported
// https://github.com/facebook/react-native/pull/39276
// https://github.com/pmndrs/react-three-fiber/issues/3058
if (reactNative.Platform.OS !== 'web') {
try {
const blob = new Blob([new ArrayBuffer(4)]);
const url = URL.createObjectURL(blob);
URL.revokeObjectURL(url);
} catch (_) {
const BlobManager = require('react-native/Libraries/Blob/BlobManager.js');
const createObjectURL = URL.createObjectURL;
URL.createObjectURL = function (blob) {
if (blob.data._base64) {
return `data:${blob.type};base64,${blob.data._base64}`;
}
return createObjectURL(blob);
};
const createFromParts = BlobManager.createFromParts;
BlobManager.createFromParts = function (parts, options) {
parts = parts.map(part => {
if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
part = base64Js.fromByteArray(new Uint8Array(part));
}
return part;
});
const blob = createFromParts(parts, options);
// Always enable slow but safe path for iOS (previously for Android unauth)
// https://github.com/pmndrs/react-three-fiber/issues/3075
// if (!NativeModules.BlobModule?.BLOB_URI_SCHEME) {
blob.data._base64 = '';
for (const part of parts) {
var _data$_base, _data;
blob.data._base64 += (_data$_base = (_data = part.data) == null ? void 0 : _data._base64) != null ? _data$_base : part;
}
// }
return blob;
};
}
}
// Don't pre-process urls, let expo-asset generate an absolute URL
const extractUrlBase = THREE__namespace.LoaderUtils.extractUrlBase.bind(THREE__namespace.LoaderUtils);
THREE__namespace.LoaderUtils.extractUrlBase = url => typeof url === 'string' ? extractUrlBase(url) : './';
// There's no Image in native, so create a data texture instead
THREE__namespace.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
if (this.path && typeof url === 'string') url = this.path + url;
const texture = new THREE__namespace.Texture();
getAsset(url).then(async uri => {
// https://github.com/expo/expo-three/pull/266
const {
width,
height
} = await new Promise((res, rej) => reactNative.Image.getSize(uri, (width, height) => res({
width,
height
}), rej));
texture.image = {
// Special case for EXGLImageUtils::loadImage
data: {
localUri: uri
},
width,
height
};
texture.flipY = true; // Since expo-gl@12.4.0
texture.needsUpdate = true;
// Force non-DOM upload for EXGL texImage2D
// @ts-expect-error
texture.isDataTexture = true;
onLoad == null ? void 0 : onLoad(texture);
}).catch(onError);
return texture;
};
// Fetches assets via FS
THREE__namespace.FileLoader.prototype.load = function load(url, onLoad, onProgress, onError) {
if (this.path && typeof url === 'string') url = this.path + url;
this.manager.itemStart(url);
getAsset(url).then(async uri => {
const base64 = await fs__namespace.readAsStringAsync(uri, {
encoding: fs__namespace.EncodingType.Base64
});
const data = buffer.Buffer.from(base64, 'base64');
onLoad == null ? void 0 : onLoad(data.buffer);
}).catch(error => {
onError == null ? void 0 : onError(error);
this.manager.itemError(url);
}).finally(() => {
this.manager.itemEnd(url);
});
};
}
if (reactNative.Platform.OS !== 'web') polyfills();
exports.ReactThreeFiber = events.threeTypes;
exports._roots = events.roots;
exports.act = events.act;
exports.addAfterEffect = events.addAfterEffect;
exports.addEffect = events.addEffect;
exports.addTail = events.addTail;
exports.advance = events.advance;
exports.applyProps = events.applyProps;
exports.buildGraph = events.buildGraph;
exports.context = events.context;
exports.createEvents = events.createEvents;
exports.createPointerEvents = events.createPointerEvents;
exports.createPortal = events.createPortal;
exports.createRoot = events.createRoot;
exports.dispose = events.dispose;
exports.extend = events.extend;
exports.flushGlobalEffects = events.flushGlobalEffects;
exports.flushSync = events.flushSync;
exports.getRootState = events.getRootState;
exports.invalidate = events.invalidate;
exports.reconciler = events.reconciler;
exports.render = events.render;
exports.unmountComponentAtNode = events.unmountComponentAtNode;
exports.useFrame = events.useFrame;
exports.useGraph = events.useGraph;
exports.useInstanceHandle = events.useInstanceHandle;
exports.useLoader = events.useLoader;
exports.useStore = events.useStore;
exports.useThree = events.useThree;
exports.Canvas = Canvas;
exports.events = createTouchEvents;