react-three-game 0.0.93 → 0.0.95
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 +35 -77
- package/dist/index.d.ts +9 -6
- package/dist/index.js +5 -3
- package/dist/tools/prefabeditor/EditorTree.js +8 -12
- package/dist/tools/prefabeditor/EditorUI.js +4 -4
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +12 -33
- package/dist/tools/prefabeditor/PrefabEditor.js +137 -161
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +24 -12
- package/dist/tools/prefabeditor/PrefabRoot.js +117 -59
- package/dist/tools/prefabeditor/assetRuntime.d.ts +11 -17
- package/dist/tools/prefabeditor/assetRuntime.js +15 -15
- package/dist/tools/prefabeditor/components/CameraComponent.js +2 -2
- package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/Input.js +5 -9
- package/dist/tools/prefabeditor/components/MaterialComponent.d.ts +5 -2
- package/dist/tools/prefabeditor/components/MaterialComponent.js +40 -24
- package/dist/tools/prefabeditor/components/ModelComponent.js +3 -5
- package/dist/tools/prefabeditor/components/PointLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/SoundComponent.js +2 -2
- package/dist/tools/prefabeditor/components/SpotLightComponent.js +2 -2
- package/dist/tools/prefabeditor/components/SpriteComponent.d.ts +8 -0
- package/dist/tools/prefabeditor/components/SpriteComponent.js +27 -0
- package/dist/tools/prefabeditor/components/index.js +22 -14
- package/dist/tools/prefabeditor/prefab.d.ts +1 -2
- package/dist/tools/prefabeditor/prefab.js +2 -3
- package/dist/tools/prefabeditor/prefabStore.d.ts +0 -6
- package/dist/tools/prefabeditor/prefabStore.js +1 -33
- package/package.json +49 -49
|
@@ -15,7 +15,7 @@ import { extend } from '@react-three/fiber';
|
|
|
15
15
|
import { useFrame } from '@react-three/fiber';
|
|
16
16
|
import { FieldRenderer, Label, NumberInput } from './Input';
|
|
17
17
|
import { useAssetRuntime } from '../assetRuntime';
|
|
18
|
-
import { MeshBasicNodeMaterial, MeshStandardNodeMaterial } from 'three/webgpu';
|
|
18
|
+
import { MeshBasicNodeMaterial, MeshStandardNodeMaterial, SpriteNodeMaterial } from 'three/webgpu';
|
|
19
19
|
import { TexturePicker } from '../../assetviewer/page';
|
|
20
20
|
import { RepeatWrapping, ClampToEdgeWrapping, SRGBColorSpace, LinearSRGBColorSpace, NearestFilter, LinearFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapNearestFilter, LinearMipmapLinearFilter, FrontSide, BackSide, DoubleSide, } from 'three';
|
|
21
21
|
function Vector2Editor({ label, value, onChange, min, max, step, }) {
|
|
@@ -35,6 +35,7 @@ export function MaterialOverridesProvider({ overrides, children, }) {
|
|
|
35
35
|
extend({
|
|
36
36
|
MeshBasicNodeMaterial,
|
|
37
37
|
MeshStandardNodeMaterial,
|
|
38
|
+
SpriteNodeMaterial,
|
|
38
39
|
});
|
|
39
40
|
function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
40
41
|
var _a;
|
|
@@ -43,6 +44,7 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
43
44
|
const hasRepeat = component.properties.repeat;
|
|
44
45
|
const animateOffset = component.properties.animateOffset;
|
|
45
46
|
const isStandardMaterial = materialType === 'standard';
|
|
47
|
+
const isSpriteMaterial = materialType === 'sprite';
|
|
46
48
|
const fields = [
|
|
47
49
|
{
|
|
48
50
|
name: 'materialType',
|
|
@@ -51,13 +53,22 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
51
53
|
options: [
|
|
52
54
|
{ value: 'standard', label: 'Standard' },
|
|
53
55
|
{ value: 'basic', label: 'Basic' },
|
|
56
|
+
{ value: 'sprite', label: 'Sprite' },
|
|
54
57
|
],
|
|
55
58
|
},
|
|
56
59
|
{ name: 'color', type: 'color', label: 'Color' },
|
|
57
60
|
{ name: 'toneMapped', type: 'boolean', label: 'Tone Mapped' },
|
|
58
|
-
|
|
61
|
+
...(!isSpriteMaterial ? [
|
|
62
|
+
{ name: 'wireframe', type: 'boolean', label: 'Wireframe' },
|
|
63
|
+
] : []),
|
|
59
64
|
{ name: 'transparent', type: 'boolean', label: 'Transparent' },
|
|
60
65
|
{ name: 'opacity', type: 'number', label: 'Opacity', min: 0, max: 1, step: 0.01 },
|
|
66
|
+
...(isSpriteMaterial ? [
|
|
67
|
+
{ name: 'rotation', type: 'number', label: 'Rotation', step: 0.01 },
|
|
68
|
+
{ name: 'sizeAttenuation', type: 'boolean', label: 'Size Attenuation' },
|
|
69
|
+
{ name: 'depthTest', type: 'boolean', label: 'Depth Test' },
|
|
70
|
+
{ name: 'depthWrite', type: 'boolean', label: 'Depth Write' },
|
|
71
|
+
] : []),
|
|
61
72
|
...(isStandardMaterial ? [
|
|
62
73
|
{ name: 'metalness', type: 'number', label: 'Metalness', min: 0, max: 1, step: 0.01 },
|
|
63
74
|
{ name: 'roughness', type: 'number', label: 'Roughness', min: 0, max: 1, step: 0.01 },
|
|
@@ -65,16 +76,16 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
65
76
|
{ name: 'thickness', type: 'number', label: 'Thickness', min: 0, step: 0.1 },
|
|
66
77
|
{ name: 'ior', type: 'number', label: 'IOR (Index of Refraction)', min: 1, max: 2.333, step: 0.01 },
|
|
67
78
|
] : []),
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
...(!isSpriteMaterial ? [{
|
|
80
|
+
name: 'side',
|
|
81
|
+
type: 'select',
|
|
82
|
+
label: 'Side',
|
|
83
|
+
options: [
|
|
84
|
+
{ value: 'FrontSide', label: 'Front' },
|
|
85
|
+
{ value: 'BackSide', label: 'Back' },
|
|
86
|
+
{ value: 'DoubleSide', label: 'Double' },
|
|
87
|
+
],
|
|
88
|
+
}] : []),
|
|
78
89
|
{
|
|
79
90
|
name: 'texture',
|
|
80
91
|
type: 'custom',
|
|
@@ -103,13 +114,13 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
103
114
|
label: 'Speed (X, Y)',
|
|
104
115
|
render: ({ value, onChange }) => (_jsx(Vector2Editor, { label: "Speed", value: value, onChange: onChange, step: 0.01 })),
|
|
105
116
|
}] : []),
|
|
106
|
-
{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
...(component.properties.normalMapTexture ? [{
|
|
117
|
+
...(!isSpriteMaterial ? [{
|
|
118
|
+
name: 'normalMapTexture',
|
|
119
|
+
type: 'custom',
|
|
120
|
+
label: 'Normal Map',
|
|
121
|
+
render: ({ value, onChange }) => (_jsx(TexturePicker, { value: value, onChange: onChange, basePath: basePath })),
|
|
122
|
+
}] : []),
|
|
123
|
+
...(!isSpriteMaterial && component.properties.normalMapTexture ? [{
|
|
113
124
|
name: 'normalScale',
|
|
114
125
|
type: 'custom',
|
|
115
126
|
label: 'Normal Scale (X, Y)',
|
|
@@ -144,7 +155,7 @@ function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
144
155
|
}
|
|
145
156
|
// View for Material component
|
|
146
157
|
function MaterialComponentView({ properties: rawProps }) {
|
|
147
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
158
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
148
159
|
const { getTexture } = useAssetRuntime();
|
|
149
160
|
const properties = rawProps;
|
|
150
161
|
const materialType = (_a = properties === null || properties === void 0 ? void 0 : properties.materialType) !== null && _a !== void 0 ? _a : 'standard';
|
|
@@ -163,7 +174,7 @@ function MaterialComponentView({ properties: rawProps }) {
|
|
|
163
174
|
const normalMapTexture = normalMapTextureName ? (_c = getTexture(normalMapTextureName)) !== null && _c !== void 0 ? _c : undefined : undefined;
|
|
164
175
|
const materialSource = properties !== null && properties !== void 0 ? properties : {};
|
|
165
176
|
// Destructure all material props and separate custom texture handling props
|
|
166
|
-
const { texture: _texture, offset: _offset, repeat: _repeat, repeatCount: _repeatCount, animateOffset: _animateOffset, offsetSpeed: _offsetSpeed, generateMipmaps: _generateMipmaps, minFilter: _minFilter, magFilter: _magFilter, map: _map, materialType: _materialType, normalMapTexture: _normalMapTexture, normalScale: _normalScale, normalMap: _normalMap, side: sideProp } = materialSource, materialProps = __rest(materialSource, ["texture", "offset", "repeat", "repeatCount", "animateOffset", "offsetSpeed", "generateMipmaps", "minFilter", "magFilter", "map", "materialType", "normalMapTexture", "normalScale", "normalMap", "side"]);
|
|
177
|
+
const { texture: _texture, offset: _offset, repeat: _repeat, repeatCount: _repeatCount, animateOffset: _animateOffset, offsetSpeed: _offsetSpeed, generateMipmaps: _generateMipmaps, minFilter: _minFilter, magFilter: _magFilter, map: _map, materialType: _materialType, 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", "normalMapTexture", "normalScale", "normalMap", "rotation", "sizeAttenuation", "side"]);
|
|
167
178
|
const sideMap = { FrontSide, BackSide, DoubleSide };
|
|
168
179
|
const resolvedSide = sideProp ? ((_d = sideMap[sideProp]) !== null && _d !== void 0 ? _d : FrontSide) : FrontSide;
|
|
169
180
|
const minFilterMap = {
|
|
@@ -220,14 +231,18 @@ function MaterialComponentView({ properties: rawProps }) {
|
|
|
220
231
|
return t;
|
|
221
232
|
}, [normalMapTexture]);
|
|
222
233
|
if (!properties) {
|
|
223
|
-
return _jsx("meshStandardNodeMaterial", { color: "red", wireframe: true });
|
|
234
|
+
return _jsx("meshStandardNodeMaterial", { attach: "material", color: "red", wireframe: true });
|
|
224
235
|
}
|
|
225
236
|
const overrides = useMaterialOverrides();
|
|
226
237
|
const sharedProps = Object.assign(Object.assign({ map: finalTexture, side: resolvedSide }, materialProps), overrides);
|
|
227
238
|
if (materialType === 'basic') {
|
|
228
|
-
return _jsx("meshBasicNodeMaterial", Object.assign({}, sharedProps));
|
|
239
|
+
return _jsx("meshBasicNodeMaterial", Object.assign({ attach: "material" }, sharedProps));
|
|
240
|
+
}
|
|
241
|
+
if (materialType === 'sprite') {
|
|
242
|
+
const spriteTransparent = properties.transparent !== false;
|
|
243
|
+
return (_jsx("spriteNodeMaterial", Object.assign({ attach: "material", map: finalTexture, color: (_j = properties.color) !== null && _j !== void 0 ? _j : '#ffffff', opacity: (_k = properties.opacity) !== null && _k !== void 0 ? _k : 1, transparent: spriteTransparent, alphaTest: (_l = properties.alphaTest) !== null && _l !== void 0 ? _l : 0, depthTest: (_m = properties.depthTest) !== null && _m !== void 0 ? _m : false, depthWrite: (_o = properties.depthWrite) !== null && _o !== void 0 ? _o : false, toneMapped: (_p = properties.toneMapped) !== null && _p !== void 0 ? _p : true }, overrides, { rotation: rotation !== null && rotation !== void 0 ? rotation : 0, sizeAttenuation: sizeAttenuation !== null && sizeAttenuation !== void 0 ? sizeAttenuation : true })));
|
|
229
244
|
}
|
|
230
|
-
return (_jsx("meshStandardNodeMaterial", Object.assign({}, sharedProps, { normalMap: finalNormalMap, normalScale: finalNormalMap ? [(
|
|
245
|
+
return (_jsx("meshStandardNodeMaterial", Object.assign({ attach: "material" }, sharedProps, { normalMap: finalNormalMap, normalScale: finalNormalMap ? [(_q = normalScaleProp === null || normalScaleProp === void 0 ? void 0 : normalScaleProp[0]) !== null && _q !== void 0 ? _q : 1, (_r = normalScaleProp === null || normalScaleProp === void 0 ? void 0 : normalScaleProp[1]) !== null && _r !== void 0 ? _r : 1] : undefined })));
|
|
231
246
|
}
|
|
232
247
|
const MaterialComponent = {
|
|
233
248
|
name: 'Material',
|
|
@@ -240,6 +255,7 @@ const MaterialComponent = {
|
|
|
240
255
|
wireframe: false,
|
|
241
256
|
transparent: false,
|
|
242
257
|
opacity: 1,
|
|
258
|
+
sizeAttenuation: true,
|
|
243
259
|
offset: [0, 0],
|
|
244
260
|
animateOffset: false,
|
|
245
261
|
offsetSpeed: [0, 0],
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { ModelPicker } from '../../assetviewer/page';
|
|
3
|
-
import {
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
4
|
import { BooleanField, FieldGroup, Label, ListEditor, NumberInput, SelectInput, StringField } from './Input';
|
|
5
5
|
import { useAssetRuntime } from '../assetRuntime';
|
|
6
|
-
import {
|
|
6
|
+
import { useEditorContext } from '../PrefabEditor';
|
|
7
7
|
import { getRepeatAxesFromModelProperties, normalizeRepeatAxes } from '../InstanceProvider';
|
|
8
8
|
import { colors, ui } from '../styles';
|
|
9
9
|
const AXIS_OPTIONS = [
|
|
@@ -39,9 +39,7 @@ function RepeatAxisEditor({ axes, onChange, positionSnap, }) {
|
|
|
39
39
|
} }));
|
|
40
40
|
}
|
|
41
41
|
function ModelComponentEditor({ component, node, onUpdate, basePath = "" }) {
|
|
42
|
-
|
|
43
|
-
const editorContext = useContext(EditorContext);
|
|
44
|
-
const positionSnap = (_a = editorContext === null || editorContext === void 0 ? void 0 : editorContext.positionSnap) !== null && _a !== void 0 ? _a : 0.5;
|
|
42
|
+
const { positionSnap } = useEditorContext();
|
|
45
43
|
const repeatAxes = getRepeatAxesFromModelProperties(component.properties);
|
|
46
44
|
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: "emitClickEvent", label: "Emit Click Event", values: component.properties, onChange: onUpdate, fallback: false }), component.properties.emitClickEvent ? (_jsx(StringField, { name: "clickEventName", label: "Click Event Name", values: component.properties, onChange: onUpdate, placeholder: "node:click" })) : null] })) : null, 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 }))] }))] }));
|
|
47
45
|
}
|
|
@@ -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 { useHelper } from '@react-three/drei';
|
|
4
4
|
import { PointLightHelper } from 'three';
|
|
5
|
-
import {
|
|
5
|
+
import { useNode } from '../assetRuntime';
|
|
6
6
|
import { BooleanField, ColorField, NumberField } from './Input';
|
|
7
7
|
import { LightSection, ShadowBiasField, mergeWithDefaults } from './lightUtils';
|
|
8
8
|
const pointLightDefaults = {
|
|
@@ -23,7 +23,7 @@ function PointLightComponentEditor({ component, onUpdate }) {
|
|
|
23
23
|
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] })] }));
|
|
24
24
|
}
|
|
25
25
|
function PointLightView({ properties, children }) {
|
|
26
|
-
const { editMode, isSelected } =
|
|
26
|
+
const { editMode, isSelected } = useNode();
|
|
27
27
|
const merged = mergeWithDefaults(pointLightDefaults, properties);
|
|
28
28
|
const color = merged.color;
|
|
29
29
|
const intensity = merged.intensity;
|
|
@@ -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,
|
|
5
|
+
import { 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,7 +124,7 @@ function SoundComponentEditor({ component, onUpdate, basePath = '' }) {
|
|
|
124
124
|
}
|
|
125
125
|
function SoundComponentView({ properties, children }) {
|
|
126
126
|
const { getSound } = useAssetRuntime();
|
|
127
|
-
const { editMode, nodeId } =
|
|
127
|
+
const { editMode, nodeId } = useNode();
|
|
128
128
|
const { camera } = useThree();
|
|
129
129
|
const { eventName, autoplay = false, positional = false, refDistance = 1, maxDistance = 24, rolloffFactor = 1, distanceModel = 'inverse' } = properties;
|
|
130
130
|
const sequenceIndexRef = useRef(0);
|
|
@@ -3,7 +3,7 @@ import { useHelper } from "@react-three/drei";
|
|
|
3
3
|
import { useRef, useEffect } from "react";
|
|
4
4
|
import { BooleanField, ColorField, Label, NumberField, Vector3Input } from "./Input";
|
|
5
5
|
import { SpotLightHelper } from "three";
|
|
6
|
-
import { useAssetRuntime,
|
|
6
|
+
import { useAssetRuntime, useNode } from "../assetRuntime";
|
|
7
7
|
import { useFrame } from "@react-three/fiber";
|
|
8
8
|
import { TexturePicker } from "../../assetviewer/page";
|
|
9
9
|
import { LightSection, ShadowBiasField, mergeWithDefaults } from "./lightUtils";
|
|
@@ -31,7 +31,7 @@ function SpotLightComponentEditor({ component, onUpdate, basePath = "" }) {
|
|
|
31
31
|
function SpotLightView({ properties, children }) {
|
|
32
32
|
var _a;
|
|
33
33
|
const { getTexture } = useAssetRuntime();
|
|
34
|
-
const { editMode, isSelected } =
|
|
34
|
+
const { editMode, isSelected } = useNode();
|
|
35
35
|
const merged = mergeWithDefaults(spotLightDefaults, properties);
|
|
36
36
|
const color = merged.color;
|
|
37
37
|
const intensity = merged.intensity;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { BooleanField, FieldRenderer, NumberInput, StringField } from './Input';
|
|
3
|
+
function Vector2Editor({ value, onChange, min, max, step, }) {
|
|
4
|
+
var _a, _b;
|
|
5
|
+
return (_jsxs("div", { style: { display: 'flex', gap: 2 }, children: [_jsx(NumberInput, { value: (_a = value === null || value === void 0 ? void 0 : value[0]) !== null && _a !== void 0 ? _a : 0, onChange: x => { var _a; return onChange([x, (_a = value === null || value === void 0 ? void 0 : value[1]) !== null && _a !== void 0 ? _a : 0]); }, min: min, max: max, step: step, style: { width: '100%', minWidth: 0, boxSizing: 'border-box' } }), _jsx(NumberInput, { value: (_b = value === null || value === void 0 ? void 0 : value[1]) !== null && _b !== void 0 ? _b : 0, onChange: y => { var _a; return onChange([(_a = value === null || value === void 0 ? void 0 : value[0]) !== null && _a !== void 0 ? _a : 0, y]); }, min: min, max: max, step: step, style: { width: '100%', minWidth: 0, boxSizing: 'border-box' } })] }));
|
|
6
|
+
}
|
|
7
|
+
function SpriteComponentEditor({ component, onUpdate, }) {
|
|
8
|
+
const fields = [
|
|
9
|
+
{
|
|
10
|
+
name: 'center',
|
|
11
|
+
type: 'custom',
|
|
12
|
+
label: 'Center',
|
|
13
|
+
render: ({ value, onChange }) => (_jsx(Vector2Editor, { value: value, onChange: onChange, min: 0, max: 1, step: 0.01 })),
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
return (_jsxs(_Fragment, { children: [_jsx(FieldRenderer, { fields: fields, values: component.properties, onChange: onUpdate }), _jsxs("div", { style: { marginTop: 8 }, children: [_jsx(BooleanField, { name: "emitClickEvent", label: "Emit Click Event", values: component.properties, onChange: onUpdate, fallback: false }), component.properties.emitClickEvent ? (_jsx(StringField, { name: "clickEventName", label: "Click Event Name", values: component.properties, onChange: onUpdate, fallback: "node:click" })) : null] })] }));
|
|
17
|
+
}
|
|
18
|
+
const SpriteComponent = {
|
|
19
|
+
name: 'Sprite',
|
|
20
|
+
Editor: SpriteComponentEditor,
|
|
21
|
+
defaultProperties: {
|
|
22
|
+
center: [0.5, 0.5],
|
|
23
|
+
emitClickEvent: false,
|
|
24
|
+
clickEventName: 'node:click',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default SpriteComponent;
|
|
@@ -1,28 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
1
|
+
// biome-ignore assist/source/organizeImports: <in order of display in the editor>
|
|
2
|
+
import TransformComponent from "./TransformComponent";
|
|
3
|
+
import GeometryComponent from "./GeometryComponent";
|
|
4
|
+
import BufferGeometryComponent from "./BufferGeometryComponent";
|
|
5
|
+
import ModelComponent from "./ModelComponent";
|
|
6
|
+
import SpriteComponent from "./SpriteComponent";
|
|
7
|
+
import TextComponent from "./TextComponent";
|
|
8
|
+
import MaterialComponent from "./MaterialComponent";
|
|
9
|
+
import SpotLightComponent from "./SpotLightComponent";
|
|
10
|
+
import PointLightComponent from "./PointLightComponent";
|
|
11
|
+
import DirectionalLightComponent from "./DirectionalLightComponent";
|
|
12
|
+
import AmbientLightComponent from "./AmbientLightComponent";
|
|
13
|
+
import EnvironmentComponent from "./EnvironmentComponent";
|
|
14
|
+
import CameraComponent from "./CameraComponent";
|
|
15
|
+
import SoundComponent from "./SoundComponent";
|
|
16
|
+
import DataComponent from "./DataComponent";
|
|
17
|
+
// this controls the order of components in the editor, and also which components are available to add
|
|
15
18
|
export const builtinComponents = [
|
|
16
19
|
TransformComponent,
|
|
20
|
+
// geometry components
|
|
17
21
|
GeometryComponent,
|
|
18
22
|
BufferGeometryComponent,
|
|
19
23
|
ModelComponent,
|
|
24
|
+
SpriteComponent,
|
|
20
25
|
TextComponent,
|
|
26
|
+
// material components
|
|
21
27
|
MaterialComponent,
|
|
28
|
+
// light components
|
|
22
29
|
SpotLightComponent,
|
|
23
30
|
PointLightComponent,
|
|
24
31
|
DirectionalLightComponent,
|
|
25
32
|
AmbientLightComponent,
|
|
33
|
+
// other components
|
|
26
34
|
EnvironmentComponent,
|
|
27
35
|
CameraComponent,
|
|
28
36
|
SoundComponent,
|
|
@@ -8,7 +8,6 @@ export interface PrefabState {
|
|
|
8
8
|
nodesById: Record<string, PrefabNodeRecord>;
|
|
9
9
|
childIdsById: Record<string, string[]>;
|
|
10
10
|
parentIdById: Record<string, string | null>;
|
|
11
|
-
revision: number;
|
|
12
11
|
assetManifestKey: string;
|
|
13
12
|
assetRefCounts: PrefabAssetRefCounts;
|
|
14
13
|
}
|
|
@@ -25,7 +24,7 @@ export declare function createEmptyNode(name?: string): GameObject;
|
|
|
25
24
|
export declare function createEmptyPrefab(): Prefab;
|
|
26
25
|
export declare function createModelNode(filename: string, name?: string): GameObject;
|
|
27
26
|
export declare function createImageNode(texturePath: string, name?: string): GameObject;
|
|
28
|
-
export declare function normalizePrefab(prefab: Prefab
|
|
27
|
+
export declare function normalizePrefab(prefab: Prefab): PrefabState;
|
|
29
28
|
export declare function createPrefabPatch(state: PrefabState, patch: Partial<PrefabState>, nextAssetRefCounts?: PrefabAssetRefCounts): Partial<PrefabState>;
|
|
30
29
|
export declare function denormalizePrefab(state: Pick<PrefabState, 'prefabId' | 'prefabName' | 'rootId' | 'nodesById' | 'childIdsById'>): Prefab;
|
|
31
30
|
export declare function collectSubtreeIds(id: string, childIdsById: Record<string, string[]>): string[];
|
|
@@ -132,7 +132,7 @@ export function createImageNode(texturePath, name) {
|
|
|
132
132
|
},
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
-
export function normalizePrefab(prefab
|
|
135
|
+
export function normalizePrefab(prefab) {
|
|
136
136
|
const nodesById = {};
|
|
137
137
|
const childIdsById = {};
|
|
138
138
|
const parentIdById = {};
|
|
@@ -145,14 +145,13 @@ export function normalizePrefab(prefab, revision = 0) {
|
|
|
145
145
|
nodesById,
|
|
146
146
|
childIdsById,
|
|
147
147
|
parentIdById,
|
|
148
|
-
revision,
|
|
149
148
|
assetManifestKey: getAssetManifestKey(assetRefCounts),
|
|
150
149
|
assetRefCounts,
|
|
151
150
|
};
|
|
152
151
|
}
|
|
153
152
|
export function createPrefabPatch(state, patch, nextAssetRefCounts = state.assetRefCounts) {
|
|
154
153
|
const assetRefsChanged = nextAssetRefCounts !== state.assetRefCounts;
|
|
155
|
-
return Object.assign(Object.assign(
|
|
154
|
+
return Object.assign(Object.assign({}, patch), (assetRefsChanged ? {
|
|
156
155
|
assetRefCounts: nextAssetRefCounts,
|
|
157
156
|
assetManifestKey: getAssetManifestKey(nextAssetRefCounts),
|
|
158
157
|
} : null));
|
|
@@ -5,14 +5,9 @@ import { denormalizePrefab, PrefabState, PrefabNodeRecord } from "./prefab";
|
|
|
5
5
|
export interface PrefabStoreState extends PrefabState {
|
|
6
6
|
replacePrefab: (prefab: Prefab) => void;
|
|
7
7
|
updateNode: (id: string, update: (node: PrefabNodeRecord) => PrefabNodeRecord) => void;
|
|
8
|
-
updateNodes: (updates: Array<{
|
|
9
|
-
id: string;
|
|
10
|
-
update: (node: PrefabNodeRecord) => PrefabNodeRecord;
|
|
11
|
-
}>) => void;
|
|
12
8
|
addChild: (parentId: string, node: GameObject) => void;
|
|
13
9
|
deleteNode: (id: string) => void;
|
|
14
10
|
duplicateNode: (id: string) => string | null;
|
|
15
|
-
toggleNodeFlag: (id: string, key: "disabled" | "locked") => void;
|
|
16
11
|
moveNode: (draggedId: string, targetId: string, position: "before" | "inside") => void;
|
|
17
12
|
}
|
|
18
13
|
export type PrefabStoreApi = StoreApi<PrefabStoreState>;
|
|
@@ -21,7 +16,6 @@ export declare function PrefabStoreProvider({ store, children, }: {
|
|
|
21
16
|
children: ReactNode;
|
|
22
17
|
}): import("react").FunctionComponentElement<import("react").ProviderProps<PrefabStoreApi | null>>;
|
|
23
18
|
export declare function usePrefabStoreApi(): PrefabStoreApi;
|
|
24
|
-
export declare function useOptionalPrefabStoreApi(): PrefabStoreApi | null;
|
|
25
19
|
export declare function usePrefabStore<T>(selector: (state: PrefabStoreState) => T): T;
|
|
26
20
|
export declare function usePrefabRootId(): string;
|
|
27
21
|
export declare function usePrefabNode(nodeId: string | null | undefined): PrefabNodeRecord | null;
|
|
@@ -15,9 +15,6 @@ export function usePrefabStoreApi() {
|
|
|
15
15
|
}
|
|
16
16
|
return store;
|
|
17
17
|
}
|
|
18
|
-
export function useOptionalPrefabStoreApi() {
|
|
19
|
-
return useContext(PrefabStoreContext);
|
|
20
|
-
}
|
|
21
18
|
export function usePrefabStore(selector) {
|
|
22
19
|
return useStore(usePrefabStoreApi(), selector);
|
|
23
20
|
}
|
|
@@ -32,7 +29,7 @@ export function usePrefabChildIds(nodeId) {
|
|
|
32
29
|
}
|
|
33
30
|
export function createPrefabStore(prefab) {
|
|
34
31
|
return createStore()(subscribeWithSelector((set, get) => (Object.assign(Object.assign({}, normalizePrefab(prefab)), { replacePrefab: (nextPrefab) => {
|
|
35
|
-
set(normalizePrefab(nextPrefab
|
|
32
|
+
set(normalizePrefab(nextPrefab));
|
|
36
33
|
}, updateNode: (id, update) => {
|
|
37
34
|
const state = get();
|
|
38
35
|
const node = state.nodesById[id];
|
|
@@ -45,26 +42,6 @@ export function createPrefabStore(prefab) {
|
|
|
45
42
|
set(createPrefabPatch(state, {
|
|
46
43
|
nodesById: Object.assign(Object.assign({}, state.nodesById), { [id]: nextNode }),
|
|
47
44
|
}, nextAssetRefCounts));
|
|
48
|
-
}, updateNodes: (updates) => {
|
|
49
|
-
if (updates.length === 0)
|
|
50
|
-
return;
|
|
51
|
-
const state = get();
|
|
52
|
-
let nextNodesById = null;
|
|
53
|
-
let nextAssetRefCounts = state.assetRefCounts;
|
|
54
|
-
for (const { id, update } of updates) {
|
|
55
|
-
const currentNode = (nextNodesById !== null && nextNodesById !== void 0 ? nextNodesById : state.nodesById)[id];
|
|
56
|
-
if (!currentNode)
|
|
57
|
-
continue;
|
|
58
|
-
const nextNode = update(currentNode);
|
|
59
|
-
if (nextNode === currentNode)
|
|
60
|
-
continue;
|
|
61
|
-
nextNodesById !== null && nextNodesById !== void 0 ? nextNodesById : (nextNodesById = Object.assign({}, state.nodesById));
|
|
62
|
-
nextNodesById[id] = nextNode;
|
|
63
|
-
nextAssetRefCounts = updateAssetRefsForNodeChange(nextAssetRefCounts, currentNode, nextNode);
|
|
64
|
-
}
|
|
65
|
-
if (!nextNodesById)
|
|
66
|
-
return;
|
|
67
|
-
set(createPrefabPatch(state, { nodesById: nextNodesById }, nextAssetRefCounts));
|
|
68
45
|
}, addChild: (parentId, node) => {
|
|
69
46
|
var _a;
|
|
70
47
|
const state = get();
|
|
@@ -152,15 +129,6 @@ export function createPrefabStore(prefab) {
|
|
|
152
129
|
parentIdById: nextParentIdById,
|
|
153
130
|
}, nextAssetRefCounts));
|
|
154
131
|
return duplicatedRootId;
|
|
155
|
-
}, toggleNodeFlag: (id, key) => {
|
|
156
|
-
const state = get();
|
|
157
|
-
const node = state.nodesById[id];
|
|
158
|
-
if (!node)
|
|
159
|
-
return;
|
|
160
|
-
const nextNode = Object.assign(Object.assign({}, node), { [key]: !node[key] });
|
|
161
|
-
set(createPrefabPatch(state, {
|
|
162
|
-
nodesById: Object.assign(Object.assign({}, state.nodesById), { [id]: nextNode }),
|
|
163
|
-
}));
|
|
164
132
|
}, moveNode: (draggedId, targetId, position) => {
|
|
165
133
|
var _a, _b, _c;
|
|
166
134
|
const state = get();
|
package/package.json
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
2
|
+
"name": "react-three-game",
|
|
3
|
+
"version": "0.0.95",
|
|
4
|
+
"description": "high performance 3D game engine built in React",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"clean": "rm -rf dist",
|
|
15
|
+
"watch": "npm run clean && tsc --watch",
|
|
16
|
+
"dev": "concurrently \"npm run watch\" \"cd docs && npm run dev\"",
|
|
17
|
+
"build": "npm run clean && tsc",
|
|
18
|
+
"release": "npm run build && npm publish --access public"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [],
|
|
21
|
+
"author": "prnth",
|
|
22
|
+
"license": "VPL",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"workspaces": [
|
|
25
|
+
"docs"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@react-three/drei": ">=10.0.0",
|
|
29
|
+
"@react-three/fiber": ">=9.0.0",
|
|
30
|
+
"react": ">=18.0.0",
|
|
31
|
+
"react-dom": ">=18.0.0",
|
|
32
|
+
"three": ">=0.182.0",
|
|
33
|
+
"three-text": ">=0.4.4"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@react-three/drei": "^10.7.7",
|
|
37
|
+
"@react-three/fiber": "^9.5.0",
|
|
38
|
+
"@types/react": "^19.2.9",
|
|
39
|
+
"@types/react-dom": "^19.2.3",
|
|
40
|
+
"@types/three": "^0.182.0",
|
|
41
|
+
"concurrently": "^9.2.1",
|
|
42
|
+
"react": "^19.2.4",
|
|
43
|
+
"react-dom": "^19.2.4",
|
|
44
|
+
"three": "^0.184.0",
|
|
45
|
+
"typescript": "^5.9.3",
|
|
46
|
+
"vite": "^7.3.1"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"zustand": "^5.0.12"
|
|
50
|
+
}
|
|
51
51
|
}
|