react-three-game 0.0.39 → 0.0.41

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.
Files changed (83) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/README.md +17 -0
  3. package/dist/index.umd.js +438 -0
  4. package/package.json +6 -3
  5. package/src/shared/GameCanvas.tsx +0 -2
  6. package/src/tools/assetviewer/page.tsx +31 -26
  7. package/src/tools/dragdrop/DragDropLoader.tsx +0 -1
  8. package/src/tools/prefabeditor/PrefabEditor.tsx +0 -2
  9. package/src/tools/prefabeditor/PrefabRoot.tsx +0 -2
  10. package/src/tools/prefabeditor/components/MaterialComponent.tsx +25 -9
  11. package/src/tools/prefabeditor/components/ModelComponent.tsx +25 -10
  12. package/src/tools/prefabeditor/styles.ts +0 -1
  13. package/vite.config.ts +34 -0
  14. package/dist/helpers/SoundManager.d.ts +0 -35
  15. package/dist/helpers/SoundManager.js +0 -93
  16. package/dist/helpers/index.d.ts +0 -35
  17. package/dist/helpers/index.js +0 -44
  18. package/dist/index.d.ts +0 -14
  19. package/dist/index.js +0 -14
  20. package/dist/shared/GameCanvas.d.ts +0 -9
  21. package/dist/shared/GameCanvas.js +0 -48
  22. package/dist/shared/extend-three.d.ts +0 -1
  23. package/dist/shared/extend-three.js +0 -13
  24. package/dist/tools/assetviewer/page.d.ts +0 -23
  25. package/dist/tools/assetviewer/page.js +0 -159
  26. package/dist/tools/dragdrop/DragDropLoader.d.ts +0 -9
  27. package/dist/tools/dragdrop/DragDropLoader.js +0 -79
  28. package/dist/tools/dragdrop/modelLoader.d.ts +0 -7
  29. package/dist/tools/dragdrop/modelLoader.js +0 -52
  30. package/dist/tools/dragdrop/page.d.ts +0 -1
  31. package/dist/tools/dragdrop/page.js +0 -11
  32. package/dist/tools/loading/GameWithLoader.d.ts +0 -6
  33. package/dist/tools/loading/GameWithLoader.js +0 -8
  34. package/dist/tools/loading/loading.d.ts +0 -2
  35. package/dist/tools/loading/loading.js +0 -38
  36. package/dist/tools/prefabeditor/EditorContext.d.ts +0 -11
  37. package/dist/tools/prefabeditor/EditorContext.js +0 -9
  38. package/dist/tools/prefabeditor/EditorTree.d.ts +0 -12
  39. package/dist/tools/prefabeditor/EditorTree.js +0 -150
  40. package/dist/tools/prefabeditor/EditorUI.d.ts +0 -14
  41. package/dist/tools/prefabeditor/EditorUI.js +0 -71
  42. package/dist/tools/prefabeditor/EventSystem.d.ts +0 -7
  43. package/dist/tools/prefabeditor/EventSystem.js +0 -23
  44. package/dist/tools/prefabeditor/ExportHelper.d.ts +0 -7
  45. package/dist/tools/prefabeditor/ExportHelper.js +0 -55
  46. package/dist/tools/prefabeditor/InstanceProvider.d.ts +0 -30
  47. package/dist/tools/prefabeditor/InstanceProvider.js +0 -254
  48. package/dist/tools/prefabeditor/PrefabEditor.d.ts +0 -16
  49. package/dist/tools/prefabeditor/PrefabEditor.js +0 -141
  50. package/dist/tools/prefabeditor/PrefabRoot.d.ts +0 -28
  51. package/dist/tools/prefabeditor/PrefabRoot.js +0 -294
  52. package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +0 -18
  53. package/dist/tools/prefabeditor/components/ComponentRegistry.js +0 -13
  54. package/dist/tools/prefabeditor/components/DirectionalLightComponent.d.ts +0 -3
  55. package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +0 -78
  56. package/dist/tools/prefabeditor/components/GeometryComponent.d.ts +0 -3
  57. package/dist/tools/prefabeditor/components/GeometryComponent.js +0 -66
  58. package/dist/tools/prefabeditor/components/Input.d.ts +0 -20
  59. package/dist/tools/prefabeditor/components/Input.js +0 -129
  60. package/dist/tools/prefabeditor/components/MaterialComponent.d.ts +0 -3
  61. package/dist/tools/prefabeditor/components/MaterialComponent.js +0 -96
  62. package/dist/tools/prefabeditor/components/ModelComponent.d.ts +0 -3
  63. package/dist/tools/prefabeditor/components/ModelComponent.js +0 -53
  64. package/dist/tools/prefabeditor/components/PhysicsComponent.d.ts +0 -10
  65. package/dist/tools/prefabeditor/components/PhysicsComponent.js +0 -33
  66. package/dist/tools/prefabeditor/components/RotatorComponent.d.ts +0 -3
  67. package/dist/tools/prefabeditor/components/RotatorComponent.js +0 -42
  68. package/dist/tools/prefabeditor/components/SpotLightComponent.d.ts +0 -3
  69. package/dist/tools/prefabeditor/components/SpotLightComponent.js +0 -49
  70. package/dist/tools/prefabeditor/components/TransformComponent.d.ts +0 -3
  71. package/dist/tools/prefabeditor/components/TransformComponent.js +0 -42
  72. package/dist/tools/prefabeditor/components/index.d.ts +0 -2
  73. package/dist/tools/prefabeditor/components/index.js +0 -16
  74. package/dist/tools/prefabeditor/hooks/useModelLoader.d.ts +0 -10
  75. package/dist/tools/prefabeditor/hooks/useModelLoader.js +0 -40
  76. package/dist/tools/prefabeditor/page.d.ts +0 -1
  77. package/dist/tools/prefabeditor/page.js +0 -5
  78. package/dist/tools/prefabeditor/styles.d.ts +0 -1809
  79. package/dist/tools/prefabeditor/styles.js +0 -168
  80. package/dist/tools/prefabeditor/types.d.ts +0 -19
  81. package/dist/tools/prefabeditor/types.js +0 -1
  82. package/dist/tools/prefabeditor/utils.d.ts +0 -26
  83. package/dist/tools/prefabeditor/utils.js +0 -131
