react-three-game 0.0.108 → 0.0.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -16
- package/dist/editor.d.ts +22 -0
- package/dist/editor.js +15 -0
- package/dist/plugins/crashcat/CrashcatPhysicsComponent.js +47 -9
- package/dist/plugins/crashcat/CrashcatRagdoll.d.ts +1 -1
- package/dist/plugins/crashcat/CrashcatRuntime.d.ts +1 -1
- package/dist/plugins/crashcat/CrashcatRuntime.js +1 -1
- package/dist/shared/ContactShadow.d.ts +1 -1
- package/dist/shared/GameCanvas.d.ts +1 -1
- package/dist/tools/assetviewer/page.d.ts +10 -10
- package/dist/tools/dragdrop/DragDropLoader.d.ts +2 -2
- package/dist/tools/prefabeditor/Dropdown.d.ts +1 -1
- package/dist/tools/prefabeditor/EditorContext.d.ts +36 -0
- package/dist/tools/prefabeditor/EditorContext.js +17 -0
- package/dist/tools/prefabeditor/EditorTree.d.ts +1 -1
- package/dist/tools/prefabeditor/EditorTree.js +1 -1
- package/dist/tools/prefabeditor/EditorTreeMenus.d.ts +2 -2
- package/dist/tools/prefabeditor/EditorTreeMenus.js +1 -1
- package/dist/tools/prefabeditor/EditorUI.d.ts +1 -1
- package/dist/tools/prefabeditor/EditorUI.js +1 -1
- package/dist/tools/prefabeditor/InstanceProvider.d.ts +1 -1
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +4 -37
- package/dist/tools/prefabeditor/PrefabEditor.js +72 -71
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +5 -29
- package/dist/tools/prefabeditor/PrefabRoot.js +72 -188
- package/dist/tools/prefabeditor/SceneContext.d.ts +28 -0
- package/dist/tools/prefabeditor/SceneContext.js +14 -0
- package/dist/tools/prefabeditor/SceneProvider.d.ts +14 -0
- package/dist/tools/prefabeditor/SceneProvider.js +68 -0
- package/dist/tools/prefabeditor/assetRuntime.d.ts +29 -2
- package/dist/tools/prefabeditor/assetRuntime.js +115 -1
- package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +1 -1
- package/dist/tools/prefabeditor/components/EnvironmentComponent.js +3 -3
- package/dist/tools/prefabeditor/components/Input.d.ts +19 -19
- package/dist/tools/prefabeditor/components/MaterialComponent.d.ts +1 -1
- package/dist/tools/prefabeditor/components/MaterialComponent.js +13 -14
- package/dist/tools/prefabeditor/components/ModelComponent.js +3 -4
- package/dist/tools/prefabeditor/components/PrefabRefComponent.js +43 -19
- package/dist/tools/prefabeditor/components/SoundComponent.js +6 -2
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +2 -5
- package/dist/tools/prefabeditor/components/TransformComponent.js +1 -1
- package/dist/tools/prefabeditor/components/index.d.ts +1 -0
- package/dist/tools/prefabeditor/components/index.js +8 -0
- package/dist/tools/prefabeditor/components/lightUtils.d.ts +2 -2
- package/dist/tools/prefabeditor/prefabStore.d.ts +2 -1
- package/dist/tools/prefabeditor/prefabStore.js +16 -1
- package/dist/tools/prefabeditor/runtimeUtils.d.ts +10 -0
- package/dist/tools/prefabeditor/runtimeUtils.js +30 -0
- package/dist/tools/prefabeditor/utils.d.ts +1 -9
- package/dist/tools/prefabeditor/utils.js +3 -28
- package/dist/viewer.d.ts +21 -0
- package/dist/viewer.js +12 -0
- package/package.json +18 -16
- package/dist/index.d.ts +0 -40
- package/dist/index.js +0 -32
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Environment } from '@react-three/drei';
|
|
3
3
|
import { FieldGroup, NumberField } from './Input';
|
|
4
|
-
import {
|
|
4
|
+
import { useAssetRevision } from '../assetRuntime';
|
|
5
5
|
function EnvironmentView({ properties, children, }) {
|
|
6
|
-
const
|
|
6
|
+
const assetRevision = useAssetRevision();
|
|
7
7
|
const { intensity = 1, resolution = 256 } = properties;
|
|
8
|
-
const environmentRevision = `${
|
|
8
|
+
const environmentRevision = `${assetRevision}::${intensity}::${resolution}`;
|
|
9
9
|
return (_jsx(Environment, { background: true, environmentIntensity: intensity, resolution: resolution, frames: 1, children: children }, environmentRevision));
|
|
10
10
|
}
|
|
11
11
|
const EnvironmentComponent = {
|
|
@@ -59,44 +59,44 @@ interface InputProps {
|
|
|
59
59
|
style?: React.CSSProperties;
|
|
60
60
|
label?: string;
|
|
61
61
|
}
|
|
62
|
-
export declare function NumberInput({ value, onChange, step, min, max, style }: InputProps):
|
|
62
|
+
export declare function NumberInput({ value, onChange, step, min, max, style }: InputProps): React.JSX.Element;
|
|
63
63
|
export declare function Label({ children }: {
|
|
64
64
|
children: React.ReactNode;
|
|
65
|
-
}):
|
|
65
|
+
}): React.JSX.Element;
|
|
66
66
|
export declare function FieldRow({ label, children, }: {
|
|
67
67
|
label: string;
|
|
68
68
|
children: React.ReactNode;
|
|
69
|
-
}):
|
|
69
|
+
}): React.JSX.Element;
|
|
70
70
|
export declare function Vector3Input({ label, value, onChange, snap, labelExtra }: {
|
|
71
71
|
label: string;
|
|
72
72
|
value: [number, number, number];
|
|
73
73
|
onChange: (v: [number, number, number]) => void;
|
|
74
74
|
snap?: number;
|
|
75
75
|
labelExtra?: React.ReactNode;
|
|
76
|
-
}):
|
|
76
|
+
}): React.JSX.Element;
|
|
77
77
|
export declare function ColorInput({ label, value, onChange }: {
|
|
78
78
|
label?: string;
|
|
79
79
|
value: string;
|
|
80
80
|
onChange: (value: string) => void;
|
|
81
|
-
}):
|
|
81
|
+
}): React.JSX.Element;
|
|
82
82
|
export declare function StringInput({ label, value, onChange, placeholder }: {
|
|
83
83
|
label?: string;
|
|
84
84
|
value: string;
|
|
85
85
|
onChange: (value: string) => void;
|
|
86
86
|
placeholder?: string;
|
|
87
|
-
}):
|
|
87
|
+
}): React.JSX.Element;
|
|
88
88
|
export declare function NodeInput({ label, value, onChange, placeholder, includeRoot, }: {
|
|
89
89
|
label: string;
|
|
90
90
|
value: string;
|
|
91
91
|
onChange: (value: string) => void;
|
|
92
92
|
placeholder?: string;
|
|
93
93
|
includeRoot?: boolean;
|
|
94
|
-
}):
|
|
94
|
+
}): React.JSX.Element;
|
|
95
95
|
export declare function BooleanInput({ label, value, onChange }: {
|
|
96
96
|
label?: string;
|
|
97
97
|
value: boolean;
|
|
98
98
|
onChange: (value: boolean) => void;
|
|
99
|
-
}):
|
|
99
|
+
}): React.JSX.Element;
|
|
100
100
|
export declare function SelectInput({ label, value, onChange, options }: {
|
|
101
101
|
label?: string;
|
|
102
102
|
value: string;
|
|
@@ -105,7 +105,7 @@ export declare function SelectInput({ label, value, onChange, options }: {
|
|
|
105
105
|
value: string;
|
|
106
106
|
label: string;
|
|
107
107
|
}[];
|
|
108
|
-
}):
|
|
108
|
+
}): React.JSX.Element;
|
|
109
109
|
interface BoundFieldProps {
|
|
110
110
|
name: string;
|
|
111
111
|
values: Record<string, any>;
|
|
@@ -148,7 +148,7 @@ interface BoundVector3FieldProps extends BoundFieldProps {
|
|
|
148
148
|
}
|
|
149
149
|
export declare function FieldGroup({ children }: {
|
|
150
150
|
children: React.ReactNode;
|
|
151
|
-
}):
|
|
151
|
+
}): React.JSX.Element;
|
|
152
152
|
interface ListEditorOption {
|
|
153
153
|
value: string;
|
|
154
154
|
label: string;
|
|
@@ -164,20 +164,20 @@ interface ListEditorProps<T> {
|
|
|
164
164
|
addButtonTitle?: string;
|
|
165
165
|
addDisabledTitle?: string;
|
|
166
166
|
}
|
|
167
|
-
export declare function ListEditor<T>({ label, items, renderItem, onAdd, addOptions, emptyMessage, canAdd, addButtonTitle, addDisabledTitle, }: ListEditorProps<T>):
|
|
168
|
-
export declare function NumberField({ name, label, values, onChange, fallback, step, min, max, style, }: BoundNumberFieldProps):
|
|
169
|
-
export declare function StringField({ name, label, values, onChange, fallback, placeholder, }: BoundStringFieldProps):
|
|
170
|
-
export declare function ColorField({ name, label, values, onChange, fallback, }: BoundColorFieldProps):
|
|
171
|
-
export declare function BooleanField({ name, label, values, onChange, fallback, }: BoundBooleanFieldProps):
|
|
172
|
-
export declare function SelectField({ name, label, values, onChange, fallback, options, }: BoundSelectFieldProps):
|
|
167
|
+
export declare function ListEditor<T>({ label, items, renderItem, onAdd, addOptions, emptyMessage, canAdd, addButtonTitle, addDisabledTitle, }: ListEditorProps<T>): React.JSX.Element;
|
|
168
|
+
export declare function NumberField({ name, label, values, onChange, fallback, step, min, max, style, }: BoundNumberFieldProps): React.JSX.Element;
|
|
169
|
+
export declare function StringField({ name, label, values, onChange, fallback, placeholder, }: BoundStringFieldProps): React.JSX.Element;
|
|
170
|
+
export declare function ColorField({ name, label, values, onChange, fallback, }: BoundColorFieldProps): React.JSX.Element;
|
|
171
|
+
export declare function BooleanField({ name, label, values, onChange, fallback, }: BoundBooleanFieldProps): React.JSX.Element;
|
|
172
|
+
export declare function SelectField({ name, label, values, onChange, fallback, options, }: BoundSelectFieldProps): React.JSX.Element;
|
|
173
173
|
export declare function NodeField({ name, label, values, onChange, fallback, }: BoundStringFieldProps & {
|
|
174
174
|
fallback?: string;
|
|
175
|
-
}):
|
|
176
|
-
export declare function Vector3Field({ name, label, values, onChange, fallback, snap, labelExtra, }: BoundVector3FieldProps):
|
|
175
|
+
}): React.JSX.Element;
|
|
176
|
+
export declare function Vector3Field({ name, label, values, onChange, fallback, snap, labelExtra, }: BoundVector3FieldProps): React.JSX.Element;
|
|
177
177
|
interface FieldRendererProps {
|
|
178
178
|
fields: FieldDefinition[];
|
|
179
179
|
values: Record<string, any>;
|
|
180
180
|
onChange: (values: Record<string, any>) => void;
|
|
181
181
|
}
|
|
182
|
-
export declare function FieldRenderer({ fields, values, onChange }: FieldRendererProps):
|
|
182
|
+
export declare function FieldRenderer({ fields, values, onChange }: FieldRendererProps): React.JSX.Element;
|
|
183
183
|
export { styles };
|
|
@@ -41,6 +41,6 @@ export declare function useMaterialOverrides(): MaterialOverrides;
|
|
|
41
41
|
export declare function MaterialOverridesProvider({ overrides, children, }: {
|
|
42
42
|
overrides: MaterialOverrides;
|
|
43
43
|
children: ReactNode;
|
|
44
|
-
}): import("react
|
|
44
|
+
}): import("react").JSX.Element;
|
|
45
45
|
declare const MaterialComponent: Component;
|
|
46
46
|
export default MaterialComponent;
|
|
@@ -15,7 +15,7 @@ import { extend } from '@react-three/fiber';
|
|
|
15
15
|
import { useFrame } from '@react-three/fiber';
|
|
16
16
|
import { assetRef, assetRefs } from './ComponentRegistry';
|
|
17
17
|
import { FieldRenderer, Label, NumberInput } from './Input';
|
|
18
|
-
import {
|
|
18
|
+
import { useTextureAsset } from '../assetRuntime';
|
|
19
19
|
import { MeshBasicNodeMaterial, MeshStandardNodeMaterial, SpriteNodeMaterial } from 'three/webgpu';
|
|
20
20
|
import { TexturePicker } from '../../assetviewer/page';
|
|
21
21
|
import { RepeatWrapping, ClampToEdgeWrapping, NoColorSpace, SRGBColorSpace, NearestFilter, LinearFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapNearestFilter, LinearMipmapLinearFilter, FrontSide, BackSide, DoubleSide, } from 'three';
|
|
@@ -219,8 +219,7 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "", }) {
|
|
|
219
219
|
}
|
|
220
220
|
// View for Material component
|
|
221
221
|
function MaterialComponentView({ properties: rawProps }) {
|
|
222
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
223
|
-
const { getTexture } = useAssetRuntime();
|
|
222
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
224
223
|
const properties = rawProps;
|
|
225
224
|
const materialSource = properties !== null && properties !== void 0 ? properties : {};
|
|
226
225
|
const materialType = (_a = materialSource.materialType) !== null && _a !== void 0 ? _a : 'standard';
|
|
@@ -234,15 +233,15 @@ function MaterialComponentView({ properties: rawProps }) {
|
|
|
234
233
|
const generateMipmaps = materialSource.generateMipmaps !== false;
|
|
235
234
|
const minFilter = (_b = materialSource.minFilter) !== null && _b !== void 0 ? _b : 'LinearMipmapLinearFilter';
|
|
236
235
|
const magFilter = (_c = materialSource.magFilter) !== null && _c !== void 0 ? _c : 'LinearFilter';
|
|
237
|
-
const texture =
|
|
236
|
+
const texture = (_d = useTextureAsset(textureName)) !== null && _d !== void 0 ? _d : undefined;
|
|
238
237
|
const normalScaleProp = materialSource.normalScale;
|
|
239
|
-
const normalMapTexture =
|
|
238
|
+
const normalMapTexture = (_e = useTextureAsset(normalMapTextureName)) !== null && _e !== void 0 ? _e : undefined;
|
|
240
239
|
// Destructure all material props and separate custom texture handling props
|
|
241
240
|
const { texture: _texture, offset: _offset, repeat: _repeat, repeatCount: _repeatCount, animateOffset: _animateOffset, offsetSpeed: _offsetSpeed, generateMipmaps: _generateMipmaps, minFilter: _minFilter, magFilter: _magFilter, map: _map, materialType: _materialType, attach, normalMapTexture: _normalMapTexture, normalScale: _normalScale, normalMap: _normalMap, rotation, sizeAttenuation, side: sideProp } = materialSource, materialProps = __rest(materialSource, ["texture", "offset", "repeat", "repeatCount", "animateOffset", "offsetSpeed", "generateMipmaps", "minFilter", "magFilter", "map", "materialType", "attach", "normalMapTexture", "normalScale", "normalMap", "rotation", "sizeAttenuation", "side"]);
|
|
242
|
-
const resolvedSide = sideProp ? (
|
|
243
|
-
const resolvedMinFilter = (
|
|
244
|
-
const resolvedMagFilter = (
|
|
245
|
-
const animatedOffsetRef = useRef([(
|
|
241
|
+
const resolvedSide = sideProp ? (_f = SIDE_MAP[sideProp]) !== null && _f !== void 0 ? _f : FrontSide : FrontSide;
|
|
242
|
+
const resolvedMinFilter = (_g = MIN_FILTER_MAP[minFilter]) !== null && _g !== void 0 ? _g : LinearMipmapLinearFilter;
|
|
243
|
+
const resolvedMagFilter = (_h = MAG_FILTER_MAP[magFilter]) !== null && _h !== void 0 ? _h : LinearFilter;
|
|
244
|
+
const animatedOffsetRef = useRef([(_j = offset === null || offset === void 0 ? void 0 : offset[0]) !== null && _j !== void 0 ? _j : 0, (_k = offset === null || offset === void 0 ? void 0 : offset[1]) !== null && _k !== void 0 ? _k : 0]);
|
|
246
245
|
const textureConfig = {
|
|
247
246
|
repeat,
|
|
248
247
|
repeatCount,
|
|
@@ -253,7 +252,7 @@ function MaterialComponentView({ properties: rawProps }) {
|
|
|
253
252
|
};
|
|
254
253
|
const finalTexture = useConfiguredTexture(texture, Object.assign(Object.assign({}, textureConfig), { colorSpace: SRGBColorSpace }));
|
|
255
254
|
const finalNormalMap = useConfiguredTexture(normalMapTexture, Object.assign(Object.assign({}, textureConfig), { colorSpace: NoColorSpace }));
|
|
256
|
-
animatedOffsetRef.current = [(
|
|
255
|
+
animatedOffsetRef.current = [(_l = offset === null || offset === void 0 ? void 0 : offset[0]) !== null && _l !== void 0 ? _l : 0, (_m = offset === null || offset === void 0 ? void 0 : offset[1]) !== null && _m !== void 0 ? _m : 0];
|
|
257
256
|
useFrame((_, delta) => {
|
|
258
257
|
var _a, _b;
|
|
259
258
|
if ((!finalTexture && !finalNormalMap) || !animateOffset)
|
|
@@ -276,8 +275,8 @@ function MaterialComponentView({ properties: rawProps }) {
|
|
|
276
275
|
textureName !== null && textureName !== void 0 ? textureName : 'no-texture',
|
|
277
276
|
normalMapTextureName !== null && normalMapTextureName !== void 0 ? normalMapTextureName : 'no-normal',
|
|
278
277
|
repeat ? 'repeat' : 'clamp',
|
|
279
|
-
(
|
|
280
|
-
(
|
|
278
|
+
(_o = repeatCount === null || repeatCount === void 0 ? void 0 : repeatCount[0]) !== null && _o !== void 0 ? _o : 1,
|
|
279
|
+
(_p = repeatCount === null || repeatCount === void 0 ? void 0 : repeatCount[1]) !== null && _p !== void 0 ? _p : 1,
|
|
281
280
|
generateMipmaps ? 'mips' : 'no-mips',
|
|
282
281
|
minFilter,
|
|
283
282
|
magFilter,
|
|
@@ -287,11 +286,11 @@ function MaterialComponentView({ properties: rawProps }) {
|
|
|
287
286
|
}
|
|
288
287
|
if (materialType === 'sprite') {
|
|
289
288
|
const spriteTransparent = materialSource.transparent !== false;
|
|
290
|
-
return (_jsx("spriteNodeMaterial", Object.assign({ attach: attach !== null && attach !== void 0 ? attach : 'material', map: finalTexture !== null && finalTexture !== void 0 ? finalTexture : null, color: (
|
|
289
|
+
return (_jsx("spriteNodeMaterial", Object.assign({ attach: attach !== null && attach !== void 0 ? attach : 'material', map: finalTexture !== null && finalTexture !== void 0 ? finalTexture : null, color: (_q = materialSource.color) !== null && _q !== void 0 ? _q : '#ffffff', opacity: (_r = materialSource.opacity) !== null && _r !== void 0 ? _r : 1, transparent: spriteTransparent, alphaTest: (_s = materialSource.alphaTest) !== null && _s !== void 0 ? _s : 0, depthTest: (_t = materialSource.depthTest) !== null && _t !== void 0 ? _t : false, depthWrite: (_u = materialSource.depthWrite) !== null && _u !== void 0 ? _u : false, toneMapped: (_v = materialSource.toneMapped) !== null && _v !== void 0 ? _v : true, onUpdate: material => {
|
|
291
290
|
material.needsUpdate = true;
|
|
292
291
|
} }, overrides, { rotation: rotation !== null && rotation !== void 0 ? rotation : 0, sizeAttenuation: sizeAttenuation !== null && sizeAttenuation !== void 0 ? sizeAttenuation : true }), materialKey));
|
|
293
292
|
}
|
|
294
|
-
return (_jsx("meshStandardNodeMaterial", Object.assign({ attach: attach !== null && attach !== void 0 ? attach : 'material' }, sharedProps, { normalMap: finalNormalMap !== null && finalNormalMap !== void 0 ? finalNormalMap : null, normalScale: finalNormalMap ? [(
|
|
293
|
+
return (_jsx("meshStandardNodeMaterial", Object.assign({ attach: attach !== null && attach !== void 0 ? attach : 'material' }, sharedProps, { normalMap: finalNormalMap !== null && finalNormalMap !== void 0 ? finalNormalMap : null, normalScale: finalNormalMap ? [(_w = normalScaleProp === null || normalScaleProp === void 0 ? void 0 : normalScaleProp[0]) !== null && _w !== void 0 ? _w : 1, (_x = normalScaleProp === null || normalScaleProp === void 0 ? void 0 : normalScaleProp[1]) !== null && _x !== void 0 ? _x : 1] : undefined }), materialKey));
|
|
295
294
|
}
|
|
296
295
|
const MaterialComponent = {
|
|
297
296
|
name: 'Material',
|
|
@@ -4,8 +4,8 @@ import { useMemo } from 'react';
|
|
|
4
4
|
import { Mesh } from 'three';
|
|
5
5
|
import { assetRef, assetRefs } from './ComponentRegistry';
|
|
6
6
|
import { BooleanField, FieldGroup, Label, ListEditor, NumberInput, SelectInput, StringField } from './Input';
|
|
7
|
-
import {
|
|
8
|
-
import { useEditorContext, useEditorRef } from '../
|
|
7
|
+
import { useModelAsset } from '../assetRuntime';
|
|
8
|
+
import { useEditorContext, useEditorRef } from '../EditorContext';
|
|
9
9
|
import { getRepeatAxesFromModelProperties, normalizeRepeatAxes } from '../InstanceProvider';
|
|
10
10
|
import { base, colors, ui } from '../styles';
|
|
11
11
|
import { decomposeModelToPrefabNodes } from '../modelPrefab';
|
|
@@ -89,8 +89,7 @@ function ModelComponentEditor({ component, node, onUpdate, basePath = "" }) {
|
|
|
89
89
|
}
|
|
90
90
|
// View for Model component
|
|
91
91
|
function ModelComponentView({ properties, children }) {
|
|
92
|
-
const
|
|
93
|
-
const sourceModel = properties.filename ? getModel(properties.filename) : null;
|
|
92
|
+
const sourceModel = useModelAsset(properties.filename);
|
|
94
93
|
// Clone model once and set up shadows - memoized to avoid cloning on every render
|
|
95
94
|
const clonedModel = useMemo(() => {
|
|
96
95
|
if (!sourceModel || !properties.filename || properties.instanced)
|
|
@@ -8,29 +8,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { useEffect, useState } from 'react';
|
|
12
|
-
import
|
|
13
|
-
import { useEditorRef } from '../PrefabEditor';
|
|
11
|
+
import { lazy, Suspense, useEffect, useState } from 'react';
|
|
12
|
+
import { useEditorRef } from '../EditorContext';
|
|
14
13
|
import { withBasePath } from '../utils';
|
|
15
14
|
import { base, colors } from '../styles';
|
|
16
15
|
import { FieldGroup, Label } from './Input';
|
|
16
|
+
const PrefabRoot = lazy(() => import('../PrefabRoot'));
|
|
17
|
+
function fetchJson(url) {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const response = yield fetch(url);
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error(`Request failed (${response.status}) for ${url}`);
|
|
22
|
+
}
|
|
23
|
+
return response.json();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
17
26
|
function PrefabRefView({ properties, children, basePath = '' }) {
|
|
18
|
-
var _a;
|
|
19
27
|
const [loadedPrefab, setLoadedPrefab] = useState(null);
|
|
20
|
-
const
|
|
21
|
-
const resolvedUrl = url ? withBasePath(basePath, url) : '';
|
|
28
|
+
const resolvedUrl = properties.url ? withBasePath(basePath, properties.url) : '';
|
|
22
29
|
useEffect(() => {
|
|
23
|
-
if (!resolvedUrl)
|
|
30
|
+
if (!resolvedUrl) {
|
|
31
|
+
setLoadedPrefab(null);
|
|
24
32
|
return;
|
|
33
|
+
}
|
|
25
34
|
let cancelled = false;
|
|
26
|
-
|
|
27
|
-
.then(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
void fetchJson(resolvedUrl)
|
|
36
|
+
.then((data) => {
|
|
37
|
+
if (!cancelled)
|
|
38
|
+
setLoadedPrefab(data);
|
|
39
|
+
})
|
|
40
|
+
.catch((err) => {
|
|
41
|
+
if (!cancelled)
|
|
42
|
+
setLoadedPrefab(null);
|
|
43
|
+
console.warn('[PrefabRef] Failed to load:', resolvedUrl, err);
|
|
44
|
+
});
|
|
31
45
|
return () => { cancelled = true; };
|
|
32
46
|
}, [resolvedUrl]);
|
|
33
|
-
return (_jsxs(_Fragment, { children: [loadedPrefab && _jsx(PrefabRoot, { data: loadedPrefab, editMode: false, basePath: basePath }), children] }));
|
|
47
|
+
return (_jsxs(_Fragment, { children: [loadedPrefab && (_jsx(Suspense, { fallback: null, children: _jsx(PrefabRoot, { data: loadedPrefab, editMode: false, basePath: basePath }) })), children] }));
|
|
34
48
|
}
|
|
35
49
|
function PrefabRefEditor({ node, component, onUpdate, basePath = '', }) {
|
|
36
50
|
var _a, _b;
|
|
@@ -39,17 +53,27 @@ function PrefabRefEditor({ node, component, onUpdate, basePath = '', }) {
|
|
|
39
53
|
const [unpacking, setUnpacking] = useState(false);
|
|
40
54
|
const editor = useEditorRef();
|
|
41
55
|
useEffect(() => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.then(data =>
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
let cancelled = false;
|
|
57
|
+
void fetchJson(withBasePath(basePath, '/prefabs/manifest.json'))
|
|
58
|
+
.then((data) => {
|
|
59
|
+
if (cancelled)
|
|
60
|
+
return;
|
|
61
|
+
setManifest(Array.isArray(data) ? data.filter((entry) => typeof entry === 'string') : []);
|
|
62
|
+
})
|
|
63
|
+
.catch(() => {
|
|
64
|
+
if (!cancelled)
|
|
65
|
+
setManifest([]);
|
|
66
|
+
});
|
|
67
|
+
return () => {
|
|
68
|
+
cancelled = true;
|
|
69
|
+
};
|
|
70
|
+
}, [basePath]);
|
|
47
71
|
const handleUnpack = () => __awaiter(this, void 0, void 0, function* () {
|
|
48
72
|
if (!node || !url)
|
|
49
73
|
return;
|
|
50
74
|
setUnpacking(true);
|
|
51
75
|
try {
|
|
52
|
-
const prefab = yield
|
|
76
|
+
const prefab = yield fetchJson(withBasePath(basePath, url));
|
|
53
77
|
editor.replaceNode(node.id, prefab.root);
|
|
54
78
|
}
|
|
55
79
|
catch (err) {
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
3
|
import { useThree } from '@react-three/fiber';
|
|
4
4
|
import { SoundPicker } from '../../assetviewer/page';
|
|
5
|
-
import { useAssetRuntime, useNode } from '../assetRuntime';
|
|
5
|
+
import { useAssetRevision, useAssetRuntime, useNode } from '../assetRuntime';
|
|
6
6
|
import { gameEvents } from '../GameEvents';
|
|
7
7
|
import { BooleanField, FieldGroup, FieldRenderer, ListEditor, NumberField, SelectField, StringField } from './Input';
|
|
8
8
|
import { colors, ui } from '../styles';
|
|
@@ -124,6 +124,7 @@ function SoundComponentEditor({ component, onUpdate, basePath = '' }) {
|
|
|
124
124
|
}
|
|
125
125
|
function SoundComponentView({ properties, children }) {
|
|
126
126
|
const { getSound } = useAssetRuntime();
|
|
127
|
+
const assetRevision = useAssetRevision();
|
|
127
128
|
const { editMode, nodeId } = useNode();
|
|
128
129
|
const { camera } = useThree();
|
|
129
130
|
const { eventName, autoplay = false, positional = false, refDistance = 1, maxDistance = 24, rolloffFactor = 1, distanceModel = 'inverse' } = properties;
|
|
@@ -180,6 +181,9 @@ function SoundComponentView({ properties, children }) {
|
|
|
180
181
|
});
|
|
181
182
|
}, [editMode, eventName, getSound, mode, nodeId, paths, properties]);
|
|
182
183
|
useEffect(() => {
|
|
184
|
+
// Re-run when assets load so autoplay can start once the buffer is ready
|
|
185
|
+
// (the asset runtime context is now stable and no longer re-renders on load).
|
|
186
|
+
void assetRevision;
|
|
183
187
|
if (editMode || !autoplay || paths.length === 0) {
|
|
184
188
|
return;
|
|
185
189
|
}
|
|
@@ -198,7 +202,7 @@ function SoundComponentView({ properties, children }) {
|
|
|
198
202
|
audio.stop();
|
|
199
203
|
}
|
|
200
204
|
};
|
|
201
|
-
}, [autoplay, editMode, getSound, mode, paths, properties]);
|
|
205
|
+
}, [autoplay, editMode, getSound, mode, paths, properties, assetRevision]);
|
|
202
206
|
return (_jsxs(_Fragment, { children: [listenerRef.current ? _jsx("positionalAudio", { ref: positionalAudioRef, args: [listenerRef.current] }) : null, children] }));
|
|
203
207
|
}
|
|
204
208
|
const SoundComponent = {
|
|
@@ -4,7 +4,7 @@ import { useHelper } from "@react-three/drei";
|
|
|
4
4
|
import { useRef } from "react";
|
|
5
5
|
import { BooleanField, ColorField, Label, NumberField, Vector3Input } from "./Input";
|
|
6
6
|
import { SpotLightHelper } from "three";
|
|
7
|
-
import {
|
|
7
|
+
import { useTextureAsset, useNode } from "../assetRuntime";
|
|
8
8
|
import { TexturePicker } from "../../assetviewer/page";
|
|
9
9
|
import { LightSection, ShadowBiasField, mergeWithDefaults } from "./lightUtils";
|
|
10
10
|
const spotLightDefaults = {
|
|
@@ -30,12 +30,9 @@ function SpotLightComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
30
30
|
}
|
|
31
31
|
function SpotLightView({ properties, children }) {
|
|
32
32
|
var _a, _b;
|
|
33
|
-
const { getTexture } = useAssetRuntime();
|
|
34
33
|
const { editMode, isSelected } = useNode();
|
|
35
34
|
const merged = mergeWithDefaults(spotLightDefaults, properties);
|
|
36
|
-
const textureMap = merged.map
|
|
37
|
-
? (_a = getTexture(merged.map)) !== null && _a !== void 0 ? _a : undefined
|
|
38
|
-
: undefined;
|
|
35
|
+
const textureMap = (_a = useTextureAsset(merged.map)) !== null && _a !== void 0 ? _a : undefined;
|
|
39
36
|
const lightProps = {
|
|
40
37
|
color: merged.color,
|
|
41
38
|
intensity: merged.intensity,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Label, Vector3Input } from "./Input";
|
|
3
|
-
import { useEditorContext } from "../
|
|
3
|
+
import { useEditorContext } from "../EditorContext";
|
|
4
4
|
import { colors } from "../styles";
|
|
5
5
|
const buttonStyle = {
|
|
6
6
|
padding: '2px 6px',
|
|
@@ -15,6 +15,7 @@ import EnvironmentComponent from "./EnvironmentComponent";
|
|
|
15
15
|
import CameraComponent from "./CameraComponent";
|
|
16
16
|
import SoundComponent from "./SoundComponent";
|
|
17
17
|
import DataComponent from "./DataComponent";
|
|
18
|
+
import { registerComponent } from "./ComponentRegistry";
|
|
18
19
|
// this controls the order of components in the editor, and also which components are available to add
|
|
19
20
|
export const builtinComponents = [
|
|
20
21
|
TransformComponent,
|
|
@@ -38,3 +39,10 @@ export const builtinComponents = [
|
|
|
38
39
|
DataComponent,
|
|
39
40
|
PrefabRefComponent,
|
|
40
41
|
];
|
|
42
|
+
let didRegisterBuiltinComponents = false;
|
|
43
|
+
export function registerBuiltinComponents() {
|
|
44
|
+
if (didRegisterBuiltinComponents)
|
|
45
|
+
return;
|
|
46
|
+
builtinComponents.forEach(registerComponent);
|
|
47
|
+
didRegisterBuiltinComponents = true;
|
|
48
|
+
}
|
|
@@ -3,11 +3,11 @@ export declare function mergeWithDefaults<T extends Record<string, any>>(default
|
|
|
3
3
|
export declare function LightSection({ title, children }: {
|
|
4
4
|
title: string;
|
|
5
5
|
children: ReactNode;
|
|
6
|
-
}): import("react
|
|
6
|
+
}): import("react").JSX.Element;
|
|
7
7
|
export declare function ShadowBiasField({ name, label, values, onChange, fallback, }: {
|
|
8
8
|
name: string;
|
|
9
9
|
label: string;
|
|
10
10
|
values: Record<string, any>;
|
|
11
11
|
onChange: (values: Record<string, any>) => void;
|
|
12
12
|
fallback?: number;
|
|
13
|
-
}): import("react
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -4,6 +4,7 @@ import { GameObject, Prefab } from "./types";
|
|
|
4
4
|
import { denormalizePrefab, PrefabState, PrefabNodeRecord } from "./prefab";
|
|
5
5
|
export interface PrefabStoreState extends PrefabState {
|
|
6
6
|
replacePrefab: (prefab: Prefab) => void;
|
|
7
|
+
restoreState: (snapshot: PrefabState) => void;
|
|
7
8
|
updateNode: (id: string, update: (node: PrefabNodeRecord) => PrefabNodeRecord) => void;
|
|
8
9
|
replaceNode: (id: string, node: GameObject) => void;
|
|
9
10
|
addChild: (parentId: string, node: GameObject) => void;
|
|
@@ -15,7 +16,7 @@ export type PrefabStoreApi = StoreApi<PrefabStoreState>;
|
|
|
15
16
|
export declare function PrefabStoreProvider({ store, children, }: {
|
|
16
17
|
store: PrefabStoreApi;
|
|
17
18
|
children: ReactNode;
|
|
18
|
-
}): import("react").FunctionComponentElement<import("react").ProviderProps<PrefabStoreApi | null>>;
|
|
19
|
+
}): import("react").FunctionComponentElement<import("react").FragmentProps> | import("react").FunctionComponentElement<import("react").ProviderProps<PrefabStoreApi | null>>;
|
|
19
20
|
export declare function usePrefabStoreApi(): PrefabStoreApi;
|
|
20
21
|
export declare function usePrefabStore<T>(selector: (state: PrefabStoreState) => T): T;
|
|
21
22
|
export declare function usePrefabRootId(): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, createElement, useContext } from "react";
|
|
1
|
+
import { Fragment, createContext, createElement, useContext } from "react";
|
|
2
2
|
import { subscribeWithSelector } from "zustand/middleware";
|
|
3
3
|
import { useStore } from "zustand";
|
|
4
4
|
import { createStore } from "zustand/vanilla";
|
|
@@ -45,6 +45,10 @@ function insertSubtreeIntoGraph(node, parentId, next) {
|
|
|
45
45
|
addAssetRefs(next.assetRefCounts, collectSubtreeAssetRefs(node));
|
|
46
46
|
}
|
|
47
47
|
export function PrefabStoreProvider({ store, children, }) {
|
|
48
|
+
const parentStore = useContext(PrefabStoreContext);
|
|
49
|
+
if (parentStore === store) {
|
|
50
|
+
return createElement(Fragment, null, children);
|
|
51
|
+
}
|
|
48
52
|
return createElement(PrefabStoreContext.Provider, { value: store }, children);
|
|
49
53
|
}
|
|
50
54
|
export function usePrefabStoreApi() {
|
|
@@ -69,6 +73,17 @@ export function usePrefabChildIds(nodeId) {
|
|
|
69
73
|
export function createPrefabStore(prefab) {
|
|
70
74
|
return createStore()(subscribeWithSelector((set, get) => (Object.assign(Object.assign({}, normalizePrefab(prefab)), { replacePrefab: (nextPrefab) => {
|
|
71
75
|
set(normalizePrefab(nextPrefab));
|
|
76
|
+
}, restoreState: (snapshot) => {
|
|
77
|
+
set({
|
|
78
|
+
prefabId: snapshot.prefabId,
|
|
79
|
+
prefabName: snapshot.prefabName,
|
|
80
|
+
rootId: snapshot.rootId,
|
|
81
|
+
nodesById: snapshot.nodesById,
|
|
82
|
+
childIdsById: snapshot.childIdsById,
|
|
83
|
+
parentIdById: snapshot.parentIdById,
|
|
84
|
+
assetManifestKey: snapshot.assetManifestKey,
|
|
85
|
+
assetRefCounts: snapshot.assetRefCounts,
|
|
86
|
+
});
|
|
72
87
|
}, updateNode: (id, update) => {
|
|
73
88
|
const state = get();
|
|
74
89
|
const node = state.nodesById[id];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Matrix4 } from "three";
|
|
2
|
+
export declare function isExternalPath(path: string): boolean;
|
|
3
|
+
export declare function withBasePath(basePath: string | undefined, path: string): string;
|
|
4
|
+
export declare function decompose(m: Matrix4): {
|
|
5
|
+
position: [number, number, number];
|
|
6
|
+
rotation: [number, number, number];
|
|
7
|
+
scale: [number, number, number];
|
|
8
|
+
};
|
|
9
|
+
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
10
|
+
export declare function composeTransform(position?: [number, number, number], rotation?: [number, number, number], scale?: [number, number, number]): Matrix4;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
2
|
+
export function isExternalPath(path) {
|
|
3
|
+
return (path.startsWith("data:") ||
|
|
4
|
+
path.startsWith("http://") ||
|
|
5
|
+
path.startsWith("https://"));
|
|
6
|
+
}
|
|
7
|
+
export function withBasePath(basePath, path) {
|
|
8
|
+
if (!path)
|
|
9
|
+
return (basePath !== null && basePath !== void 0 ? basePath : "").replace(/\/$/, "");
|
|
10
|
+
if (isExternalPath(path))
|
|
11
|
+
return path;
|
|
12
|
+
const normalizedBasePath = (basePath !== null && basePath !== void 0 ? basePath : "").replace(/\/$/, "");
|
|
13
|
+
return path.startsWith("/") ? `${normalizedBasePath}${path}` : `${normalizedBasePath}/${path}`;
|
|
14
|
+
}
|
|
15
|
+
export function decompose(m) {
|
|
16
|
+
const p = new Vector3();
|
|
17
|
+
const q = new Quaternion();
|
|
18
|
+
const s = new Vector3();
|
|
19
|
+
m.decompose(p, q, s);
|
|
20
|
+
const e = new Euler().setFromQuaternion(q);
|
|
21
|
+
return {
|
|
22
|
+
position: [p.x, p.y, p.z],
|
|
23
|
+
rotation: [e.x, e.y, e.z],
|
|
24
|
+
scale: [s.x, s.y, s.z],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
28
|
+
export function composeTransform(position = [0, 0, 0], rotation = [0, 0, 0], scale = [1, 1, 1]) {
|
|
29
|
+
return new Matrix4().compose(new Vector3(...position), new Quaternion().setFromEuler(new Euler(...rotation)), new Vector3(...scale));
|
|
30
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { GameObject, Prefab } from "./types";
|
|
2
2
|
import { Matrix4, Object3D, Vector3 } from "three";
|
|
3
|
-
export
|
|
4
|
-
export declare function withBasePath(basePath: string | undefined, path: string): string;
|
|
3
|
+
export { composeTransform, decompose, isExternalPath, withBasePath } from "./runtimeUtils";
|
|
5
4
|
export interface ExportGLBOptions {
|
|
6
5
|
filename?: string;
|
|
7
6
|
}
|
|
@@ -23,13 +22,6 @@ export declare function exportGLBData(sceneRoot: Object3D): Promise<ArrayBuffer>
|
|
|
23
22
|
*/
|
|
24
23
|
export declare function exportGLB(sceneRoot: Object3D, options?: ExportGLBOptions): Promise<ArrayBuffer>;
|
|
25
24
|
export declare function focusCameraOnObject(object: Object3D, camera: Object3D, target: Vector3, update?: () => void): void;
|
|
26
|
-
export declare function decompose(m: Matrix4): {
|
|
27
|
-
position: [number, number, number];
|
|
28
|
-
rotation: [number, number, number];
|
|
29
|
-
scale: [number, number, number];
|
|
30
|
-
};
|
|
31
|
-
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
32
|
-
export declare function composeTransform(position?: [number, number, number], rotation?: [number, number, number], scale?: [number, number, number]): Matrix4;
|
|
33
25
|
/** Compute the parent world matrix for a node using the normalized store data */
|
|
34
26
|
export declare function computeParentWorldMatrix(state: {
|
|
35
27
|
nodesById: Record<string, {
|
|
@@ -8,21 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { findComponent } from "./types";
|
|
11
|
+
import { composeTransform } from "./runtimeUtils";
|
|
11
12
|
import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
12
|
-
import { Box3,
|
|
13
|
-
export
|
|
14
|
-
return (path.startsWith("data:") ||
|
|
15
|
-
path.startsWith("http://") ||
|
|
16
|
-
path.startsWith("https://"));
|
|
17
|
-
}
|
|
18
|
-
export function withBasePath(basePath, path) {
|
|
19
|
-
if (!path)
|
|
20
|
-
return (basePath !== null && basePath !== void 0 ? basePath : "").replace(/\/$/, "");
|
|
21
|
-
if (isExternalPath(path))
|
|
22
|
-
return path;
|
|
23
|
-
const normalizedBasePath = (basePath !== null && basePath !== void 0 ? basePath : "").replace(/\/$/, "");
|
|
24
|
-
return path.startsWith("/") ? `${normalizedBasePath}${path}` : `${normalizedBasePath}/${path}`;
|
|
25
|
-
}
|
|
13
|
+
import { Box3, Matrix4, PerspectiveCamera, Quaternion, Vector3, } from "three";
|
|
14
|
+
export { composeTransform, decompose, isExternalPath, withBasePath } from "./runtimeUtils";
|
|
26
15
|
/** Save scene JSON, showing a Save As dialog when supported */
|
|
27
16
|
export function saveJson(data, filename) {
|
|
28
17
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -172,20 +161,6 @@ export function focusCameraOnObject(object, camera, target, update) {
|
|
|
172
161
|
target.copy(center);
|
|
173
162
|
update === null || update === void 0 ? void 0 : update();
|
|
174
163
|
}
|
|
175
|
-
export function decompose(m) {
|
|
176
|
-
const p = new Vector3(), q = new Quaternion(), s = new Vector3();
|
|
177
|
-
m.decompose(p, q, s);
|
|
178
|
-
const e = new Euler().setFromQuaternion(q);
|
|
179
|
-
return {
|
|
180
|
-
position: [p.x, p.y, p.z],
|
|
181
|
-
rotation: [e.x, e.y, e.z],
|
|
182
|
-
scale: [s.x, s.y, s.z],
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
186
|
-
export function composeTransform(position = [0, 0, 0], rotation = [0, 0, 0], scale = [1, 1, 1]) {
|
|
187
|
-
return new Matrix4().compose(new Vector3(...position), new Quaternion().setFromEuler(new Euler(...rotation)), new Vector3(...scale));
|
|
188
|
-
}
|
|
189
164
|
/** Compute the parent world matrix for a node using the normalized store data */
|
|
190
165
|
export function computeParentWorldMatrix(state, targetId) {
|
|
191
166
|
var _a;
|
package/dist/viewer.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { default as GameCanvas } from "./shared/GameCanvas";
|
|
2
|
+
export type { GameCanvasProps } from "./shared/GameCanvas";
|
|
3
|
+
export { ground } from "./helpers";
|
|
4
|
+
export type { GroundOptions, Vec3 } from "./helpers";
|
|
5
|
+
export { sound as soundManager } from "./helpers/SoundManager";
|
|
6
|
+
export { default as PrefabRoot } from "./tools/prefabeditor/PrefabRoot";
|
|
7
|
+
export type { PrefabRootProps } from "./tools/prefabeditor/PrefabRoot";
|
|
8
|
+
export { PrefabEditorMode, SceneContext, useScene, } from "./tools/prefabeditor/SceneContext";
|
|
9
|
+
export type { PrefabNode, Scene } from "./tools/prefabeditor/SceneContext";
|
|
10
|
+
export { SceneProvider } from "./tools/prefabeditor/SceneProvider";
|
|
11
|
+
export type { AssetRuntime, NodeApi, LiveRef, } from "./tools/prefabeditor/assetRuntime";
|
|
12
|
+
export { useAssetRuntime, useNode, useNodeHandle, useNodeObject, AssetRuntimeProvider, } from "./tools/prefabeditor/assetRuntime";
|
|
13
|
+
export { gameEvents, useClickEvent, useGameEvent, } from "./tools/prefabeditor/GameEvents";
|
|
14
|
+
export type { ClickEventPayload, ContactEventPayload, GameEventHandler, GameEventMap, } from "./tools/prefabeditor/GameEvents";
|
|
15
|
+
export { registerComponent } from "./tools/prefabeditor/components/ComponentRegistry";
|
|
16
|
+
export type { Component, ComponentViewProps, } from "./tools/prefabeditor/components/ComponentRegistry";
|
|
17
|
+
export { denormalizePrefab, createModelNode, createImageNode, } from "./tools/prefabeditor/prefab";
|
|
18
|
+
export type { Prefab, GameObject, ComponentData, } from "./tools/prefabeditor/types";
|
|
19
|
+
export { findComponent, findComponentEntry, hasComponent, } from "./tools/prefabeditor/types";
|
|
20
|
+
export { loadModel, loadSound, loadTexture, } from "./tools/dragdrop/modelLoader";
|
|
21
|
+
export type { LoadedModel, LoadedModels, ModelLoadResult, LoadedSound, LoadedSounds, SoundLoadResult, LoadedTexture, LoadedTextures, TextureLoadResult, ProgressCallback, } from "./tools/dragdrop/modelLoader";
|