react-three-game 0.0.70 → 0.0.71
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 +10 -5
- package/dist/index.js +7 -2
- package/dist/tools/prefabeditor/EditorTree.js +2 -12
- package/dist/tools/prefabeditor/EditorTreeMenus.js +1 -19
- package/dist/tools/prefabeditor/EditorUI.js +2 -1
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +1 -1
- package/dist/tools/prefabeditor/PrefabEditor.js +12 -21
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +25 -12
- package/dist/tools/prefabeditor/PrefabRoot.js +61 -28
- package/dist/tools/prefabeditor/RefBridge.d.ts +24 -0
- package/dist/tools/prefabeditor/RefBridge.js +44 -0
- package/dist/tools/prefabeditor/components/AmbientLightComponent.js +10 -7
- package/dist/tools/prefabeditor/components/CameraComponent.js +8 -14
- package/dist/tools/prefabeditor/components/ClickComponent.js +2 -0
- package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +21 -1
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +124 -52
- package/dist/tools/prefabeditor/components/EnvironmentComponent.js +5 -3
- package/dist/tools/prefabeditor/components/MaterialComponent.js +9 -6
- package/dist/tools/prefabeditor/components/ModelComponent.js +4 -2
- package/dist/tools/prefabeditor/components/PhysicsComponent.js +5 -3
- package/dist/tools/prefabeditor/components/PointLightComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/PointLightComponent.js +55 -0
- package/dist/tools/prefabeditor/components/SoundComponent.js +20 -16
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +48 -24
- package/dist/tools/prefabeditor/components/index.js +2 -0
- package/dist/tools/prefabeditor/components/lightUtils.d.ts +13 -0
- package/dist/tools/prefabeditor/components/lightUtils.js +64 -0
- package/dist/tools/prefabeditor/prefab.d.ts +37 -0
- package/dist/tools/prefabeditor/prefab.js +229 -0
- package/dist/tools/prefabeditor/prefabStore.d.ts +3 -16
- package/dist/tools/prefabeditor/prefabStore.js +29 -168
- package/dist/tools/prefabeditor/{sceneApi.js → scene.js} +3 -14
- package/dist/tools/prefabeditor/utils.d.ts +0 -4
- package/dist/tools/prefabeditor/utils.js +0 -37
- package/package.json +1 -1
- /package/dist/tools/prefabeditor/{sceneApi.d.ts → scene.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { PerspectiveCamera } from '@react-three/drei';
|
|
3
|
-
import {
|
|
2
|
+
import { PerspectiveCamera, useHelper } from '@react-three/drei';
|
|
3
|
+
import { useRef } from 'react';
|
|
4
4
|
import { CameraHelper } from 'three';
|
|
5
5
|
import { useFrame } from '@react-three/fiber';
|
|
6
6
|
import { FieldGroup, NumberField } from './Input';
|
|
@@ -20,21 +20,15 @@ function CameraComponentView({ properties, children, editMode, isSelected }) {
|
|
|
20
20
|
const near = merged.near;
|
|
21
21
|
const zoom = merged.zoom;
|
|
22
22
|
const far = merged.far;
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
return () => {
|
|
27
|
-
cameraHelper === null || cameraHelper === void 0 ? void 0 : cameraHelper.dispose();
|
|
28
|
-
};
|
|
29
|
-
}, [cameraHelper]);
|
|
23
|
+
const cameraRef = useRef(null);
|
|
24
|
+
useHelper(editMode && isSelected ? cameraRef : null, CameraHelper);
|
|
30
25
|
useFrame(() => {
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
cameraHelper.update();
|
|
26
|
+
if (cameraRef.current && editMode && isSelected) {
|
|
27
|
+
cameraRef.current.updateProjectionMatrix();
|
|
28
|
+
cameraRef.current.updateMatrixWorld();
|
|
35
29
|
}
|
|
36
30
|
});
|
|
37
|
-
return (_jsxs(_Fragment, { children: [_jsx(PerspectiveCamera, { ref:
|
|
31
|
+
return (_jsxs(_Fragment, { children: [_jsx(PerspectiveCamera, { ref: cameraRef, makeDefault: !editMode, fov: fov, near: near, zoom: zoom, far: far }), editMode ? (_jsxs("group", { children: [_jsxs("mesh", { children: [_jsx("boxGeometry", { args: [0.3, 0.3, 0.5] }), _jsx("meshBasicMaterial", { color: '#22d3ee', wireframe: true })] }), _jsxs("mesh", { position: [0, 0, -0.25], rotation: [Math.PI / 2, 0, 0], children: [_jsx("coneGeometry", { args: [0.08, 0.16, 16] }), _jsx("meshBasicMaterial", { color: '#22d3ee', wireframe: true })] })] })) : null, children] }));
|
|
38
32
|
}
|
|
39
33
|
const CameraComponent = {
|
|
40
34
|
name: 'Camera',
|
|
@@ -27,6 +27,8 @@ function ClickComponentView({ children, editMode, nodeId, properties }) {
|
|
|
27
27
|
return (_jsx("group", { onPointerDown: (event) => {
|
|
28
28
|
event.stopPropagation();
|
|
29
29
|
clickValid.current = true;
|
|
30
|
+
}, onClick: (event) => {
|
|
31
|
+
event.stopPropagation();
|
|
30
32
|
}, onPointerMove: () => {
|
|
31
33
|
clickValid.current = false;
|
|
32
34
|
}, onPointerUp: (event) => {
|
|
@@ -4,6 +4,25 @@ export type AssetRef = {
|
|
|
4
4
|
type: "model" | "texture" | "sound";
|
|
5
5
|
path: string;
|
|
6
6
|
};
|
|
7
|
+
/** Props every component View receives from the renderer. */
|
|
8
|
+
export interface ComponentViewProps<P = Record<string, any>> {
|
|
9
|
+
/** This component's own data from the prefab JSON. */
|
|
10
|
+
properties: P;
|
|
11
|
+
/** Children to render (for wrapper / child-host components). */
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
/** The entity ID this component belongs to. */
|
|
14
|
+
nodeId?: string;
|
|
15
|
+
/** True when the editor is in edit mode. */
|
|
16
|
+
editMode?: boolean;
|
|
17
|
+
/** True when this entity is selected in the editor. */
|
|
18
|
+
isSelected?: boolean;
|
|
19
|
+
/** Entity local position (passed to wrapper components like Physics). */
|
|
20
|
+
position?: [number, number, number];
|
|
21
|
+
/** Entity local rotation in radians (passed to wrapper components like Physics). */
|
|
22
|
+
rotation?: [number, number, number];
|
|
23
|
+
/** Entity local scale (passed to wrapper components like Physics). */
|
|
24
|
+
scale?: [number, number, number];
|
|
25
|
+
}
|
|
7
26
|
export interface Component {
|
|
8
27
|
name: string;
|
|
9
28
|
Editor: FC<{
|
|
@@ -13,9 +32,10 @@ export interface Component {
|
|
|
13
32
|
basePath?: string;
|
|
14
33
|
}>;
|
|
15
34
|
defaultProperties: any;
|
|
16
|
-
View?: FC<
|
|
35
|
+
View?: FC<ComponentViewProps>;
|
|
17
36
|
/** When true, this component wraps child entities (e.g. Physics wraps children in RigidBody). */
|
|
18
37
|
isWrapper?: boolean;
|
|
38
|
+
/** Declare which asset paths this component references (for asset loading). */
|
|
19
39
|
getAssetRefs?: (properties: Record<string, any>) => AssetRef[];
|
|
20
40
|
}
|
|
21
41
|
export declare function registerComponent(component: Component): void;
|
|
@@ -1,59 +1,114 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useHelper } from "@react-three/drei";
|
|
3
|
+
import { useRef, useEffect, useState } from "react";
|
|
3
4
|
import { useFrame } from "@react-three/fiber";
|
|
4
5
|
import { CameraHelper, Vector3 } from "three";
|
|
5
|
-
import {
|
|
6
|
-
|
|
6
|
+
import { BooleanField, ColorField, NumberField, NumberInput, Vector3Input } from "./Input";
|
|
7
|
+
import { LightSection, ShadowBiasField, mergeWithDefaults } from "./lightUtils";
|
|
8
|
+
import { colors } from "../styles";
|
|
7
9
|
const directionalLightDefaults = {
|
|
8
10
|
color: '#ffffff',
|
|
9
11
|
intensity: 1,
|
|
10
|
-
castShadow:
|
|
11
|
-
shadowMapSize:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
castShadow: false,
|
|
13
|
+
shadowMapSize: 512,
|
|
14
|
+
shadowBias: 0,
|
|
15
|
+
shadowNormalBias: 0,
|
|
16
|
+
shadowAutoUpdate: true,
|
|
17
|
+
shadowCameraNear: 0.5,
|
|
18
|
+
shadowCameraFar: 500,
|
|
19
|
+
shadowCameraTop: 5,
|
|
20
|
+
shadowCameraBottom: -5,
|
|
21
|
+
shadowCameraLeft: -5,
|
|
22
|
+
shadowCameraRight: 5,
|
|
18
23
|
targetOffset: [0, -5, 0],
|
|
19
24
|
};
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
25
|
+
const frustumLabelStyle = {
|
|
26
|
+
fontSize: 10,
|
|
27
|
+
textTransform: 'uppercase',
|
|
28
|
+
letterSpacing: '0.06em',
|
|
29
|
+
color: colors.textMuted,
|
|
30
|
+
textAlign: 'center',
|
|
31
|
+
};
|
|
32
|
+
const frustumCellStyle = {
|
|
33
|
+
display: 'flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
};
|
|
37
|
+
const frustumInputStyle = {
|
|
38
|
+
width: 62,
|
|
39
|
+
minWidth: 62,
|
|
40
|
+
textAlign: 'center',
|
|
41
|
+
};
|
|
42
|
+
const centerLockButtonStyle = {
|
|
43
|
+
width: 34,
|
|
44
|
+
height: 34,
|
|
45
|
+
borderRadius: 999,
|
|
46
|
+
border: `1px solid ${colors.border}`,
|
|
47
|
+
background: colors.bgInput,
|
|
48
|
+
color: colors.textMuted,
|
|
49
|
+
cursor: 'pointer',
|
|
50
|
+
fontSize: 14,
|
|
51
|
+
lineHeight: 1,
|
|
52
|
+
padding: 0,
|
|
53
|
+
};
|
|
54
|
+
function areFrustumSidesLocked(values) {
|
|
55
|
+
const top = Math.abs(values.shadowCameraTop);
|
|
56
|
+
const bottom = Math.abs(values.shadowCameraBottom);
|
|
57
|
+
const left = Math.abs(values.shadowCameraLeft);
|
|
58
|
+
const right = Math.abs(values.shadowCameraRight);
|
|
59
|
+
return top === bottom && top === left && top === right;
|
|
60
|
+
}
|
|
61
|
+
function ShadowFrustumField({ values, onChange, }) {
|
|
62
|
+
const [locked, setLocked] = useState(() => areFrustumSidesLocked(values));
|
|
63
|
+
const updateSide = (side, nextValue) => {
|
|
64
|
+
if (!locked) {
|
|
65
|
+
onChange({ [side]: nextValue });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const magnitude = Math.abs(nextValue);
|
|
69
|
+
onChange({
|
|
70
|
+
shadowCameraTop: magnitude,
|
|
71
|
+
shadowCameraBottom: -magnitude,
|
|
72
|
+
shadowCameraLeft: -magnitude,
|
|
73
|
+
shadowCameraRight: magnitude,
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const toggleLocked = () => {
|
|
77
|
+
setLocked(current => {
|
|
78
|
+
const nextLocked = !current;
|
|
79
|
+
if (nextLocked) {
|
|
80
|
+
const magnitude = Math.max(Math.abs(values.shadowCameraTop), Math.abs(values.shadowCameraBottom), Math.abs(values.shadowCameraLeft), Math.abs(values.shadowCameraRight));
|
|
81
|
+
onChange({
|
|
82
|
+
shadowCameraTop: magnitude,
|
|
83
|
+
shadowCameraBottom: -magnitude,
|
|
84
|
+
shadowCameraLeft: -magnitude,
|
|
85
|
+
shadowCameraRight: magnitude,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return nextLocked;
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 6 }, children: [_jsx("div", { style: Object.assign(Object.assign({}, frustumLabelStyle), { textAlign: 'left' }), children: "Shadow Frustum" }), _jsxs("div", { style: {
|
|
92
|
+
display: 'grid',
|
|
93
|
+
gridTemplateColumns: '1fr auto 1fr',
|
|
94
|
+
gridTemplateRows: 'auto auto auto',
|
|
95
|
+
gap: 8,
|
|
96
|
+
alignItems: 'center',
|
|
97
|
+
}, children: [_jsx("div", {}), _jsx("div", { style: frustumCellStyle, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }, children: [_jsx("div", { style: frustumLabelStyle, children: "Top" }), _jsx(NumberInput, { value: values.shadowCameraTop, onChange: nextValue => updateSide('shadowCameraTop', nextValue), step: 0.5, style: frustumInputStyle })] }) }), _jsx("div", {}), _jsx("div", { style: frustumCellStyle, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }, children: [_jsx("div", { style: frustumLabelStyle, children: "Left" }), _jsx(NumberInput, { value: values.shadowCameraLeft, onChange: nextValue => updateSide('shadowCameraLeft', nextValue), step: 0.5, style: frustumInputStyle })] }) }), _jsx("div", { style: frustumCellStyle, children: _jsx("button", { type: "button", onClick: toggleLocked, style: Object.assign(Object.assign({}, centerLockButtonStyle), { color: locked ? colors.accent : colors.textMuted, borderColor: locked ? colors.accentBorder : colors.border, background: locked ? colors.accentBg : colors.bgInput }), title: locked ? 'Frustum sides locked' : 'Frustum sides unlocked', children: locked ? '🔒' : '🔓' }) }), _jsx("div", { style: frustumCellStyle, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }, children: [_jsx("div", { style: frustumLabelStyle, children: "Right" }), _jsx(NumberInput, { value: values.shadowCameraRight, onChange: nextValue => updateSide('shadowCameraRight', nextValue), step: 0.5, style: frustumInputStyle })] }) }), _jsx("div", {}), _jsx("div", { style: frustumCellStyle, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center' }, children: [_jsx("div", { style: frustumLabelStyle, children: "Bottom" }), _jsx(NumberInput, { value: values.shadowCameraBottom, onChange: nextValue => updateSide('shadowCameraBottom', nextValue), step: 0.5, style: frustumInputStyle })] }) }), _jsx("div", {})] })] }));
|
|
98
|
+
}
|
|
44
99
|
function DirectionalLightComponentEditor({ component, onUpdate }) {
|
|
45
|
-
const values =
|
|
46
|
-
|
|
47
|
-
? directionalLightFields
|
|
48
|
-
: directionalLightFields.filter(field => field.name !== '_shadowCamera');
|
|
49
|
-
return (_jsx(FieldRenderer, { fields: fields, values: values, onChange: onUpdate }));
|
|
100
|
+
const values = mergeWithDefaults(directionalLightDefaults, component.properties);
|
|
101
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsxs(LightSection, { title: "Light", children: [_jsx(ColorField, { name: "color", label: "Color", values: values, onChange: onUpdate }), _jsx(NumberField, { name: "intensity", label: "Intensity", values: values, onChange: onUpdate, min: 0, step: 0.1, fallback: 1 }), _jsx(Vector3Input, { label: "Target Offset", value: values.targetOffset, onChange: targetOffset => onUpdate({ targetOffset }), snap: 0.5 })] }), _jsxs(LightSection, { title: "Shadow", children: [_jsx(BooleanField, { name: "castShadow", label: "Cast Shadow", values: values, onChange: onUpdate, fallback: false }), values.castShadow ? (_jsxs(_Fragment, { children: [_jsx(BooleanField, { name: "shadowAutoUpdate", label: "Auto Update", values: values, onChange: onUpdate, fallback: true }), _jsx(NumberField, { name: "shadowMapSize", label: "Map Size", values: values, onChange: onUpdate, min: 128, step: 128, fallback: 512 }), _jsx(ShadowBiasField, { name: "shadowBias", label: "Bias", values: values, onChange: onUpdate, fallback: 0 }), _jsx(ShadowBiasField, { name: "shadowNormalBias", label: "Normal Bias", values: values, onChange: onUpdate, fallback: 0 }), _jsx(NumberField, { name: "shadowCameraNear", label: "Near", values: values, onChange: onUpdate, min: 0.001, step: 0.1, fallback: 0.5 }), _jsx(NumberField, { name: "shadowCameraFar", label: "Far", values: values, onChange: onUpdate, min: 0.1, step: 1, fallback: 500 }), _jsx(ShadowFrustumField, { values: values, onChange: onUpdate })] })) : null] })] }));
|
|
50
102
|
}
|
|
51
103
|
function DirectionalLightView({ properties, children, editMode, isSelected }) {
|
|
52
|
-
const merged =
|
|
104
|
+
const merged = mergeWithDefaults(directionalLightDefaults, properties);
|
|
53
105
|
const color = merged.color;
|
|
54
106
|
const intensity = merged.intensity;
|
|
55
107
|
const castShadow = merged.castShadow;
|
|
56
108
|
const shadowMapSize = merged.shadowMapSize;
|
|
109
|
+
const shadowBias = merged.shadowBias;
|
|
110
|
+
const shadowNormalBias = merged.shadowNormalBias;
|
|
111
|
+
const shadowAutoUpdate = merged.shadowAutoUpdate;
|
|
57
112
|
const shadowCameraNear = merged.shadowCameraNear;
|
|
58
113
|
const shadowCameraFar = merged.shadowCameraFar;
|
|
59
114
|
const shadowCameraTop = merged.shadowCameraTop;
|
|
@@ -63,31 +118,48 @@ function DirectionalLightView({ properties, children, editMode, isSelected }) {
|
|
|
63
118
|
const targetOffset = merged.targetOffset;
|
|
64
119
|
const directionalLightRef = useRef(null);
|
|
65
120
|
const targetRef = useRef(null);
|
|
121
|
+
const shadowCameraRef = useRef(null);
|
|
66
122
|
const [shadowCamera, setShadowCamera] = useState(null);
|
|
67
|
-
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
return () => {
|
|
70
|
-
shadowCameraHelper === null || shadowCameraHelper === void 0 ? void 0 : shadowCameraHelper.dispose();
|
|
71
|
-
};
|
|
72
|
-
}, [shadowCameraHelper]);
|
|
123
|
+
useHelper(editMode && isSelected && castShadow ? shadowCameraRef : null, CameraHelper);
|
|
73
124
|
// Use a local target object so node transforms rotate the light direction naturally.
|
|
74
125
|
useEffect(() => {
|
|
75
126
|
if (directionalLightRef.current && targetRef.current) {
|
|
76
127
|
directionalLightRef.current.target = targetRef.current;
|
|
77
|
-
|
|
128
|
+
const nextShadowCamera = directionalLightRef.current.shadow.camera;
|
|
129
|
+
shadowCameraRef.current = nextShadowCamera;
|
|
130
|
+
setShadowCamera(nextShadowCamera);
|
|
78
131
|
}
|
|
79
132
|
}, []);
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
var _a;
|
|
135
|
+
const shadow = (_a = directionalLightRef.current) === null || _a === void 0 ? void 0 : _a.shadow;
|
|
136
|
+
if (!shadow)
|
|
137
|
+
return;
|
|
138
|
+
shadow.needsUpdate = true;
|
|
139
|
+
shadow.camera.updateProjectionMatrix();
|
|
140
|
+
}, [
|
|
141
|
+
castShadow,
|
|
142
|
+
shadowMapSize,
|
|
143
|
+
shadowBias,
|
|
144
|
+
shadowNormalBias,
|
|
145
|
+
shadowAutoUpdate,
|
|
146
|
+
shadowCameraNear,
|
|
147
|
+
shadowCameraFar,
|
|
148
|
+
shadowCameraTop,
|
|
149
|
+
shadowCameraBottom,
|
|
150
|
+
shadowCameraLeft,
|
|
151
|
+
shadowCameraRight,
|
|
152
|
+
]);
|
|
80
153
|
useFrame(() => {
|
|
81
154
|
if (!directionalLightRef.current || !targetRef.current)
|
|
82
155
|
return;
|
|
83
156
|
directionalLightRef.current.target.updateMatrixWorld();
|
|
84
|
-
if (shadowCamera &&
|
|
157
|
+
if (shadowCamera && castShadow) {
|
|
85
158
|
shadowCamera.updateProjectionMatrix();
|
|
86
159
|
shadowCamera.updateMatrixWorld();
|
|
87
|
-
shadowCameraHelper.update();
|
|
88
160
|
}
|
|
89
161
|
});
|
|
90
|
-
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":
|
|
162
|
+
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": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate }), _jsx("object3D", { ref: targetRef, position: targetOffset }), 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) => {
|
|
91
163
|
const points = [
|
|
92
164
|
new Vector3(0, 0, 0),
|
|
93
165
|
new Vector3(targetOffset[0], targetOffset[1], targetOffset[2])
|
|
@@ -99,6 +171,6 @@ const DirectionalLightComponent = {
|
|
|
99
171
|
name: 'DirectionalLight',
|
|
100
172
|
Editor: DirectionalLightComponentEditor,
|
|
101
173
|
View: DirectionalLightView,
|
|
102
|
-
defaultProperties:
|
|
174
|
+
defaultProperties: {}
|
|
103
175
|
};
|
|
104
176
|
export default DirectionalLightComponent;
|
|
@@ -1,10 +1,12 @@
|
|
|
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
|
-
|
|
4
|
+
import { useSceneRuntime } from '../PrefabRoot';
|
|
5
|
+
function EnvironmentView({ properties, children, }) {
|
|
6
|
+
const { getAssetRevision } = useSceneRuntime();
|
|
5
7
|
const { intensity = 1, resolution = 256 } = properties;
|
|
6
|
-
const
|
|
7
|
-
return (_jsx(Environment, { background: true, environmentIntensity: intensity, resolution: resolution, frames:
|
|
8
|
+
const environmentRevision = `${getAssetRevision()}::${intensity}::${resolution}`;
|
|
9
|
+
return (_jsx(Environment, { background: true, environmentIntensity: intensity, resolution: resolution, frames: 1, children: children }, environmentRevision));
|
|
8
10
|
}
|
|
9
11
|
const EnvironmentComponent = {
|
|
10
12
|
name: 'Environment',
|
|
@@ -12,6 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import { extend } from '@react-three/fiber';
|
|
14
14
|
import { FieldRenderer, Label, NumberInput } from './Input';
|
|
15
|
+
import { useSceneRuntime } from '../PrefabRoot';
|
|
15
16
|
import { useMemo } from 'react';
|
|
16
17
|
import { MeshBasicNodeMaterial, MeshStandardNodeMaterial } from 'three/webgpu';
|
|
17
18
|
import { TexturePicker } from '../../assetviewer/page';
|
|
@@ -119,8 +120,10 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
119
120
|
return (_jsx(FieldRenderer, { fields: fields, values: component.properties, onChange: onUpdate }));
|
|
120
121
|
}
|
|
121
122
|
// View for Material component
|
|
122
|
-
function MaterialComponentView({ properties
|
|
123
|
-
var _a, _b, _c;
|
|
123
|
+
function MaterialComponentView({ properties: rawProps }) {
|
|
124
|
+
var _a, _b, _c, _d, _e;
|
|
125
|
+
const { getTexture } = useSceneRuntime();
|
|
126
|
+
const properties = rawProps;
|
|
124
127
|
const materialType = (_a = properties === null || properties === void 0 ? void 0 : properties.materialType) !== null && _a !== void 0 ? _a : 'standard';
|
|
125
128
|
const textureName = properties === null || properties === void 0 ? void 0 : properties.texture;
|
|
126
129
|
const repeat = properties === null || properties === void 0 ? void 0 : properties.repeat;
|
|
@@ -128,15 +131,15 @@ function MaterialComponentView({ properties, loadedTextures }) {
|
|
|
128
131
|
const generateMipmaps = (properties === null || properties === void 0 ? void 0 : properties.generateMipmaps) !== false;
|
|
129
132
|
const minFilter = (properties === null || properties === void 0 ? void 0 : properties.minFilter) || 'LinearMipmapLinearFilter';
|
|
130
133
|
const magFilter = (properties === null || properties === void 0 ? void 0 : properties.magFilter) || 'LinearFilter';
|
|
131
|
-
const texture = textureName &&
|
|
134
|
+
const texture = textureName ? (_b = getTexture(textureName)) !== null && _b !== void 0 ? _b : undefined : undefined;
|
|
132
135
|
const normalMapTextureName = properties === null || properties === void 0 ? void 0 : properties.normalMapTexture;
|
|
133
136
|
const normalScaleProp = properties === null || properties === void 0 ? void 0 : properties.normalScale;
|
|
134
|
-
const normalMapTexture = normalMapTextureName &&
|
|
137
|
+
const normalMapTexture = normalMapTextureName ? (_c = getTexture(normalMapTextureName)) !== null && _c !== void 0 ? _c : undefined : undefined;
|
|
135
138
|
const materialSource = properties !== null && properties !== void 0 ? properties : {};
|
|
136
139
|
// Destructure all material props and separate custom texture handling props
|
|
137
140
|
const { texture: _texture, repeat: _repeat, repeatCount: _repeatCount, generateMipmaps: _generateMipmaps, minFilter: _minFilter, magFilter: _magFilter, map: _map, materialType: _materialType, normalMapTexture: _normalMapTexture, normalScale: _normalScale, normalMap: _normalMap, side: sideProp } = materialSource, materialProps = __rest(materialSource, ["texture", "repeat", "repeatCount", "generateMipmaps", "minFilter", "magFilter", "map", "materialType", "normalMapTexture", "normalScale", "normalMap", "side"]);
|
|
138
141
|
const sideMap = { FrontSide, BackSide, DoubleSide };
|
|
139
|
-
const resolvedSide = sideProp ? ((
|
|
142
|
+
const resolvedSide = sideProp ? ((_d = sideMap[sideProp]) !== null && _d !== void 0 ? _d : FrontSide) : FrontSide;
|
|
140
143
|
const minFilterMap = {
|
|
141
144
|
NearestFilter,
|
|
142
145
|
LinearFilter,
|
|
@@ -187,7 +190,7 @@ function MaterialComponentView({ properties, loadedTextures }) {
|
|
|
187
190
|
if (!properties) {
|
|
188
191
|
return _jsx("meshStandardNodeMaterial", { color: "red", wireframe: true });
|
|
189
192
|
}
|
|
190
|
-
const materialKey = `${(
|
|
193
|
+
const materialKey = `${(_e = finalTexture === null || finalTexture === void 0 ? void 0 : finalTexture.uuid) !== null && _e !== void 0 ? _e : 'no-texture'}:${materialProps.transparent ? 'transparent' : 'opaque'}`;
|
|
191
194
|
const sharedProps = Object.assign({ map: finalTexture, side: resolvedSide }, materialProps);
|
|
192
195
|
if (materialType === 'basic') {
|
|
193
196
|
return _jsx("meshBasicNodeMaterial", Object.assign({}, sharedProps), materialKey);
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { ModelPicker } from '../../assetviewer/page';
|
|
3
3
|
import { useContext, useMemo } from 'react';
|
|
4
4
|
import { BooleanField, FieldGroup, Label, ListEditor, NumberInput, SelectInput } from './Input';
|
|
5
|
+
import { useSceneRuntime } from '../PrefabRoot';
|
|
5
6
|
import { EditorContext } from '../PrefabEditor';
|
|
6
7
|
import { DEFAULT_REPEAT_AXES, getRepeatAxesFromModelProperties, normalizeRepeatAxes } from '../InstanceProvider';
|
|
7
8
|
import { colors } from '../styles';
|
|
@@ -63,11 +64,12 @@ function ModelComponentEditor({ component, node, onUpdate, basePath = "" }) {
|
|
|
63
64
|
return (_jsxs(FieldGroup, { children: [_jsx(ModelPicker, { value: component.properties.filename, onChange: (filename) => onUpdate({ filename }), basePath: basePath, pickerKey: node === null || node === void 0 ? void 0 : node.id }), _jsx(BooleanField, { name: "instanced", label: "Instanced", values: component.properties, onChange: onUpdate, fallback: false }), component.properties.instanced && (_jsxs(_Fragment, { children: [_jsx(BooleanField, { name: "repeat", label: "Repeat", values: component.properties, onChange: onUpdate, fallback: false }), component.properties.repeat && (_jsx(RepeatAxisEditor, { axes: repeatAxes, onChange: (nextAxes) => onUpdate({ repeatAxes: nextAxes }), positionSnap: positionSnap }))] }))] }));
|
|
64
65
|
}
|
|
65
66
|
// View for Model component
|
|
66
|
-
function ModelComponentView({ properties,
|
|
67
|
+
function ModelComponentView({ properties, children }) {
|
|
68
|
+
const { getModel } = useSceneRuntime();
|
|
67
69
|
// Instanced models are handled elsewhere (GameInstance), so only render non-instanced here
|
|
68
70
|
if (!properties.filename || properties.instanced)
|
|
69
71
|
return _jsx(_Fragment, { children: children });
|
|
70
|
-
const sourceModel =
|
|
72
|
+
const sourceModel = getModel(properties.filename);
|
|
71
73
|
// Clone model once and set up shadows - memoized to avoid cloning on every render
|
|
72
74
|
const clonedModel = useMemo(() => {
|
|
73
75
|
if (!sourceModel)
|
|
@@ -12,6 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
13
|
import { CapsuleCollider, RigidBody, useRapier } from "@react-three/rapier";
|
|
14
14
|
import { useRef, useEffect, useCallback } from 'react';
|
|
15
|
+
import { useSceneRuntime } from "../PrefabRoot";
|
|
15
16
|
import { BooleanField, FieldGroup, ListEditor, NumberField, SelectField, SelectInput, StringInput, Vector3Field } from "./Input";
|
|
16
17
|
import { gameEvents, getEntityIdFromRigidBody } from "../GameEvents";
|
|
17
18
|
import { colors } from "../styles";
|
|
@@ -162,7 +163,8 @@ function PhysicsComponentEditor({ component, onUpdate }) {
|
|
|
162
163
|
{ value: 'all', label: 'All (includes kinematic & fixed)' },
|
|
163
164
|
] })] }));
|
|
164
165
|
}
|
|
165
|
-
function PhysicsComponentView({ properties, children, position, rotation, scale, editMode, nodeId
|
|
166
|
+
function PhysicsComponentView({ properties, children, position, rotation, scale, editMode, nodeId }) {
|
|
167
|
+
const { registerRigidBodyRef } = useSceneRuntime();
|
|
166
168
|
const { type, colliders, sensor, activeCollisionTypes, linearVelocity = [0, 0, 0], angularVelocity = [0, 0, 0], capsuleRadius = capsuleRadiusFallback, capsuleHalfHeight = capsuleHalfHeightFallback, sensorEnterEventName, sensorExitEventName, collisionEnterEventName, collisionExitEventName, enabledTranslations = enabledAxesFallback, enabledRotations = enabledAxesFallback } = properties, otherProps = __rest(properties, ["type", "colliders", "sensor", "activeCollisionTypes", "linearVelocity", "angularVelocity", "capsuleRadius", "capsuleHalfHeight", "sensorEnterEventName", "sensorExitEventName", "collisionEnterEventName", "collisionExitEventName", "enabledTranslations", "enabledRotations"]);
|
|
167
169
|
const colliderType = colliders || (type === 'fixed' ? 'trimesh' : 'hull');
|
|
168
170
|
const usesManualCapsuleCollider = colliderType === 'capsule';
|
|
@@ -183,11 +185,11 @@ function PhysicsComponentView({ properties, children, position, rotation, scale,
|
|
|
183
185
|
}
|
|
184
186
|
// Register RigidBody ref when it's available
|
|
185
187
|
useEffect(() => {
|
|
186
|
-
if (nodeId &&
|
|
188
|
+
if (nodeId && rigidBodyRef.current) {
|
|
187
189
|
registerRigidBodyRef(nodeId, rigidBodyRef.current);
|
|
188
190
|
}
|
|
189
191
|
return () => {
|
|
190
|
-
if (nodeId
|
|
192
|
+
if (nodeId) {
|
|
191
193
|
registerRigidBodyRef(nodeId, null);
|
|
192
194
|
}
|
|
193
195
|
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { useHelper } from '@react-three/drei';
|
|
4
|
+
import { PointLightHelper } from 'three';
|
|
5
|
+
import { BooleanField, ColorField, NumberField } from './Input';
|
|
6
|
+
import { LightSection, ShadowBiasField, mergeWithDefaults } from './lightUtils';
|
|
7
|
+
const pointLightDefaults = {
|
|
8
|
+
color: '#ffffff',
|
|
9
|
+
intensity: 1,
|
|
10
|
+
distance: 0,
|
|
11
|
+
decay: 2,
|
|
12
|
+
castShadow: false,
|
|
13
|
+
shadowMapSize: 512,
|
|
14
|
+
shadowBias: 0,
|
|
15
|
+
shadowNormalBias: 0,
|
|
16
|
+
shadowAutoUpdate: true,
|
|
17
|
+
shadowCameraNear: 0.5,
|
|
18
|
+
shadowCameraFar: 500,
|
|
19
|
+
};
|
|
20
|
+
function PointLightComponentEditor({ component, onUpdate }) {
|
|
21
|
+
const values = mergeWithDefaults(pointLightDefaults, component.properties);
|
|
22
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsxs(LightSection, { title: "Light", children: [_jsx(ColorField, { name: "color", label: "Color", values: values, onChange: onUpdate }), _jsx(NumberField, { name: "intensity", label: "Intensity", values: values, onChange: onUpdate, min: 0, step: 0.1, fallback: 1 }), _jsx(NumberField, { name: "distance", label: "Distance", values: values, onChange: onUpdate, min: 0, step: 1, fallback: 0 }), _jsx(NumberField, { name: "decay", label: "Decay", values: values, onChange: onUpdate, min: 0, step: 0.1, fallback: 2 })] }), _jsxs(LightSection, { title: "Shadow", children: [_jsx(BooleanField, { name: "castShadow", label: "Cast Shadow", values: values, onChange: onUpdate, fallback: false }), values.castShadow ? (_jsxs(_Fragment, { children: [_jsx(BooleanField, { name: "shadowAutoUpdate", label: "Auto Update", values: values, onChange: onUpdate, fallback: true }), _jsx(NumberField, { name: "shadowMapSize", label: "Map Size", values: values, onChange: onUpdate, min: 128, step: 128, fallback: 512 }), _jsx(ShadowBiasField, { name: "shadowBias", label: "Bias", values: values, onChange: onUpdate, fallback: 0 }), _jsx(ShadowBiasField, { name: "shadowNormalBias", label: "Normal Bias", values: values, onChange: onUpdate, fallback: 0 }), _jsx(NumberField, { name: "shadowCameraNear", label: "Near", values: values, onChange: onUpdate, min: 0.001, step: 0.1, fallback: 0.5 }), _jsx(NumberField, { name: "shadowCameraFar", label: "Far", values: values, onChange: onUpdate, min: 0.1, step: 1, fallback: 500 })] })) : null] })] }));
|
|
23
|
+
}
|
|
24
|
+
function PointLightView({ properties, children, editMode, isSelected }) {
|
|
25
|
+
const merged = mergeWithDefaults(pointLightDefaults, properties);
|
|
26
|
+
const color = merged.color;
|
|
27
|
+
const intensity = merged.intensity;
|
|
28
|
+
const distance = merged.distance;
|
|
29
|
+
const decay = merged.decay;
|
|
30
|
+
const castShadow = merged.castShadow;
|
|
31
|
+
const shadowMapSize = merged.shadowMapSize;
|
|
32
|
+
const shadowBias = merged.shadowBias;
|
|
33
|
+
const shadowNormalBias = merged.shadowNormalBias;
|
|
34
|
+
const shadowAutoUpdate = merged.shadowAutoUpdate;
|
|
35
|
+
const shadowCameraNear = merged.shadowCameraNear;
|
|
36
|
+
const shadowCameraFar = merged.shadowCameraFar;
|
|
37
|
+
const lightRef = useRef(null);
|
|
38
|
+
useHelper(editMode && isSelected ? lightRef : null, PointLightHelper, 0.5, color);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
var _a;
|
|
41
|
+
const shadow = (_a = lightRef.current) === null || _a === void 0 ? void 0 : _a.shadow;
|
|
42
|
+
if (!shadow)
|
|
43
|
+
return;
|
|
44
|
+
shadow.needsUpdate = true;
|
|
45
|
+
shadow.camera.updateProjectionMatrix();
|
|
46
|
+
}, [castShadow, shadowMapSize, shadowBias, shadowNormalBias, shadowAutoUpdate, shadowCameraNear, shadowCameraFar]);
|
|
47
|
+
return (_jsxs(_Fragment, { children: [_jsx("pointLight", { ref: lightRef, color: color, intensity: intensity, distance: distance, decay: decay, castShadow: castShadow, "shadow-mapSize-width": shadowMapSize, "shadow-mapSize-height": shadowMapSize, "shadow-bias": shadowBias, "shadow-normalBias": shadowNormalBias, "shadow-autoUpdate": shadowAutoUpdate, "shadow-camera-near": shadowCameraNear, "shadow-camera-far": shadowCameraFar }), editMode && isSelected ? (_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.2, 10, 8] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] })) : null, children] }));
|
|
48
|
+
}
|
|
49
|
+
const PointLightComponent = {
|
|
50
|
+
name: 'PointLight',
|
|
51
|
+
Editor: PointLightComponentEditor,
|
|
52
|
+
View: PointLightView,
|
|
53
|
+
defaultProperties: {},
|
|
54
|
+
};
|
|
55
|
+
export default PointLightComponent;
|
|
@@ -4,6 +4,7 @@ import { useThree } from '@react-three/fiber';
|
|
|
4
4
|
import { SoundPicker } from '../../assetviewer/page';
|
|
5
5
|
import { sound as soundManager } from '../../../helpers/SoundManager';
|
|
6
6
|
import { gameEvents } from '../GameEvents';
|
|
7
|
+
import { useSceneRuntime } from '../PrefabRoot';
|
|
7
8
|
import { BooleanField, FieldGroup, FieldRenderer, ListEditor, NumberField, SelectField, StringField } from './Input';
|
|
8
9
|
import { colors } from '../styles';
|
|
9
10
|
import { AudioListener } from 'three';
|
|
@@ -44,12 +45,12 @@ function getVolumeValue(properties) {
|
|
|
44
45
|
}
|
|
45
46
|
return Number.isFinite(properties.volume) ? Number(properties.volume) : 1;
|
|
46
47
|
}
|
|
47
|
-
function resolveClipPaths({
|
|
48
|
+
function resolveClipPaths({ clips, clipMode }) {
|
|
48
49
|
const normalizedClips = normalizeClips(clips);
|
|
49
50
|
if (normalizedClips.length > 0) {
|
|
50
51
|
return { paths: normalizedClips, mode: clipMode !== null && clipMode !== void 0 ? clipMode : 'random' };
|
|
51
52
|
}
|
|
52
|
-
return
|
|
53
|
+
return { paths: [], mode: 'single' };
|
|
53
54
|
}
|
|
54
55
|
function pickClip(paths, mode, sequenceIndexRef) {
|
|
55
56
|
if (paths.length <= 1 || mode === 'single') {
|
|
@@ -63,22 +64,27 @@ function pickClip(paths, mode, sequenceIndexRef) {
|
|
|
63
64
|
return paths[Math.floor(Math.random() * paths.length)];
|
|
64
65
|
}
|
|
65
66
|
function SoundComponentEditor({ component, onUpdate, basePath = '' }) {
|
|
66
|
-
const clips =
|
|
67
|
+
const clips = Array.isArray(component.properties.clips)
|
|
68
|
+
? component.properties.clips.map((clip) => typeof clip === 'string' ? clip : '')
|
|
69
|
+
: [];
|
|
67
70
|
const randomizePitch = Boolean(component.properties.randomizePitch);
|
|
68
71
|
const randomizeVolume = Boolean(component.properties.randomizeVolume);
|
|
69
72
|
const positional = Boolean(component.properties.positional);
|
|
73
|
+
const setClips = (nextClips) => {
|
|
74
|
+
onUpdate({ clips: nextClips });
|
|
75
|
+
};
|
|
70
76
|
const addClip = () => {
|
|
71
|
-
|
|
77
|
+
setClips([...clips, '']);
|
|
72
78
|
};
|
|
73
79
|
const updateClip = (index, nextPath) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
const nextClips = [...clips];
|
|
81
|
+
nextClips[index] = nextPath;
|
|
82
|
+
setClips(nextClips);
|
|
77
83
|
};
|
|
78
84
|
const removeClip = (index) => {
|
|
79
|
-
|
|
85
|
+
setClips(clips.filter((_, clipIndex) => clipIndex !== index));
|
|
80
86
|
};
|
|
81
|
-
return (_jsxs(FieldGroup, { children: [_jsx(
|
|
87
|
+
return (_jsxs(FieldGroup, { children: [_jsx(StringField, { name: "eventName", label: "Listen Event", values: component.properties, onChange: onUpdate, placeholder: "click" }), _jsx(FieldRenderer, { fields: [
|
|
82
88
|
{
|
|
83
89
|
name: 'clipMode',
|
|
84
90
|
label: 'Clip Mode',
|
|
@@ -117,7 +123,8 @@ function payloadMatchesNode(nodeId, payload) {
|
|
|
117
123
|
const hasEntityIds = ids.some(id => typeof id === 'string');
|
|
118
124
|
return hasEntityIds ? ids.includes(nodeId) : true;
|
|
119
125
|
}
|
|
120
|
-
function SoundComponentView({ properties, editMode, nodeId, children
|
|
126
|
+
function SoundComponentView({ properties, editMode, nodeId, children }) {
|
|
127
|
+
const { getSound } = useSceneRuntime();
|
|
121
128
|
const { camera } = useThree();
|
|
122
129
|
const { eventName, positional = false, refDistance = 1, maxDistance = 24, rolloffFactor = 1, distanceModel = 'inverse' } = properties;
|
|
123
130
|
const sequenceIndexRef = useRef(0);
|
|
@@ -170,7 +177,7 @@ function SoundComponentView({ properties, editMode, nodeId, children, loadedSoun
|
|
|
170
177
|
const pitch = getPitchValue(properties);
|
|
171
178
|
const volume = getVolumeValue(properties);
|
|
172
179
|
if (!positional) {
|
|
173
|
-
const loadedBuffer =
|
|
180
|
+
const loadedBuffer = getSound(clip);
|
|
174
181
|
if (loadedBuffer && !soundManager.hasBuffer(clip)) {
|
|
175
182
|
soundManager.setBuffer(clip, loadedBuffer);
|
|
176
183
|
}
|
|
@@ -183,7 +190,7 @@ function SoundComponentView({ properties, editMode, nodeId, children, loadedSoun
|
|
|
183
190
|
}
|
|
184
191
|
const audio = positionalAudioRef.current;
|
|
185
192
|
const listener = listenerRef.current;
|
|
186
|
-
const buffer =
|
|
193
|
+
const buffer = getSound(clip);
|
|
187
194
|
if (!audio || !listener || !buffer) {
|
|
188
195
|
return;
|
|
189
196
|
}
|
|
@@ -197,7 +204,7 @@ function SoundComponentView({ properties, editMode, nodeId, children, loadedSoun
|
|
|
197
204
|
audio.setVolume(volume);
|
|
198
205
|
audio.play();
|
|
199
206
|
});
|
|
200
|
-
}, [editMode, eventName,
|
|
207
|
+
}, [editMode, eventName, getSound, mode, nodeId, paths, positional, properties]);
|
|
201
208
|
return (_jsxs(_Fragment, { children: [positional && listenerRef.current ? _jsx("positionalAudio", { ref: positionalAudioRef, args: [listenerRef.current] }) : null, children] }));
|
|
202
209
|
}
|
|
203
210
|
const SoundComponent = {
|
|
@@ -205,7 +212,6 @@ const SoundComponent = {
|
|
|
205
212
|
Editor: SoundComponentEditor,
|
|
206
213
|
View: SoundComponentView,
|
|
207
214
|
defaultProperties: {
|
|
208
|
-
path: '',
|
|
209
215
|
eventName: '',
|
|
210
216
|
clips: [],
|
|
211
217
|
clipMode: 'single',
|
|
@@ -225,8 +231,6 @@ const SoundComponent = {
|
|
|
225
231
|
},
|
|
226
232
|
getAssetRefs: (properties) => {
|
|
227
233
|
const refs = [];
|
|
228
|
-
if (properties.path)
|
|
229
|
-
refs.push({ type: 'sound', path: properties.path });
|
|
230
234
|
if (Array.isArray(properties.clips)) {
|
|
231
235
|
properties.clips.forEach((clip) => {
|
|
232
236
|
if (typeof clip === 'string' && clip.trim().length > 0) {
|