@@ -1,96 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { TextureListViewer } from '../../assetviewer/page';
3
- import { useEffect, useState } from 'react';
4
- import { Input, Label } from './Input';
5
- import { useMemo } from 'react';
6
- import { DoubleSide, RepeatWrapping, ClampToEdgeWrapping, SRGBColorSpace, NearestFilter, LinearFilter, NearestMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapNearestFilter, LinearMipmapLinearFilter } from 'three';
7
- function MaterialComponentEditor({ component, onUpdate, basePath = "" }) {
8
- var _a, _b, _c, _d;
9
- const [textureFiles, setTextureFiles] = useState([]);
10
- useEffect(() => {
11
- const base = basePath ? `${basePath}/` : '';
12
- fetch(`/${base}textures/manifest.json`)
13
- .then(r => r.json())
14
- .then(data => setTextureFiles(Array.isArray(data) ? data : data.files || []))
15
- .catch(console.error);
16
- }, [basePath]);
17
- const textInputStyle = {
18
- flex: 1,
19
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
20
- border: '1px solid rgba(34, 211, 238, 0.3)',
21
- padding: '2px 4px',
22
- fontSize: '10px',
23
- color: 'rgba(165, 243, 252, 1)',
24
- fontFamily: 'monospace',
25
- outline: 'none',
26
- };
27
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsxs("div", { children: [_jsx(Label, { children: "Color" }), _jsxs("div", { style: { display: 'flex', gap: 2 }, children: [_jsx("input", { type: "color", style: { height: 20, width: 20, backgroundColor: 'transparent', border: 'none', cursor: 'pointer' }, value: component.properties.color, onChange: e => onUpdate({ color: e.target.value }) }), _jsx("input", { type: "text", style: textInputStyle, value: component.properties.color, onChange: e => onUpdate({ color: e.target.value }) })] })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 4 }, children: [_jsx("input", { type: "checkbox", style: { width: 12, height: 12 }, checked: component.properties.wireframe || false, onChange: e => onUpdate({ wireframe: e.target.checked }) }), _jsx("label", { style: { fontSize: '9px', color: 'rgba(34, 211, 238, 0.6)' }, children: "Wireframe" })] }), _jsxs("div", { children: [_jsx(Label, { children: "Texture" }), _jsx("div", { style: { maxHeight: 128, overflowY: 'auto' }, children: _jsx(TextureListViewer, { files: textureFiles, selected: component.properties.texture || undefined, onSelect: file => onUpdate({ texture: file }), basePath: basePath }) })] }), component.properties.texture && (_jsxs("div", { style: { borderTop: '1px solid rgba(34, 211, 238, 0.2)', paddingTop: 4, marginTop: 4 }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 4, marginBottom: 4 }, children: [_jsx("input", { type: "checkbox", style: { width: 12, height: 12 }, checked: component.properties.repeat || false, onChange: e => onUpdate({ repeat: e.target.checked }) }), _jsx("label", { style: { fontSize: '9px', color: 'rgba(34, 211, 238, 0.6)' }, children: "Repeat Texture" })] }), component.properties.repeat && (_jsxs("div", { children: [_jsx(Label, { children: "Repeat (X, Y)" }), _jsxs("div", { style: { display: 'flex', gap: 2 }, children: [_jsx(Input, { value: (_b = (_a = component.properties.repeatCount) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 1, onChange: value => {
28
- var _a, _b;
29
- const y = (_b = (_a = component.properties.repeatCount) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : 1;
30
- onUpdate({ repeatCount: [value, y] });
31
- } }), _jsx(Input, { value: (_d = (_c = component.properties.repeatCount) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : 1, onChange: value => {
32
- var _a, _b;
33
- const x = (_b = (_a = component.properties.repeatCount) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 1;
34
- onUpdate({ repeatCount: [x, value] });
35
- } })] })] })), _jsxs("div", { style: { marginTop: 4 }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 4, marginBottom: 4 }, children: [_jsx("input", { type: "checkbox", style: { width: 12, height: 12 }, checked: component.properties.generateMipmaps !== false, onChange: e => onUpdate({ generateMipmaps: e.target.checked }) }), _jsx("label", { style: { fontSize: '9px', color: 'rgba(34, 211, 238, 0.6)' }, children: "Generate Mipmaps" })] }), _jsxs("div", { children: [_jsx(Label, { children: "Min Filter" }), _jsxs("select", { style: Object.assign(Object.assign({}, textInputStyle), { width: '100%', cursor: 'pointer' }), value: component.properties.minFilter || 'LinearMipmapLinearFilter', onChange: e => onUpdate({ minFilter: e.target.value }), children: [_jsx("option", { value: "NearestFilter", children: "Nearest" }), _jsx("option", { value: "NearestMipmapNearestFilter", children: "Nearest Mipmap Nearest" }), _jsx("option", { value: "NearestMipmapLinearFilter", children: "Nearest Mipmap Linear" }), _jsx("option", { value: "LinearFilter", children: "Linear" }), _jsx("option", { value: "LinearMipmapNearestFilter", children: "Linear Mipmap Nearest" }), _jsx("option", { value: "LinearMipmapLinearFilter", children: "Linear Mipmap Linear (Default)" })] })] }), _jsxs("div", { style: { marginTop: 4 }, children: [_jsx(Label, { children: "Mag Filter" }), _jsxs("select", { style: Object.assign(Object.assign({}, textInputStyle), { width: '100%', cursor: 'pointer' }), value: component.properties.magFilter || 'LinearFilter', onChange: e => onUpdate({ magFilter: e.target.value }), children: [_jsx("option", { value: "NearestFilter", children: "Nearest" }), _jsx("option", { value: "LinearFilter", children: "Linear (Default)" })] })] })] })] }))] }));
36
- }
37
- ;
38
- // View for Material component
39
- function MaterialComponentView({ properties, loadedTextures }) {
40
- var _a;
41
- const textureName = properties === null || properties === void 0 ? void 0 : properties.texture;
42
- const repeat = properties === null || properties === void 0 ? void 0 : properties.repeat;
43
- const repeatCount = properties === null || properties === void 0 ? void 0 : properties.repeatCount;
44
- const generateMipmaps = (properties === null || properties === void 0 ? void 0 : properties.generateMipmaps) !== false;
45
- const minFilter = (properties === null || properties === void 0 ? void 0 : properties.minFilter) || 'LinearMipmapLinearFilter';
46
- const magFilter = (properties === null || properties === void 0 ? void 0 : properties.magFilter) || 'LinearFilter';
47
- const texture = textureName && loadedTextures ? loadedTextures[textureName] : undefined;
48
- const minFilterMap = {
49
- NearestFilter,
50
- LinearFilter,
51
- NearestMipmapNearestFilter,
52
- NearestMipmapLinearFilter,
53
- LinearMipmapNearestFilter,
54
- LinearMipmapLinearFilter
55
- };
56
- const magFilterMap = {
57
- NearestFilter,
58
- LinearFilter
59
- };
60
- const finalTexture = useMemo(() => {
61
- var _a, _b;
62
- if (!texture)
63
- return undefined;
64
- const t = texture.clone();
65
- if (repeat) {
66
- t.wrapS = t.wrapT = RepeatWrapping;
67
- if (repeatCount)
68
- t.repeat.set(repeatCount[0], repeatCount[1]);
69
- }
70
- else {
71
- t.wrapS = t.wrapT = ClampToEdgeWrapping;
72
- t.repeat.set(1, 1);
73
- }
74
- t.colorSpace = SRGBColorSpace;
75
- t.generateMipmaps = generateMipmaps;
76
- t.minFilter = (_a = minFilterMap[minFilter]) !== null && _a !== void 0 ? _a : LinearMipmapLinearFilter;
77
- t.magFilter = (_b = magFilterMap[magFilter]) !== null && _b !== void 0 ? _b : LinearFilter;
78
- t.needsUpdate = true;
79
- return t;
80
- }, [texture, repeat, repeatCount === null || repeatCount === void 0 ? void 0 : repeatCount[0], repeatCount === null || repeatCount === void 0 ? void 0 : repeatCount[1], generateMipmaps, minFilter, magFilter]);
81
- if (!properties) {
82
- return _jsx("meshStandardMaterial", { color: "red", wireframe: true });
83
- }
84
- const { color, wireframe = false } = properties;
85
- return (_jsx("meshStandardMaterial", { color: color, wireframe: wireframe, map: finalTexture, transparent: !!finalTexture, side: DoubleSide }, (_a = finalTexture === null || finalTexture === void 0 ? void 0 : finalTexture.uuid) !== null && _a !== void 0 ? _a : 'no-texture'));
86
- }
87
- const MaterialComponent = {
88
- name: 'Material',
89
- Editor: MaterialComponentEditor,
90
- View: MaterialComponentView,
91
- defaultProperties: {
92
- color: '#ffffff',
93
- wireframe: false
94
- }
95
- };
96
- export default MaterialComponent;
@@ -1,3 +0,0 @@
1
- import { Component } from './ComponentRegistry';
2
- declare const ModelComponent: Component;
3
- export default ModelComponent;
@@ -1,53 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { ModelListViewer } from '../../assetviewer/page';
3
- import { useEffect, useState, useMemo } from 'react';
4
- import { Label } from './Input';
5
- function ModelComponentEditor({ component, node, onUpdate, basePath = "" }) {
6
- const [modelFiles, setModelFiles] = useState([]);
7
- useEffect(() => {
8
- const base = basePath ? `${basePath}/` : '';
9
- fetch(`/${base}models/manifest.json`)
10
- .then(r => r.json())
11
- .then(data => setModelFiles(Array.isArray(data) ? data : data.files || []))
12
- .catch(console.error);
13
- }, [basePath]);
14
- const handleModelSelect = (file) => {
15
- // Remove leading slash for prefab compatibility
16
- const filename = file.startsWith('/') ? file.slice(1) : file;
17
- onUpdate({ 'filename': filename });
18
- };
19
- return _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [_jsxs("div", { children: [_jsx(Label, { children: "Model" }), _jsx("div", { style: { maxHeight: 128, overflowY: 'auto' }, children: _jsx(ModelListViewer, { files: modelFiles, selected: component.properties.filename ? `/${component.properties.filename}` : undefined, onSelect: handleModelSelect, basePath: basePath }, node === null || node === void 0 ? void 0 : node.id) })] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 4 }, children: [_jsx("input", { type: "checkbox", id: "instanced-checkbox", checked: component.properties.instanced || false, onChange: e => onUpdate({ instanced: e.target.checked }), style: { width: 12, height: 12 } }), _jsx("label", { htmlFor: "instanced-checkbox", style: { fontSize: '9px', color: 'rgba(34, 211, 238, 0.6)' }, children: "Instanced" })] })] });
20
- }
21
- // View for Model component
22
- function ModelComponentView({ properties, loadedModels, children }) {
23
- // Instanced models are handled elsewhere (GameInstance), so only render non-instanced here
24
- if (!properties.filename || properties.instanced)
25
- return _jsx(_Fragment, { children: children });
26
- const sourceModel = loadedModels === null || loadedModels === void 0 ? void 0 : loadedModels[properties.filename];
27
- // Clone model once and set up shadows - memoized to avoid cloning on every render
28
- const clonedModel = useMemo(() => {
29
- if (!sourceModel)
30
- return null;
31
- const clone = sourceModel.clone();
32
- clone.traverse((obj) => {
33
- if (obj.isMesh) {
34
- obj.castShadow = true;
35
- obj.receiveShadow = true;
36
- }
37
- });
38
- return clone;
39
- }, [sourceModel]);
40
- if (!clonedModel)
41
- return _jsx(_Fragment, { children: children });
42
- return _jsx("primitive", { object: clonedModel, children: children });
43
- }
44
- const ModelComponent = {
45
- name: 'Model',
46
- Editor: ModelComponentEditor,
47
- View: ModelComponentView,
48
- defaultProperties: {
49
- filename: '',
50
- instanced: false
51
- }
52
- };
53
- export default ModelComponent;
@@ -1,10 +0,0 @@
1
- import { Component } from "./ComponentRegistry";
2
- export interface PhysicsProps {
3
- type: "fixed" | "dynamic";
4
- collider?: string;
5
- mass?: number;
6
- restitution?: number;
7
- friction?: number;
8
- }
9
- declare const PhysicsComponent: Component;
10
- export default PhysicsComponent;
@@ -1,33 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { RigidBody } from "@react-three/rapier";
3
- import { Label } from "./Input";
4
- function PhysicsComponentEditor({ component, onUpdate }) {
5
- const { type = 'dynamic', collider = 'hull' } = component.properties;
6
- const selectStyle = {
7
- width: '100%',
8
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
9
- border: '1px solid rgba(34, 211, 238, 0.3)',
10
- padding: '2px 4px',
11
- fontSize: '10px',
12
- color: 'rgba(165, 243, 252, 1)',
13
- fontFamily: 'monospace',
14
- outline: 'none',
15
- };
16
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsxs("div", { children: [_jsx(Label, { children: "Type" }), _jsxs("select", { style: selectStyle, value: type, onChange: e => onUpdate({ type: e.target.value }), children: [_jsx("option", { value: "dynamic", children: "Dynamic" }), _jsx("option", { value: "fixed", children: "Fixed" })] })] }), _jsxs("div", { children: [_jsx(Label, { children: "Collider" }), _jsxs("select", { style: selectStyle, value: collider, onChange: e => onUpdate({ collider: e.target.value }), children: [_jsx("option", { value: "hull", children: "Hull (convex)" }), _jsx("option", { value: "trimesh", children: "Trimesh (exact)" }), _jsx("option", { value: "cuboid", children: "Cuboid (box)" }), _jsx("option", { value: "ball", children: "Ball (sphere)" })] })] })] }));
17
- }
18
- function PhysicsComponentView({ properties, children, position, rotation, scale, editMode }) {
19
- const colliders = properties.collider || (properties.type === 'fixed' ? 'trimesh' : 'hull');
20
- // In edit mode, include position/rotation in key to force remount when transform changes
21
- // This ensures the RigidBody debug visualization updates even when physics is paused
22
- const rbKey = editMode
23
- ? `${properties.type || 'dynamic'}_${colliders}_${position === null || position === void 0 ? void 0 : position.join(',')}_${rotation === null || rotation === void 0 ? void 0 : rotation.join(',')}`
24
- : `${properties.type || 'dynamic'}_${colliders}`;
25
- return (_jsx(RigidBody, { type: properties.type, colliders: colliders, position: position, rotation: rotation, scale: scale, children: children }, rbKey));
26
- }
27
- const PhysicsComponent = {
28
- name: 'Physics',
29
- Editor: PhysicsComponentEditor,
30
- View: PhysicsComponentView,
31
- defaultProperties: { type: 'dynamic', collider: 'hull' }
32
- };
33
- export default PhysicsComponent;
@@ -1,3 +0,0 @@
1
- import { Component } from "./ComponentRegistry";
2
- declare const RotatorComponent: Component;
3
- export default RotatorComponent;
@@ -1,42 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useFrame } from "@react-three/fiber";
3
- import { useRef } from "react";
4
- function RotatorComponentEditor({ component, onUpdate }) {
5
- var _a, _b;
6
- const props = {
7
- speed: (_a = component.properties.speed) !== null && _a !== void 0 ? _a : 1.0,
8
- axis: (_b = component.properties.axis) !== null && _b !== void 0 ? _b : 'y'
9
- };
10
- return _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-[9px] text-cyan-400/60 uppercase tracking-wider mb-0.5", children: "Rotation Speed" }), _jsx("input", { type: "number", step: "0.1", className: "w-full bg-black/40 border border-cyan-500/30 px-1 py-0.5 text-[10px] text-cyan-300 font-mono focus:outline-none focus:border-cyan-400/50", value: props.speed, onChange: e => onUpdate(Object.assign(Object.assign({}, component.properties), { speed: parseFloat(e.target.value) })) })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-[9px] text-cyan-400/60 uppercase tracking-wider mb-0.5", children: "Rotation Axis" }), _jsxs("select", { className: "w-full bg-black/40 border border-cyan-500/30 px-1 py-0.5 text-[10px] text-cyan-300 font-mono focus:outline-none focus:border-cyan-400/50", value: props.axis, onChange: e => onUpdate(Object.assign(Object.assign({}, component.properties), { axis: e.target.value })), children: [_jsx("option", { value: "x", children: "X" }), _jsx("option", { value: "y", children: "Y" }), _jsx("option", { value: "z", children: "Z" })] })] })] });
11
- }
12
- // The view component for Rotator
13
- function RotatorView({ properties, children }) {
14
- var _a, _b;
15
- const groupRef = useRef(null);
16
- const speed = (_a = properties.speed) !== null && _a !== void 0 ? _a : 1.0;
17
- const axis = (_b = properties.axis) !== null && _b !== void 0 ? _b : 'y';
18
- useFrame((state, delta) => {
19
- if (groupRef.current) {
20
- if (axis === 'x') {
21
- groupRef.current.rotation.x += delta * speed;
22
- }
23
- else if (axis === 'y') {
24
- groupRef.current.rotation.y += delta * speed;
25
- }
26
- else if (axis === 'z') {
27
- groupRef.current.rotation.z += delta * speed;
28
- }
29
- }
30
- });
31
- return (_jsx("group", { ref: groupRef, children: children }));
32
- }
33
- const RotatorComponent = {
34
- name: 'Rotator',
35
- Editor: RotatorComponentEditor,
36
- View: RotatorView,
37
- defaultProperties: {
38
- speed: 1.0,
39
- axis: 'y'
40
- }
41
- };
42
- export default RotatorComponent;
@@ -1,3 +0,0 @@
1
- import { Component } from "./ComponentRegistry";
2
- declare const SpotLightComponent: Component;
3
- export default SpotLightComponent;
@@ -1,49 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useRef, useEffect } from "react";
3
- import { Input, Label } from "./Input";
4
- function SpotLightComponentEditor({ component, onUpdate }) {
5
- var _a, _b, _c, _d, _e, _f;
6
- const props = {
7
- color: (_a = component.properties.color) !== null && _a !== void 0 ? _a : '#ffffff',
8
- intensity: (_b = component.properties.intensity) !== null && _b !== void 0 ? _b : 1.0,
9
- angle: (_c = component.properties.angle) !== null && _c !== void 0 ? _c : Math.PI / 6,
10
- penumbra: (_d = component.properties.penumbra) !== null && _d !== void 0 ? _d : 0.5,
11
- distance: (_e = component.properties.distance) !== null && _e !== void 0 ? _e : 100,
12
- castShadow: (_f = component.properties.castShadow) !== null && _f !== void 0 ? _f : true
13
- };
14
- const textInputStyle = {
15
- flex: 1,
16
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
17
- border: '1px solid rgba(34, 211, 238, 0.3)',
18
- padding: '2px 4px',
19
- fontSize: '10px',
20
- color: 'rgba(165, 243, 252, 1)',
21
- fontFamily: 'monospace',
22
- outline: 'none',
23
- };
24
- return _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsxs("div", { children: [_jsx(Label, { children: "Color" }), _jsxs("div", { style: { display: 'flex', gap: 2 }, children: [_jsx("input", { type: "color", style: { height: 20, width: 20, backgroundColor: 'transparent', border: 'none', cursor: 'pointer' }, value: props.color, onChange: e => onUpdate(Object.assign(Object.assign({}, component.properties), { color: e.target.value })) }), _jsx("input", { type: "text", style: textInputStyle, value: props.color, onChange: e => onUpdate(Object.assign(Object.assign({}, component.properties), { color: e.target.value })) })] })] }), _jsxs("div", { children: [_jsx(Label, { children: "Intensity" }), _jsx(Input, { step: "0.1", value: props.intensity, onChange: value => onUpdate(Object.assign(Object.assign({}, component.properties), { intensity: value })) })] }), _jsxs("div", { children: [_jsx(Label, { children: "Angle" }), _jsx(Input, { step: "0.1", min: 0, max: Math.PI, value: props.angle, onChange: value => onUpdate(Object.assign(Object.assign({}, component.properties), { angle: value })) })] }), _jsxs("div", { children: [_jsx(Label, { children: "Penumbra" }), _jsx(Input, { step: "0.1", min: 0, max: 1, value: props.penumbra, onChange: value => onUpdate(Object.assign(Object.assign({}, component.properties), { penumbra: value })) })] }), _jsxs("div", { children: [_jsx(Label, { children: "Distance" }), _jsx(Input, { step: "1", min: 0, value: props.distance, onChange: value => onUpdate(Object.assign(Object.assign({}, component.properties), { distance: value })) })] }), _jsxs("div", { children: [_jsx(Label, { children: "Cast Shadow" }), _jsx("input", { type: "checkbox", style: { height: 16, width: 16, backgroundColor: 'rgba(0, 0, 0, 0.4)', border: '1px solid rgba(34, 211, 238, 0.3)', cursor: 'pointer' }, checked: props.castShadow, onChange: e => onUpdate(Object.assign(Object.assign({}, component.properties), { castShadow: e.target.checked })) })] })] });
25
- }
26
- function SpotLightView({ properties, editMode }) {
27
- var _a, _b, _c, _d, _e, _f;
28
- const color = (_a = properties.color) !== null && _a !== void 0 ? _a : '#ffffff';
29
- const intensity = (_b = properties.intensity) !== null && _b !== void 0 ? _b : 1.0;
30
- const angle = (_c = properties.angle) !== null && _c !== void 0 ? _c : Math.PI / 6;
31
- const penumbra = (_d = properties.penumbra) !== null && _d !== void 0 ? _d : 0.5;
32
- const distance = (_e = properties.distance) !== null && _e !== void 0 ? _e : 100;
33
- const castShadow = (_f = properties.castShadow) !== null && _f !== void 0 ? _f : true;
34
- const spotLightRef = useRef(null);
35
- const targetRef = useRef(null);
36
- useEffect(() => {
37
- if (spotLightRef.current && targetRef.current) {
38
- spotLightRef.current.target = targetRef.current;
39
- }
40
- }, []);
41
- return (_jsxs(_Fragment, { children: [_jsx("spotLight", { ref: spotLightRef, color: color, intensity: intensity, angle: angle, penumbra: penumbra, distance: distance, castShadow: castShadow, "shadow-mapSize-width": 1024, "shadow-mapSize-height": 1024, "shadow-bias": -0.0001, "shadow-normalBias": 0.02 }), _jsx("object3D", { ref: targetRef, position: [0, -5, 0] }), editMode && (_jsxs(_Fragment, { children: [_jsxs("mesh", { children: [_jsx("sphereGeometry", { args: [0.2, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true })] }), _jsxs("mesh", { position: [0, -5, 0], children: [_jsx("sphereGeometry", { args: [0.15, 8, 6] }), _jsx("meshBasicMaterial", { color: color, wireframe: true, opacity: 0.5, transparent: true })] })] }))] }));
42
- }
43
- const SpotLightComponent = {
44
- name: 'SpotLight',
45
- Editor: SpotLightComponentEditor,
46
- View: SpotLightView,
47
- defaultProperties: {}
48
- };
49
- export default SpotLightComponent;
@@ -1,3 +0,0 @@
1
- import { Component } from "./ComponentRegistry";
2
- declare const TransformComponent: Component;
3
- export default TransformComponent;
@@ -1,42 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Vector3Input, Label } from "./Input";
3
- import { useEditorContext } from "../EditorContext";
4
- const buttonStyle = {
5
- padding: '2px 6px',
6
- background: 'transparent',
7
- color: 'rgba(255,255,255,0.9)',
8
- border: '1px solid rgba(255,255,255,0.14)',
9
- borderRadius: 4,
10
- cursor: 'pointer',
11
- font: 'inherit',
12
- flex: 1,
13
- };
14
- function TransformComponentEditor({ component, onUpdate, transformMode, setTransformMode }) {
15
- const { snapResolution, setSnapResolution } = useEditorContext();
16
- return _jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [transformMode && setTransformMode && (_jsxs("div", { style: { marginBottom: 8 }, children: [_jsxs(Label, { children: ["Transform Mode ", snapResolution > 0 && `(Snap: ${snapResolution})`] }), _jsx("div", { style: { display: 'flex', gap: 6 }, children: ["translate", "rotate", "scale"].map(mode => {
17
- const isActive = transformMode === mode;
18
- return (_jsx("button", { onClick: () => setTransformMode(mode), style: Object.assign(Object.assign({}, buttonStyle), { background: isActive ? 'rgba(255,255,255,0.10)' : 'transparent' }), onPointerEnter: (e) => {
19
- if (!isActive)
20
- e.currentTarget.style.background = 'rgba(255,255,255,0.08)';
21
- }, onPointerLeave: (e) => {
22
- if (!isActive)
23
- e.currentTarget.style.background = 'transparent';
24
- }, children: mode }, mode));
25
- }) }), _jsx("div", { style: { marginTop: 6 }, children: _jsxs("button", { onClick: () => setSnapResolution(snapResolution > 0 ? 0 : 0.1), style: Object.assign(Object.assign({}, buttonStyle), { background: snapResolution > 0 ? 'rgba(255,255,255,0.10)' : 'transparent', width: '100%' }), onPointerEnter: (e) => {
26
- if (snapResolution === 0)
27
- e.currentTarget.style.background = 'rgba(255,255,255,0.08)';
28
- }, onPointerLeave: (e) => {
29
- if (snapResolution === 0)
30
- e.currentTarget.style.background = 'transparent';
31
- }, children: ["Snap: ", snapResolution > 0 ? `ON (${snapResolution})` : 'OFF'] }) })] })), _jsx(Vector3Input, { label: "Position", value: component.properties.position, onChange: v => onUpdate({ position: v }), snap: snapResolution }), _jsx(Vector3Input, { label: "Rotation", value: component.properties.rotation, onChange: v => onUpdate({ rotation: v }), snap: snapResolution }), _jsx(Vector3Input, { label: "Scale", value: component.properties.scale, onChange: v => onUpdate({ scale: v }), snap: snapResolution })] });
32
- }
33
- const TransformComponent = {
34
- name: 'Transform',
35
- Editor: TransformComponentEditor,
36
- defaultProperties: {
37
- position: [0, 0, 0],
38
- rotation: [0, 0, 0],
39
- scale: [1, 1, 1]
40
- }
41
- };
42
- export default TransformComponent;
@@ -1,2 +0,0 @@
1
- declare const _default: import("./ComponentRegistry").Component[];
2
- export default _default;
@@ -1,16 +0,0 @@
1
- import GeometryComponent from './GeometryComponent';
2
- import TransformComponent from './TransformComponent';
3
- import MaterialComponent from './MaterialComponent';
4
- import PhysicsComponent from './PhysicsComponent';
5
- import SpotLightComponent from './SpotLightComponent';
6
- import DirectionalLightComponent from './DirectionalLightComponent';
7
- import ModelComponent from './ModelComponent';
8
- export default [
9
- GeometryComponent,
10
- TransformComponent,
11
- MaterialComponent,
12
- PhysicsComponent,
13
- SpotLightComponent,
14
- DirectionalLightComponent,
15
- ModelComponent
16
- ];
@@ -1,10 +0,0 @@
1
- import { Object3D } from 'three';
2
- /**
3
- * Hook to load a model (GLB/GLTF/FBX) using drei's optimized loaders
4
- * Returns the loaded model with proper caching and suspense support
5
- */
6
- export declare function useModel(filename: string | undefined): Object3D | null;
7
- /**
8
- * Preload a model to avoid suspense boundaries during runtime
9
- */
10
- export declare function preloadModel(filename: string): void;
@@ -1,40 +0,0 @@
1
- import { useGLTF, useFBX } from '@react-three/drei';
2
- import { useMemo } from 'react';
3
- /**
4
- * Hook to load a model (GLB/GLTF/FBX) using drei's optimized loaders
5
- * Returns the loaded model with proper caching and suspense support
6
- */
7
- export function useModel(filename) {
8
- const isFBX = filename === null || filename === void 0 ? void 0 : filename.toLowerCase().endsWith('.fbx');
9
- const isGLTF = (filename === null || filename === void 0 ? void 0 : filename.toLowerCase().endsWith('.glb')) || (filename === null || filename === void 0 ? void 0 : filename.toLowerCase().endsWith('.gltf'));
10
- // Normalize path (ensure leading slash)
11
- const normalizedPath = useMemo(() => {
12
- if (!filename)
13
- return '';
14
- return filename.startsWith('/') ? filename : `/${filename}`;
15
- }, [filename]);
16
- // Load models using drei hooks (these handle caching automatically)
17
- const gltf = useGLTF(isGLTF && normalizedPath ? normalizedPath : '', true);
18
- const fbx = useFBX(isFBX && normalizedPath ? normalizedPath : '');
19
- // Return the appropriate model
20
- if (!filename)
21
- return null;
22
- if (isGLTF)
23
- return gltf.scene;
24
- if (isFBX)
25
- return fbx;
26
- return null;
27
- }
28
- /**
29
- * Preload a model to avoid suspense boundaries during runtime
30
- */
31
- export function preloadModel(filename) {
32
- const normalizedPath = filename.startsWith('/') ? filename : `/${filename}`;
33
- const isFBX = filename.toLowerCase().endsWith('.fbx');
34
- if (isFBX) {
35
- useFBX.preload(normalizedPath);
36
- }
37
- else {
38
- useGLTF.preload(normalizedPath);
39
- }
40
- }
@@ -1 +0,0 @@
1
- export default function PrefabEditorPage(): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import PrefabEditor from "./PrefabEditor";
3
- export default function PrefabEditorPage() {
4
- return _jsx("div", { className: "w-screen h-screen", children: _jsx(PrefabEditor, { children: _jsx("directionalLight", { position: [5, 10, 7.5], intensity: 1, castShadow: true }) }) });
5
- }