react-three-game 0.0.55 → 0.0.57
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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/shared/ContactShadow.d.ts +8 -0
- package/dist/shared/ContactShadow.js +32 -0
- package/dist/shared/GameCanvas.js +1 -3
- package/dist/tools/assetviewer/page.js +36 -15
- package/dist/tools/dragdrop/DragDropLoader.js +17 -40
- package/dist/tools/dragdrop/modelLoader.d.ts +5 -0
- package/dist/tools/dragdrop/modelLoader.js +39 -0
- package/dist/tools/prefabeditor/Dropdown.d.ts +15 -0
- package/dist/tools/prefabeditor/Dropdown.js +82 -0
- package/dist/tools/prefabeditor/EditorContext.d.ts +5 -0
- package/dist/tools/prefabeditor/EditorTree.js +139 -70
- package/dist/tools/prefabeditor/EditorUI.js +5 -10
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +1 -0
- package/dist/tools/prefabeditor/PrefabEditor.js +70 -3
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +3 -0
- package/dist/tools/prefabeditor/PrefabRoot.js +136 -35
- package/dist/tools/prefabeditor/components/AmbientLightComponent.js +3 -7
- package/dist/tools/prefabeditor/components/CameraComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/CameraComponent.js +25 -0
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/EnvironmentComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/EnvironmentComponent.js +15 -0
- package/dist/tools/prefabeditor/components/GeometryComponent.js +46 -46
- package/dist/tools/prefabeditor/components/Input.d.ts +51 -1
- package/dist/tools/prefabeditor/components/Input.js +100 -47
- package/dist/tools/prefabeditor/components/MaterialComponent.d.ts +8 -2
- package/dist/tools/prefabeditor/components/MaterialComponent.js +129 -14
- package/dist/tools/prefabeditor/components/ModelComponent.js +44 -3
- package/dist/tools/prefabeditor/components/PhysicsComponent.js +16 -81
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +6 -11
- package/dist/tools/prefabeditor/components/TextComponent.js +7 -53
- package/dist/tools/prefabeditor/components/TransformComponent.js +31 -19
- package/dist/tools/prefabeditor/components/index.js +5 -1
- package/dist/tools/prefabeditor/styles.d.ts +17 -4
- package/dist/tools/prefabeditor/styles.js +69 -32
- package/dist/tools/prefabeditor/utils.d.ts +8 -3
- package/dist/tools/prefabeditor/utils.js +92 -6
- package/package.json +1 -1
- package/react-three-game-skill/react-three-game/rules/LIGHTING.md +6 -0
- package/src/index.ts +7 -0
- package/src/shared/ContactShadow.tsx +74 -0
- package/src/shared/GameCanvas.tsx +0 -3
- package/src/tools/assetviewer/page.tsx +78 -46
- package/src/tools/dragdrop/DragDropLoader.tsx +7 -39
- package/src/tools/dragdrop/modelLoader.ts +36 -0
- package/src/tools/prefabeditor/Dropdown.tsx +112 -0
- package/src/tools/prefabeditor/EditorContext.tsx +5 -0
- package/src/tools/prefabeditor/EditorTree.tsx +237 -115
- package/src/tools/prefabeditor/EditorUI.tsx +6 -11
- package/src/tools/prefabeditor/PrefabEditor.tsx +77 -5
- package/src/tools/prefabeditor/PrefabRoot.tsx +228 -59
- package/src/tools/prefabeditor/components/AmbientLightComponent.tsx +5 -11
- package/src/tools/prefabeditor/components/CameraComponent.tsx +80 -0
- package/src/tools/prefabeditor/components/DirectionalLightComponent.tsx +2 -2
- package/src/tools/prefabeditor/components/EnvironmentComponent.tsx +47 -0
- package/src/tools/prefabeditor/components/GeometryComponent.tsx +69 -63
- package/src/tools/prefabeditor/components/Input.tsx +247 -53
- package/src/tools/prefabeditor/components/MaterialComponent.tsx +191 -20
- package/src/tools/prefabeditor/components/ModelComponent.tsx +52 -5
- package/src/tools/prefabeditor/components/PhysicsComponent.tsx +44 -85
- package/src/tools/prefabeditor/components/SpotLightComponent.tsx +14 -16
- package/src/tools/prefabeditor/components/TextComponent.tsx +58 -57
- package/src/tools/prefabeditor/components/TransformComponent.tsx +78 -20
- package/src/tools/prefabeditor/components/index.ts +5 -1
- package/src/tools/prefabeditor/styles.ts +71 -32
- package/src/tools/prefabeditor/utils.ts +96 -5
|
@@ -15,28 +15,55 @@ import { getComponent, registerComponent, getNonComposableKeys } from "./compone
|
|
|
15
15
|
import components from "./components";
|
|
16
16
|
import { loadModel } from "../dragdrop/modelLoader";
|
|
17
17
|
import { GameInstance, GameInstanceProvider, useInstanceCheck } from "./InstanceProvider";
|
|
18
|
-
import { updateNode } from "./utils";
|
|
18
|
+
import { focusCameraOnObject, updateNode } from "./utils";
|
|
19
19
|
import { EditorContext } from "./EditorContext";
|
|
20
20
|
components.forEach(registerComponent);
|
|
21
21
|
const IDENTITY = new Matrix4();
|
|
22
22
|
export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selectedId, onSelect, onClick, basePath = "" }, ref) => {
|
|
23
|
-
var _a, _b;
|
|
23
|
+
var _a, _b, _c, _d;
|
|
24
24
|
// optional editor context
|
|
25
25
|
const editorContext = useContext(EditorContext);
|
|
26
26
|
const transformMode = (_a = editorContext === null || editorContext === void 0 ? void 0 : editorContext.transformMode) !== null && _a !== void 0 ? _a : "translate";
|
|
27
27
|
const snapResolution = (_b = editorContext === null || editorContext === void 0 ? void 0 : editorContext.snapResolution) !== null && _b !== void 0 ? _b : 0;
|
|
28
|
+
const positionSnap = (_c = editorContext === null || editorContext === void 0 ? void 0 : editorContext.positionSnap) !== null && _c !== void 0 ? _c : 0.5;
|
|
29
|
+
const rotationSnap = (_d = editorContext === null || editorContext === void 0 ? void 0 : editorContext.rotationSnap) !== null && _d !== void 0 ? _d : Math.PI / 4;
|
|
28
30
|
// prefab root state
|
|
29
31
|
const [models, setModels] = useState({});
|
|
30
32
|
const [textures, setTextures] = useState({});
|
|
31
33
|
const loading = useRef(new Set());
|
|
34
|
+
const failedTextures = useRef(new Set());
|
|
32
35
|
const objectRefs = useRef({});
|
|
33
36
|
const rigidBodyRefs = useRef(new Map());
|
|
34
37
|
const [selectedObject, setSelectedObject] = useState(null);
|
|
35
38
|
const rootRef = useRef(null);
|
|
39
|
+
const controlsRef = useRef(null);
|
|
40
|
+
const injectModel = useCallback((filename, model) => {
|
|
41
|
+
setModels(m => (Object.assign(Object.assign({}, m), { [filename]: model })));
|
|
42
|
+
}, []);
|
|
43
|
+
const injectTexture = useCallback((filename, file) => {
|
|
44
|
+
loading.current.add(filename);
|
|
45
|
+
const url = URL.createObjectURL(file);
|
|
46
|
+
const loader = new TextureLoader();
|
|
47
|
+
loader.load(url, tex => {
|
|
48
|
+
tex.colorSpace = SRGBColorSpace;
|
|
49
|
+
setTextures(t => (Object.assign(Object.assign({}, t), { [filename]: tex })));
|
|
50
|
+
URL.revokeObjectURL(url);
|
|
51
|
+
}, undefined, () => URL.revokeObjectURL(url));
|
|
52
|
+
}, []);
|
|
36
53
|
useImperativeHandle(ref, () => ({
|
|
37
54
|
root: rootRef.current,
|
|
38
|
-
rigidBodyRefs: rigidBodyRefs.current
|
|
39
|
-
|
|
55
|
+
rigidBodyRefs: rigidBodyRefs.current,
|
|
56
|
+
injectModel,
|
|
57
|
+
injectTexture,
|
|
58
|
+
focusNode: (nodeId) => {
|
|
59
|
+
const object = objectRefs.current[nodeId];
|
|
60
|
+
const controls = controlsRef.current;
|
|
61
|
+
const camera = controls === null || controls === void 0 ? void 0 : controls.object;
|
|
62
|
+
if (!object || !controls || !camera)
|
|
63
|
+
return;
|
|
64
|
+
focusCameraOnObject(object, camera, controls.target, () => { var _a; return (_a = controls.update) === null || _a === void 0 ? void 0 : _a.call(controls); });
|
|
65
|
+
}
|
|
66
|
+
}), [injectModel, injectTexture]);
|
|
40
67
|
const registerRef = useCallback((id, obj) => {
|
|
41
68
|
objectRefs.current[id] = obj;
|
|
42
69
|
if (id === selectedId)
|
|
@@ -77,11 +104,13 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
77
104
|
const modelsToLoad = new Set();
|
|
78
105
|
const texturesToLoad = new Set();
|
|
79
106
|
walk(data.root, node => {
|
|
80
|
-
var _a, _b, _c, _d, _e, _f;
|
|
107
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
81
108
|
((_c = (_b = (_a = node.components) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.properties) === null || _c === void 0 ? void 0 : _c.filename) &&
|
|
82
109
|
modelsToLoad.add(node.components.model.properties.filename);
|
|
83
110
|
((_f = (_e = (_d = node.components) === null || _d === void 0 ? void 0 : _d.material) === null || _e === void 0 ? void 0 : _e.properties) === null || _f === void 0 ? void 0 : _f.texture) &&
|
|
84
111
|
texturesToLoad.add(node.components.material.properties.texture);
|
|
112
|
+
((_j = (_h = (_g = node.components) === null || _g === void 0 ? void 0 : _g.material) === null || _h === void 0 ? void 0 : _h.properties) === null || _j === void 0 ? void 0 : _j.normalMapTexture) &&
|
|
113
|
+
texturesToLoad.add(node.components.material.properties.normalMapTexture);
|
|
85
114
|
});
|
|
86
115
|
modelsToLoad.forEach((file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
87
116
|
if (models[file] || loading.current.has(file))
|
|
@@ -96,7 +125,7 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
96
125
|
}));
|
|
97
126
|
const loader = new TextureLoader();
|
|
98
127
|
texturesToLoad.forEach(file => {
|
|
99
|
-
if (textures[file] || loading.current.has(file))
|
|
128
|
+
if (textures[file] || loading.current.has(file) || failedTextures.current.has(file))
|
|
100
129
|
return;
|
|
101
130
|
loading.current.add(file);
|
|
102
131
|
// Handle full URLs (http/https) or regular paths
|
|
@@ -109,12 +138,13 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
109
138
|
tex.colorSpace = SRGBColorSpace;
|
|
110
139
|
setTextures(t => (Object.assign(Object.assign({}, t), { [file]: tex })));
|
|
111
140
|
}, undefined, (err) => {
|
|
112
|
-
console.
|
|
141
|
+
console.warn(`Failed to load texture: ${path}`, err);
|
|
113
142
|
loading.current.delete(file);
|
|
143
|
+
failedTextures.current.add(file);
|
|
114
144
|
});
|
|
115
145
|
});
|
|
116
146
|
}, [data, models, textures]);
|
|
117
|
-
return (_jsxs("group", { ref: rootRef, children: [_jsx(GameInstanceProvider, { models: models, selectedId: selectedId, editMode: editMode, onSelect: editMode ? onSelect : undefined, registerRef: registerRef, children: _jsx(GameObjectRenderer, { gameObject: data.root, selectedId: selectedId, onSelect: editMode ? onSelect : undefined, onClick: onClick, registerRef: registerRef, registerRigidBodyRef: registerRigidBodyRef, loadedModels: models, loadedTextures: textures, editMode: editMode, parentMatrix: IDENTITY }) }), editMode && (_jsxs(_Fragment, { children: [_jsx(MapControls, { makeDefault: true }), selectedObject && (_jsx(TransformControls, { object: selectedObject, mode: transformMode, space: "local", onObjectChange: onTransformChange, translationSnap:
|
|
147
|
+
return (_jsxs("group", { ref: rootRef, children: [_jsx(GameInstanceProvider, { models: models, selectedId: selectedId, editMode: editMode, onSelect: editMode ? onSelect : undefined, registerRef: registerRef, children: _jsx(GameObjectRenderer, { gameObject: data.root, selectedId: selectedId, onSelect: editMode ? onSelect : undefined, onClick: onClick, registerRef: registerRef, registerRigidBodyRef: registerRigidBodyRef, loadedModels: models, loadedTextures: textures, editMode: editMode, parentMatrix: IDENTITY }) }), editMode && (_jsxs(_Fragment, { children: [_jsx(MapControls, { ref: controlsRef, makeDefault: true }), selectedObject && (_jsx(TransformControls, { object: selectedObject, mode: transformMode, space: "local", onObjectChange: onTransformChange, translationSnap: positionSnap > 0 ? positionSnap : undefined, rotationSnap: rotationSnap > 0 ? rotationSnap : undefined, scaleSnap: snapResolution > 0 ? snapResolution : undefined }, `transform-${transformMode}-${positionSnap}-${rotationSnap}-${snapResolution}`))] }))] }));
|
|
118
148
|
});
|
|
119
149
|
export function GameObjectRenderer(props) {
|
|
120
150
|
var _a, _b, _c;
|
|
@@ -172,7 +202,7 @@ function InstancedNode({ gameObject, parentMatrix = IDENTITY, editMode, register
|
|
|
172
202
|
return (_jsx(GameInstance, { id: gameObject.id, modelUrl: (_k = (_j = (_h = gameObject.components) === null || _h === void 0 ? void 0 : _h.model) === null || _j === void 0 ? void 0 : _j.properties) === null || _k === void 0 ? void 0 : _k.filename, position: worldPosition, rotation: worldRotation, scale: worldScale, physics: physicsProps }));
|
|
173
203
|
}
|
|
174
204
|
function StandardNode({ gameObject, selectedId, onSelect, onClick, registerRef, registerRigidBodyRef, loadedModels, loadedTextures, editMode, parentMatrix = IDENTITY, }) {
|
|
175
|
-
var _a, _b, _c, _d, _e
|
|
205
|
+
var _a, _b, _c, _d, _e;
|
|
176
206
|
const groupRef = useRef(null);
|
|
177
207
|
const helperRef = useRef(null);
|
|
178
208
|
const clickValid = useRef(false);
|
|
@@ -204,7 +234,20 @@ function StandardNode({ gameObject, selectedId, onSelect, onClick, registerRef,
|
|
|
204
234
|
const physicsDef = hasPhysics ? getComponent("Physics") : null;
|
|
205
235
|
const isInstanced = (_e = (_d = (_c = gameObject.components) === null || _c === void 0 ? void 0 : _c.model) === null || _d === void 0 ? void 0 : _d.properties) === null || _e === void 0 ? void 0 : _e.instanced;
|
|
206
236
|
const physicsKey = `physics_${gameObject.id}_${isInstanced ? 'instanced' : 'standard'}`;
|
|
207
|
-
const
|
|
237
|
+
const renderCtx = createRenderContext(loadedModels, loadedTextures, editMode, selectedId, registerRef);
|
|
238
|
+
const childNodes = getChildHostComponents(gameObject).length > 0
|
|
239
|
+
? renderHostedChildren(gameObject, renderCtx, world)
|
|
240
|
+
: renderSceneChildren(gameObject, world, {
|
|
241
|
+
selectedId,
|
|
242
|
+
onSelect,
|
|
243
|
+
onClick,
|
|
244
|
+
registerRef,
|
|
245
|
+
registerRigidBodyRef,
|
|
246
|
+
loadedModels,
|
|
247
|
+
loadedTextures,
|
|
248
|
+
editMode,
|
|
249
|
+
});
|
|
250
|
+
const inner = (_jsx("group", { onPointerDown: editMode ? onDown : undefined, onPointerMove: editMode ? () => (clickValid.current = false) : undefined, onPointerUp: editMode ? onUp : undefined, children: renderCompositionNode(gameObject, renderCtx, parentMatrix, childNodes) }));
|
|
208
251
|
if (editMode) {
|
|
209
252
|
return (_jsxs(_Fragment, { children: [_jsx("group", { ref: groupRef, position: transform.position, rotation: transform.rotation, scale: transform.scale, children: _jsx("mesh", { visible: false, children: _jsx("boxGeometry", { args: [0.01, 0.01, 0.01] }) }) }), _jsx("group", { ref: helperRef, position: transform.position, rotation: transform.rotation, scale: transform.scale, children: inner }), hasPhysics && (physicsDef === null || physicsDef === void 0 ? void 0 : physicsDef.View) ? (_jsx(physicsDef.View, { properties: physics.properties, position: transform.position, rotation: transform.rotation, scale: transform.scale, editMode: editMode, nodeId: gameObject.id, registerRigidBodyRef: registerRigidBodyRef, children: inner }, physicsKey)) : null] }));
|
|
210
253
|
}
|
|
@@ -213,6 +256,28 @@ function StandardNode({ gameObject, selectedId, onSelect, onClick, registerRef,
|
|
|
213
256
|
}
|
|
214
257
|
return (_jsx("group", { ref: groupRef, position: transform.position, rotation: transform.rotation, scale: transform.scale, onPointerDown: onDown, onPointerMove: () => (clickValid.current = false), onPointerUp: onUp, children: inner }));
|
|
215
258
|
}
|
|
259
|
+
const CHILD_HOST_COMPONENT_TYPES = new Set(["Environment"]);
|
|
260
|
+
function isChildHostType(type) {
|
|
261
|
+
return CHILD_HOST_COMPONENT_TYPES.has(type);
|
|
262
|
+
}
|
|
263
|
+
function getChildHostComponents(gameObject) {
|
|
264
|
+
var _a;
|
|
265
|
+
return Object.entries((_a = gameObject.components) !== null && _a !== void 0 ? _a : {}).flatMap(([key, comp]) => {
|
|
266
|
+
if (!(comp === null || comp === void 0 ? void 0 : comp.type) || !isChildHostType(comp.type))
|
|
267
|
+
return [];
|
|
268
|
+
const def = getComponent(comp.type);
|
|
269
|
+
if (!(def === null || def === void 0 ? void 0 : def.View))
|
|
270
|
+
return [];
|
|
271
|
+
return { key, View: def.View, properties: comp.properties };
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function createRenderContext(loadedModels, loadedTextures, editMode, selectedId, registerRef) {
|
|
275
|
+
return { loadedModels, loadedTextures, editMode, selectedId, registerRef };
|
|
276
|
+
}
|
|
277
|
+
function renderSceneChildren(gameObject, parentMatrix, props) {
|
|
278
|
+
var _a;
|
|
279
|
+
return (_a = gameObject.children) === null || _a === void 0 ? void 0 : _a.map(child => _jsx(GameObjectRenderer, { gameObject: child, selectedId: props.selectedId, onSelect: props.onSelect, onClick: props.onClick, registerRef: props.registerRef, registerRigidBodyRef: props.registerRigidBodyRef, loadedModels: props.loadedModels, loadedTextures: props.loadedTextures, editMode: props.editMode, parentMatrix: parentMatrix }, child.id));
|
|
280
|
+
}
|
|
216
281
|
function walk(node, fn) {
|
|
217
282
|
var _a;
|
|
218
283
|
fn(node);
|
|
@@ -255,7 +320,25 @@ function computeParentWorldMatrix(root, targetId) {
|
|
|
255
320
|
visit(root, IDENTITY);
|
|
256
321
|
return result !== null && result !== void 0 ? result : IDENTITY;
|
|
257
322
|
}
|
|
258
|
-
function
|
|
323
|
+
function renderCompositionSubtree(gameObject, ctx, parentMatrix = IDENTITY) {
|
|
324
|
+
if (!gameObject || gameObject.disabled)
|
|
325
|
+
return null;
|
|
326
|
+
const transform = getNodeTransformProps(gameObject);
|
|
327
|
+
const world = parentMatrix.clone().multiply(compose(gameObject));
|
|
328
|
+
const childNodes = renderHostedChildren(gameObject, ctx, world);
|
|
329
|
+
return (_jsx("group", { position: transform.position, rotation: transform.rotation, scale: transform.scale, children: renderCompositionNode(gameObject, ctx, parentMatrix, childNodes) }, gameObject.id));
|
|
330
|
+
}
|
|
331
|
+
function renderHostedChildren(gameObject, ctx, parentMatrix) {
|
|
332
|
+
var _a;
|
|
333
|
+
return (_a = gameObject.children) === null || _a === void 0 ? void 0 : _a.map(child => renderCompositionSubtree(child, ctx, parentMatrix));
|
|
334
|
+
}
|
|
335
|
+
function renderCompositionNode(gameObject, ctx, parentMatrix, childNodes) {
|
|
336
|
+
const ownContent = renderNodeOwnContent(gameObject, ctx, parentMatrix);
|
|
337
|
+
const siblingContent = renderNodeSiblingComponents(gameObject, ctx, parentMatrix);
|
|
338
|
+
const subtree = _jsxs(_Fragment, { children: [ownContent, siblingContent, childNodes] });
|
|
339
|
+
return wrapWithChildHosts(gameObject, ctx, parentMatrix, subtree);
|
|
340
|
+
}
|
|
341
|
+
function renderNodeOwnContent(gameObject, ctx, parentMatrix) {
|
|
259
342
|
var _a, _b, _c, _d;
|
|
260
343
|
const geometry = (_a = gameObject.components) === null || _a === void 0 ? void 0 : _a.geometry;
|
|
261
344
|
const material = (_b = gameObject.components) === null || _b === void 0 ? void 0 : _b.material;
|
|
@@ -269,41 +352,59 @@ function renderCoreNode(gameObject, ctx, parentMatrix) {
|
|
|
269
352
|
loadedModels: ctx.loadedModels,
|
|
270
353
|
loadedTextures: ctx.loadedTextures,
|
|
271
354
|
editMode: ctx.editMode,
|
|
355
|
+
isSelected: ctx.selectedId === gameObject.id,
|
|
356
|
+
nodeId: gameObject.id,
|
|
272
357
|
parentMatrix,
|
|
273
358
|
registerRef: ctx.registerRef,
|
|
274
359
|
};
|
|
275
|
-
const wrappers = [];
|
|
276
|
-
const leaves = [];
|
|
277
|
-
if (gameObject.components) {
|
|
278
|
-
Object.entries(gameObject.components)
|
|
279
|
-
.filter(([k]) => !getNonComposableKeys().includes(k))
|
|
280
|
-
.forEach(([key, comp]) => {
|
|
281
|
-
if (!(comp === null || comp === void 0 ? void 0 : comp.type))
|
|
282
|
-
return;
|
|
283
|
-
const def = getComponent(comp.type);
|
|
284
|
-
if (!(def === null || def === void 0 ? void 0 : def.View))
|
|
285
|
-
return;
|
|
286
|
-
if (def.View.toString().includes("children")) {
|
|
287
|
-
wrappers.push({ key, View: def.View, properties: comp.properties });
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
leaves.push(_jsx(def.View, Object.assign({ properties: comp.properties }, contextProps), key));
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
360
|
let core;
|
|
295
361
|
if (model && (modelDef === null || modelDef === void 0 ? void 0 : modelDef.View)) {
|
|
296
|
-
core = (
|
|
362
|
+
core = (_jsx(modelDef.View, Object.assign({ properties: model.properties }, contextProps, { children: material && (materialDef === null || materialDef === void 0 ? void 0 : materialDef.View) && (_jsx(materialDef.View, Object.assign({ properties: material.properties }, contextProps), "material")) })));
|
|
297
363
|
}
|
|
298
364
|
else if (geometry && (geometryDef === null || geometryDef === void 0 ? void 0 : geometryDef.View)) {
|
|
299
|
-
core = (_jsxs("mesh", { castShadow: true, receiveShadow: true, children: [_jsx(geometryDef.View, Object.assign({ properties: geometry.properties }, contextProps)), material && (materialDef === null || materialDef === void 0 ? void 0 : materialDef.View) && (_jsx(materialDef.View, Object.assign({ properties: material.properties }, contextProps), "material"))
|
|
365
|
+
core = (_jsxs("mesh", { castShadow: true, receiveShadow: true, children: [_jsx(geometryDef.View, Object.assign({ properties: geometry.properties }, contextProps)), material && (materialDef === null || materialDef === void 0 ? void 0 : materialDef.View) && (_jsx(materialDef.View, Object.assign({ properties: material.properties }, contextProps), "material"))] }));
|
|
300
366
|
}
|
|
301
367
|
else if (text && (textDef === null || textDef === void 0 ? void 0 : textDef.View)) {
|
|
302
|
-
core = (
|
|
368
|
+
core = (_jsx(_Fragment, { children: _jsx(textDef.View, Object.assign({ properties: text.properties }, contextProps)) }));
|
|
303
369
|
}
|
|
304
370
|
else {
|
|
305
|
-
core =
|
|
371
|
+
core = null;
|
|
306
372
|
}
|
|
307
|
-
return
|
|
373
|
+
return core;
|
|
374
|
+
}
|
|
375
|
+
function renderNodeSiblingComponents(gameObject, ctx, parentMatrix) {
|
|
376
|
+
var _a;
|
|
377
|
+
const contextProps = {
|
|
378
|
+
loadedModels: ctx.loadedModels,
|
|
379
|
+
loadedTextures: ctx.loadedTextures,
|
|
380
|
+
editMode: ctx.editMode,
|
|
381
|
+
isSelected: ctx.selectedId === gameObject.id,
|
|
382
|
+
nodeId: gameObject.id,
|
|
383
|
+
parentMatrix,
|
|
384
|
+
registerRef: ctx.registerRef,
|
|
385
|
+
};
|
|
386
|
+
return Object.entries((_a = gameObject.components) !== null && _a !== void 0 ? _a : {})
|
|
387
|
+
.filter(([key]) => !getNonComposableKeys().includes(key))
|
|
388
|
+
.flatMap(([key, comp]) => {
|
|
389
|
+
if (!(comp === null || comp === void 0 ? void 0 : comp.type) || isChildHostType(comp.type))
|
|
390
|
+
return [];
|
|
391
|
+
const def = getComponent(comp.type);
|
|
392
|
+
if (!(def === null || def === void 0 ? void 0 : def.View))
|
|
393
|
+
return [];
|
|
394
|
+
return _jsx(def.View, Object.assign({ properties: comp.properties }, contextProps), key);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
function wrapWithChildHosts(gameObject, ctx, parentMatrix, subtree) {
|
|
398
|
+
const contextProps = {
|
|
399
|
+
loadedModels: ctx.loadedModels,
|
|
400
|
+
loadedTextures: ctx.loadedTextures,
|
|
401
|
+
editMode: ctx.editMode,
|
|
402
|
+
isSelected: ctx.selectedId === gameObject.id,
|
|
403
|
+
nodeId: gameObject.id,
|
|
404
|
+
parentMatrix,
|
|
405
|
+
registerRef: ctx.registerRef,
|
|
406
|
+
};
|
|
407
|
+
const childHosts = getChildHostComponents(gameObject);
|
|
408
|
+
return childHosts.reduce((acc, { key, View, properties }) => (_jsx(View, Object.assign({ properties: properties }, contextProps, { children: acc }), key)), subtree);
|
|
308
409
|
}
|
|
309
410
|
export default PrefabRoot;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
const ambientLightFields = [
|
|
4
|
-
{ name: 'color', type: 'color', label: 'Color' },
|
|
5
|
-
{ name: 'intensity', type: 'number', label: 'Intensity', step: 0.1, min: 0 },
|
|
6
|
-
];
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ColorField, FieldGroup, NumberField } from "./Input";
|
|
7
3
|
function AmbientLightComponentEditor({ component, onUpdate, }) {
|
|
8
|
-
return (_jsx(
|
|
4
|
+
return (_jsxs(FieldGroup, { children: [_jsx(ColorField, { name: "color", label: "Color", values: component.properties, onChange: onUpdate }), _jsx(NumberField, { name: "intensity", label: "Intensity", values: component.properties, onChange: onUpdate, min: 0, step: 0.1, fallback: 1 })] }));
|
|
9
5
|
}
|
|
10
6
|
function AmbientLightComponentView({ properties }) {
|
|
11
7
|
const { color = '#ffffff', intensity = 1 } = properties;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { PerspectiveCamera, useHelper } from '@react-three/drei';
|
|
3
|
+
import { useRef } from 'react';
|
|
4
|
+
import { CameraHelper } from 'three';
|
|
5
|
+
import { FieldGroup, NumberField } from './Input';
|
|
6
|
+
function CameraComponentEditor({ component, onUpdate }) {
|
|
7
|
+
return (_jsxs(FieldGroup, { children: [_jsx(NumberField, { name: "fov", label: "FOV", values: component.properties, onChange: onUpdate, fallback: 50, min: 1, max: 179, step: 1 }), _jsx(NumberField, { name: "near", label: "Near", values: component.properties, onChange: onUpdate, fallback: 0.1, min: 0.001, step: 0.1 }), _jsx(NumberField, { name: "zoom", label: "Zoom", values: component.properties, onChange: onUpdate, fallback: 1, min: 0.01, step: 0.1 }), _jsx(NumberField, { name: "far", label: "Far", values: component.properties, onChange: onUpdate, fallback: 1000, min: 0.1, step: 1 })] }));
|
|
8
|
+
}
|
|
9
|
+
function CameraComponentView({ properties, editMode, isSelected }) {
|
|
10
|
+
var _a, _b, _c, _d;
|
|
11
|
+
const fov = (_a = properties === null || properties === void 0 ? void 0 : properties.fov) !== null && _a !== void 0 ? _a : 50;
|
|
12
|
+
const near = (_b = properties === null || properties === void 0 ? void 0 : properties.near) !== null && _b !== void 0 ? _b : 0.1;
|
|
13
|
+
const zoom = (_c = properties === null || properties === void 0 ? void 0 : properties.zoom) !== null && _c !== void 0 ? _c : 1;
|
|
14
|
+
const far = (_d = properties === null || properties === void 0 ? void 0 : properties.far) !== null && _d !== void 0 ? _d : 1000;
|
|
15
|
+
const cameraRef = useRef(null);
|
|
16
|
+
useHelper(editMode && isSelected ? cameraRef : null, CameraHelper);
|
|
17
|
+
return (_jsxs(_Fragment, { children: [_jsx(PerspectiveCamera, { ref: cameraRef, makeDefault: !editMode, fov: fov, near: near, zoom: zoom, far: far }), editMode && !isSelected ? (_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.34, 0.22, 0.18] }), _jsx("meshBasicMaterial", { color: "#22d3ee", wireframe: true })] })) : null] }));
|
|
18
|
+
}
|
|
19
|
+
const CameraComponent = {
|
|
20
|
+
name: 'Camera',
|
|
21
|
+
Editor: CameraComponentEditor,
|
|
22
|
+
View: CameraComponentView,
|
|
23
|
+
defaultProperties: {},
|
|
24
|
+
};
|
|
25
|
+
export default CameraComponent;
|
|
@@ -31,7 +31,7 @@ const directionalLightFields = [
|
|
|
31
31
|
function DirectionalLightComponentEditor({ component, onUpdate }) {
|
|
32
32
|
return (_jsx(FieldRenderer, { fields: directionalLightFields, values: component.properties, onChange: onUpdate }));
|
|
33
33
|
}
|
|
34
|
-
function DirectionalLightView({ properties, editMode }) {
|
|
34
|
+
function DirectionalLightView({ properties, editMode, isSelected }) {
|
|
35
35
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
36
36
|
const color = (_a = properties.color) !== null && _a !== void 0 ? _a : '#ffffff';
|
|
37
37
|
const intensity = (_b = properties.intensity) !== null && _b !== void 0 ? _b : 1.0;
|
|
@@ -61,7 +61,7 @@ function DirectionalLightView({ properties, editMode }) {
|
|
|
61
61
|
// Target is positioned relative to light's world position
|
|
62
62
|
targetRef.current.position.set(lightWorldPos.x + targetOffset[0], lightWorldPos.y + targetOffset[1], lightWorldPos.z + targetOffset[2]);
|
|
63
63
|
});
|
|
64
|
-
return (_jsxs(_Fragment, { children: [_jsx("directionalLight", { ref: directionalLightRef, color: color, intensity: intensity, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar, "shadow-camera-top": shadowCameraTop, "shadow-camera-bottom": shadowCameraBottom, "shadow-camera-left": shadowCameraLeft, "shadow-camera-right": shadowCameraRight, "shadow-bias": -0.001, "shadow-normalBias": 0.02 }), _jsx("object3D", { ref: targetRef }), editMode && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.3, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: targetOffset, children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] }), _jsxs("line", { children: [_jsx("bufferGeometry", { onUpdate: (geo) => {
|
|
64
|
+
return (_jsxs(_Fragment, { children: [_jsx("directionalLight", { ref: directionalLightRef, color: color, intensity: intensity, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar, "shadow-camera-top": shadowCameraTop, "shadow-camera-bottom": shadowCameraBottom, "shadow-camera-left": shadowCameraLeft, "shadow-camera-right": shadowCameraRight, "shadow-bias": -0.001, "shadow-normalBias": 0.02 }), _jsx("object3D", { ref: targetRef }), editMode && isSelected && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.3, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: targetOffset, children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] }), _jsxs("line", { children: [_jsx("bufferGeometry", { onUpdate: (geo) => {
|
|
65
65
|
const points = [
|
|
66
66
|
new Vector3(0, 0, 0),
|
|
67
67
|
new Vector3(targetOffset[0], targetOffset[1], targetOffset[2])
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Environment } from '@react-three/drei';
|
|
3
|
+
import { FieldGroup, NumberField } from './Input';
|
|
4
|
+
function EnvironmentView({ properties, children, editMode, loadedTextures, loadedModels, }) {
|
|
5
|
+
const { intensity = 1, resolution = 256 } = properties;
|
|
6
|
+
const assetRevision = `${Object.keys(loadedTextures !== null && loadedTextures !== void 0 ? loadedTextures : {}).sort().join('|')}::${Object.keys(loadedModels !== null && loadedModels !== void 0 ? loadedModels : {}).sort().join('|')}`;
|
|
7
|
+
return (_jsx(Environment, { background: true, environmentIntensity: intensity, resolution: resolution, frames: editMode ? undefined : 1, children: children }, assetRevision));
|
|
8
|
+
}
|
|
9
|
+
const EnvironmentComponent = {
|
|
10
|
+
name: 'Environment',
|
|
11
|
+
Editor: ({ component, onUpdate }) => (_jsxs(FieldGroup, { children: [_jsx(NumberField, { name: "intensity", label: "Intensity", values: component.properties, onChange: onUpdate, min: 0, step: 0.1, fallback: 1 }), _jsx(NumberField, { name: "resolution", label: "Resolution", values: component.properties, onChange: onUpdate, min: 64, step: 64, fallback: 256 })] })),
|
|
12
|
+
View: EnvironmentView,
|
|
13
|
+
defaultProperties: {},
|
|
14
|
+
};
|
|
15
|
+
export default EnvironmentComponent;
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FieldGroup, NumberField, SelectField } from "./Input";
|
|
3
3
|
const GEOMETRY_ARGS = {
|
|
4
4
|
box: {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
fields: [
|
|
6
|
+
{ name: 'width', label: 'Width', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
7
|
+
{ name: 'height', label: 'Height', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
8
|
+
{ name: 'depth', label: 'Depth', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
9
|
+
],
|
|
7
10
|
},
|
|
8
11
|
sphere: {
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
fields: [
|
|
13
|
+
{ name: 'radius', label: 'Radius', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
14
|
+
{ name: 'widthSegments', label: 'Width Segments', defaultValue: 32, min: 3, step: 1 },
|
|
15
|
+
{ name: 'heightSegments', label: 'Height Segments', defaultValue: 16, min: 2, step: 1 },
|
|
16
|
+
],
|
|
11
17
|
},
|
|
12
18
|
plane: {
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
fields: [
|
|
20
|
+
{ name: 'width', label: 'Width', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
21
|
+
{ name: 'height', label: 'Height', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
22
|
+
],
|
|
15
23
|
},
|
|
16
24
|
cylinder: {
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
fields: [
|
|
26
|
+
{ name: 'radiusTop', label: 'Radius Top', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
27
|
+
{ name: 'radiusBottom', label: 'Radius Bottom', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
28
|
+
{ name: 'height', label: 'Height', defaultValue: 1, min: 0.01, step: 0.1 },
|
|
29
|
+
{ name: 'radialSegments', label: 'Radial Segments', defaultValue: 32, min: 3, step: 1 },
|
|
30
|
+
],
|
|
19
31
|
},
|
|
20
32
|
};
|
|
33
|
+
function getDefaultArgs(geometryType) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
return ((_b = (_a = GEOMETRY_ARGS[geometryType]) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : []).map(field => field.defaultValue);
|
|
36
|
+
}
|
|
21
37
|
function GeometryComponentEditor({ component, onUpdate, }) {
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
name: 'geometryType',
|
|
27
|
-
type: 'select',
|
|
28
|
-
label: 'Type',
|
|
29
|
-
options: [
|
|
30
|
-
{ value: 'box', label: 'Box' },
|
|
31
|
-
{ value: 'sphere', label: 'Sphere' },
|
|
32
|
-
{ value: 'plane', label: 'Plane' },
|
|
33
|
-
{ value: 'cylinder', label: 'Cylinder' },
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: 'args',
|
|
38
|
-
type: 'custom',
|
|
39
|
-
label: '',
|
|
40
|
-
render: ({ values, onChangeMultiple }) => {
|
|
41
|
-
const currentType = values.geometryType;
|
|
42
|
-
const currentSchema = GEOMETRY_ARGS[currentType];
|
|
43
|
-
const currentArgs = values.args || currentSchema.defaults;
|
|
44
|
-
return (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: currentSchema.labels.map((label, i) => {
|
|
45
|
-
var _a;
|
|
46
|
-
return (_jsx(Input, { label: label, value: (_a = currentArgs[i]) !== null && _a !== void 0 ? _a : currentSchema.defaults[i], step: 0.1, min: 0.01, onChange: value => {
|
|
47
|
-
const next = [...currentArgs];
|
|
48
|
-
next[i] = value;
|
|
49
|
-
onChangeMultiple({ args: next });
|
|
50
|
-
} }, label));
|
|
51
|
-
}) }));
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
];
|
|
38
|
+
var _a, _b, _c;
|
|
39
|
+
const geometryType = (_a = component.properties.geometryType) !== null && _a !== void 0 ? _a : 'box';
|
|
40
|
+
const schema = (_b = GEOMETRY_ARGS[geometryType]) !== null && _b !== void 0 ? _b : GEOMETRY_ARGS.box;
|
|
41
|
+
const args = (_c = component.properties.args) !== null && _c !== void 0 ? _c : getDefaultArgs(geometryType);
|
|
55
42
|
// Handle geometry type change to reset args
|
|
56
43
|
const handleChange = (newValues) => {
|
|
57
44
|
if ('geometryType' in newValues && newValues.geometryType !== geometryType) {
|
|
58
|
-
onUpdate({ geometryType: newValues.geometryType, args:
|
|
45
|
+
onUpdate({ geometryType: newValues.geometryType, args: getDefaultArgs(newValues.geometryType) });
|
|
59
46
|
}
|
|
60
47
|
else {
|
|
61
48
|
onUpdate(newValues);
|
|
62
49
|
}
|
|
63
50
|
};
|
|
64
|
-
|
|
51
|
+
const updateArg = (index, value) => {
|
|
52
|
+
const next = [...args];
|
|
53
|
+
next[index] = value;
|
|
54
|
+
onUpdate({ args: next });
|
|
55
|
+
};
|
|
56
|
+
return (_jsxs(FieldGroup, { children: [_jsx(SelectField, { name: "geometryType", label: "Type", values: component.properties, onChange: handleChange, options: [
|
|
57
|
+
{ value: 'box', label: 'Box' },
|
|
58
|
+
{ value: 'sphere', label: 'Sphere' },
|
|
59
|
+
{ value: 'plane', label: 'Plane' },
|
|
60
|
+
{ value: 'cylinder', label: 'Cylinder' },
|
|
61
|
+
] }), schema.fields.map((field, index) => {
|
|
62
|
+
var _a;
|
|
63
|
+
return (_jsx(NumberField, { name: field.name, label: field.label, values: { [field.name]: (_a = args[index]) !== null && _a !== void 0 ? _a : field.defaultValue }, onChange: (next) => updateArg(index, next[field.name]), fallback: field.defaultValue, min: field.min, step: field.step }, field.name));
|
|
64
|
+
})] }));
|
|
65
65
|
}
|
|
66
66
|
// View for Geometry component
|
|
67
67
|
function GeometryComponentView({ properties, children }) {
|
|
@@ -87,7 +87,7 @@ const GeometryComponent = {
|
|
|
87
87
|
nonComposable: true,
|
|
88
88
|
defaultProperties: {
|
|
89
89
|
geometryType: 'box',
|
|
90
|
-
args:
|
|
90
|
+
args: getDefaultArgs('box'),
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
93
|
export default GeometryComponent;
|
|
@@ -58,11 +58,12 @@ export declare function Input({ value, onChange, step, min, max, style, label }:
|
|
|
58
58
|
export declare function Label({ children }: {
|
|
59
59
|
children: React.ReactNode;
|
|
60
60
|
}): import("react/jsx-runtime").JSX.Element;
|
|
61
|
-
export declare function Vector3Input({ label, value, onChange, snap }: {
|
|
61
|
+
export declare function Vector3Input({ label, value, onChange, snap, labelExtra }: {
|
|
62
62
|
label: string;
|
|
63
63
|
value: [number, number, number];
|
|
64
64
|
onChange: (v: [number, number, number]) => void;
|
|
65
65
|
snap?: number;
|
|
66
|
+
labelExtra?: React.ReactNode;
|
|
66
67
|
}): import("react/jsx-runtime").JSX.Element;
|
|
67
68
|
export declare function ColorInput({ label, value, onChange }: {
|
|
68
69
|
label?: string;
|
|
@@ -89,6 +90,55 @@ export declare function SelectInput({ label, value, onChange, options }: {
|
|
|
89
90
|
label: string;
|
|
90
91
|
}[];
|
|
91
92
|
}): import("react/jsx-runtime").JSX.Element;
|
|
93
|
+
interface BoundFieldProps {
|
|
94
|
+
name: string;
|
|
95
|
+
values: Record<string, any>;
|
|
96
|
+
onChange: (values: Record<string, any>) => void;
|
|
97
|
+
}
|
|
98
|
+
interface BoundNumberFieldProps extends BoundFieldProps {
|
|
99
|
+
label: string;
|
|
100
|
+
fallback?: number;
|
|
101
|
+
step?: string | number;
|
|
102
|
+
min?: number;
|
|
103
|
+
max?: number;
|
|
104
|
+
style?: React.CSSProperties;
|
|
105
|
+
}
|
|
106
|
+
interface BoundStringFieldProps extends BoundFieldProps {
|
|
107
|
+
label: string;
|
|
108
|
+
fallback?: string;
|
|
109
|
+
placeholder?: string;
|
|
110
|
+
}
|
|
111
|
+
interface BoundColorFieldProps extends BoundFieldProps {
|
|
112
|
+
label: string;
|
|
113
|
+
fallback?: string;
|
|
114
|
+
}
|
|
115
|
+
interface BoundBooleanFieldProps extends BoundFieldProps {
|
|
116
|
+
label: string;
|
|
117
|
+
fallback?: boolean;
|
|
118
|
+
}
|
|
119
|
+
interface BoundSelectFieldProps extends BoundFieldProps {
|
|
120
|
+
label: string;
|
|
121
|
+
fallback?: string;
|
|
122
|
+
options: {
|
|
123
|
+
value: string;
|
|
124
|
+
label: string;
|
|
125
|
+
}[];
|
|
126
|
+
}
|
|
127
|
+
interface BoundVector3FieldProps extends BoundFieldProps {
|
|
128
|
+
label: string;
|
|
129
|
+
fallback?: [number, number, number];
|
|
130
|
+
snap?: number;
|
|
131
|
+
labelExtra?: React.ReactNode;
|
|
132
|
+
}
|
|
133
|
+
export declare function FieldGroup({ children }: {
|
|
134
|
+
children: React.ReactNode;
|
|
135
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
136
|
+
export declare function NumberField({ name, label, values, onChange, fallback, step, min, max, style, }: BoundNumberFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
137
|
+
export declare function StringField({ name, label, values, onChange, fallback, placeholder, }: BoundStringFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
138
|
+
export declare function ColorField({ name, label, values, onChange, fallback, }: BoundColorFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
139
|
+
export declare function BooleanField({ name, label, values, onChange, fallback, }: BoundBooleanFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
140
|
+
export declare function SelectField({ name, label, values, onChange, fallback, options, }: BoundSelectFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
141
|
+
export declare function Vector3Field({ name, label, values, onChange, fallback, snap, labelExtra, }: BoundVector3FieldProps): import("react/jsx-runtime").JSX.Element;
|
|
92
142
|
interface FieldRendererProps {
|
|
93
143
|
fields: FieldDefinition[];
|
|
94
144
|
values: Record<string, any>;
|