react-three-game 0.0.107 → 0.0.109
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 +12 -5
- package/dist/editor.d.ts +22 -0
- package/dist/editor.js +15 -0
- package/dist/plugins/crashcat/CrashcatPhysicsComponent.js +75 -47
- package/dist/plugins/crashcat/CrashcatRagdoll.d.ts +58 -0
- package/dist/plugins/crashcat/CrashcatRagdoll.js +410 -0
- package/dist/plugins/crashcat/CrashcatRuntime.js +19 -15
- package/dist/plugins/crashcat/index.d.ts +1 -0
- package/dist/plugins/crashcat/index.js +1 -0
- package/dist/tools/assetviewer/page.js +4 -4
- package/dist/tools/prefabeditor/EditorContext.d.ts +36 -0
- package/dist/tools/prefabeditor/EditorContext.js +17 -0
- package/dist/tools/prefabeditor/EditorTree.js +6 -3
- package/dist/tools/prefabeditor/EditorTreeMenus.d.ts +2 -1
- package/dist/tools/prefabeditor/EditorTreeMenus.js +18 -6
- package/dist/tools/prefabeditor/EditorUI.js +1 -1
- package/dist/tools/prefabeditor/GameEvents.d.ts +1 -0
- package/dist/tools/prefabeditor/PrefabEditor.d.ts +5 -37
- package/dist/tools/prefabeditor/PrefabEditor.js +41 -43
- package/dist/tools/prefabeditor/PrefabRoot.d.ts +5 -27
- package/dist/tools/prefabeditor/PrefabRoot.js +133 -78
- package/dist/tools/prefabeditor/SceneContext.d.ts +28 -0
- package/dist/tools/prefabeditor/SceneContext.js +14 -0
- package/dist/tools/prefabeditor/assetRuntime.d.ts +4 -0
- package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +16 -1
- package/dist/tools/prefabeditor/components/ModelComponent.js +1 -1
- package/dist/tools/prefabeditor/components/PrefabRefComponent.d.ts +3 -0
- package/dist/tools/prefabeditor/components/PrefabRefComponent.js +72 -0
- package/dist/tools/prefabeditor/components/TextComponent.js +8 -5
- package/dist/tools/prefabeditor/components/TransformComponent.js +1 -1
- package/dist/tools/prefabeditor/components/index.d.ts +1 -0
- package/dist/tools/prefabeditor/components/index.js +10 -0
- package/dist/tools/prefabeditor/components/runtime.d.ts +4 -0
- package/dist/tools/prefabeditor/components/runtime.js +372 -0
- package/dist/tools/prefabeditor/modelPrefab.d.ts +3 -0
- package/dist/tools/prefabeditor/modelPrefab.js +44 -11
- package/dist/tools/prefabeditor/prefab.d.ts +5 -4
- package/dist/tools/prefabeditor/prefab.js +47 -29
- package/dist/tools/prefabeditor/prefabStore.d.ts +1 -1
- package/dist/tools/prefabeditor/prefabStore.js +5 -1
- package/dist/tools/prefabeditor/runtimeUtils.d.ts +10 -0
- package/dist/tools/prefabeditor/runtimeUtils.js +30 -0
- package/dist/tools/prefabeditor/utils.d.ts +7 -8
- package/dist/tools/prefabeditor/utils.js +63 -36
- package/dist/viewer.d.ts +22 -0
- package/dist/viewer.js +14 -0
- package/package.json +22 -20
- package/dist/index.d.ts +0 -40
- package/dist/index.js +0 -32
|
@@ -9,12 +9,12 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { getComponentAssetRefs, getComponentDef } from
|
|
12
|
+
import { getComponentAssetRefs, getComponentDef, } from "./components/ComponentRegistry";
|
|
13
13
|
function clonePrefabValue(value) {
|
|
14
14
|
if (Array.isArray(value)) {
|
|
15
|
-
return value.map(item => clonePrefabValue(item));
|
|
15
|
+
return value.map((item) => clonePrefabValue(item));
|
|
16
16
|
}
|
|
17
|
-
if (value && typeof value ===
|
|
17
|
+
if (value && typeof value === "object") {
|
|
18
18
|
const clone = {};
|
|
19
19
|
Object.entries(value).forEach(([key, entry]) => {
|
|
20
20
|
clone[key] = clonePrefabValue(entry);
|
|
@@ -25,7 +25,7 @@ function clonePrefabValue(value) {
|
|
|
25
25
|
}
|
|
26
26
|
function createComponentMap(components) {
|
|
27
27
|
const componentMap = {
|
|
28
|
-
transform: createComponentData(
|
|
28
|
+
transform: createComponentData("Transform"),
|
|
29
29
|
};
|
|
30
30
|
Object.entries(components).forEach(([key, component]) => {
|
|
31
31
|
componentMap[key] = createComponentData(component.type, component.properties);
|
|
@@ -33,10 +33,10 @@ function createComponentMap(components) {
|
|
|
33
33
|
return componentMap;
|
|
34
34
|
}
|
|
35
35
|
function getNodeNameFromPath(path, name) {
|
|
36
|
-
return name !== null && name !== void 0 ? name : path.replace(/^.*[\/]/,
|
|
36
|
+
return name !== null && name !== void 0 ? name : path.replace(/^.*[\/]/, "").replace(/\.[^.]+$/, "");
|
|
37
37
|
}
|
|
38
38
|
function getAssetManifestKey(assetRefCounts) {
|
|
39
|
-
return Object.keys(assetRefCounts).sort().join(
|
|
39
|
+
return Object.keys(assetRefCounts).sort().join("|");
|
|
40
40
|
}
|
|
41
41
|
function sameStringArrays(left, right) {
|
|
42
42
|
if (left.length !== right.length)
|
|
@@ -46,7 +46,7 @@ function sameStringArrays(left, right) {
|
|
|
46
46
|
function getAssetRefs(node) {
|
|
47
47
|
var _a;
|
|
48
48
|
const refs = [];
|
|
49
|
-
Object.values((_a = node === null || node === void 0 ? void 0 : node.components) !== null && _a !== void 0 ? _a : {}).forEach(component => {
|
|
49
|
+
Object.values((_a = node === null || node === void 0 ? void 0 : node.components) !== null && _a !== void 0 ? _a : {}).forEach((component) => {
|
|
50
50
|
var _a;
|
|
51
51
|
if (!(component === null || component === void 0 ? void 0 : component.type))
|
|
52
52
|
return;
|
|
@@ -57,13 +57,13 @@ function getAssetRefs(node) {
|
|
|
57
57
|
return refs.sort();
|
|
58
58
|
}
|
|
59
59
|
function addAssetRefs(assetRefCounts, refs) {
|
|
60
|
-
refs.forEach(ref => {
|
|
60
|
+
refs.forEach((ref) => {
|
|
61
61
|
var _a;
|
|
62
62
|
assetRefCounts[ref] = ((_a = assetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
function removeAssetRefs(assetRefCounts, refs) {
|
|
66
|
-
refs.forEach(ref => {
|
|
66
|
+
refs.forEach((ref) => {
|
|
67
67
|
var _a;
|
|
68
68
|
const nextCount = ((_a = assetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) - 1;
|
|
69
69
|
if (nextCount > 0) {
|
|
@@ -75,13 +75,15 @@ function removeAssetRefs(assetRefCounts, refs) {
|
|
|
75
75
|
}
|
|
76
76
|
function createAssetRefCounts(nodesById) {
|
|
77
77
|
const assetRefCounts = {};
|
|
78
|
-
Object.values(nodesById).forEach(node =>
|
|
78
|
+
Object.values(nodesById).forEach((node) => {
|
|
79
|
+
addAssetRefs(assetRefCounts, getAssetRefs(node));
|
|
80
|
+
});
|
|
79
81
|
return assetRefCounts;
|
|
80
82
|
}
|
|
81
83
|
function denormalizeNode(id, nodesById, childIdsById) {
|
|
82
84
|
var _a;
|
|
83
85
|
const node = nodesById[id];
|
|
84
|
-
return Object.assign(Object.assign({}, node), { children: ((_a = childIdsById[id]) !== null && _a !== void 0 ? _a : []).map(childId => denormalizeNode(childId, nodesById, childIdsById)) });
|
|
86
|
+
return Object.assign(Object.assign({}, node), { children: ((_a = childIdsById[id]) !== null && _a !== void 0 ? _a : []).map((childId) => denormalizeNode(childId, nodesById, childIdsById)) });
|
|
85
87
|
}
|
|
86
88
|
export function createDefaultComponentProperties(type) {
|
|
87
89
|
var _a, _b;
|
|
@@ -90,32 +92,34 @@ export function createDefaultComponentProperties(type) {
|
|
|
90
92
|
export function createComponentData(type, properties) {
|
|
91
93
|
return {
|
|
92
94
|
type,
|
|
93
|
-
properties: properties
|
|
95
|
+
properties: properties
|
|
96
|
+
? clonePrefabValue(properties)
|
|
97
|
+
: createDefaultComponentProperties(type),
|
|
94
98
|
};
|
|
95
99
|
}
|
|
96
100
|
export function createNode(name, components = {}, options) {
|
|
97
101
|
var _a;
|
|
98
102
|
return Object.assign({ id: (_a = options === null || options === void 0 ? void 0 : options.id) !== null && _a !== void 0 ? _a : crypto.randomUUID(), name, components: createComponentMap(components) }, ((options === null || options === void 0 ? void 0 : options.children) ? { children: options.children } : null));
|
|
99
103
|
}
|
|
100
|
-
export function createEmptyNode(name =
|
|
104
|
+
export function createEmptyNode(name = "New Node") {
|
|
101
105
|
return createNode(name);
|
|
102
106
|
}
|
|
103
107
|
export function createEmptyPrefab() {
|
|
104
108
|
return {
|
|
105
109
|
id: crypto.randomUUID(),
|
|
106
|
-
name:
|
|
107
|
-
root: createNode(
|
|
110
|
+
name: "New Prefab",
|
|
111
|
+
root: createNode("Root", {}, { id: crypto.randomUUID(), children: [] }),
|
|
108
112
|
};
|
|
109
113
|
}
|
|
110
114
|
export function createModelNode(filename, name) {
|
|
111
115
|
return createNode(getNodeNameFromPath(filename, name), {
|
|
112
116
|
model: {
|
|
113
|
-
type:
|
|
117
|
+
type: "Model",
|
|
114
118
|
properties: {
|
|
115
119
|
filename,
|
|
116
120
|
instanced: false,
|
|
117
121
|
repeat: false,
|
|
118
|
-
repeatAxes: [{ axis:
|
|
122
|
+
repeatAxes: [{ axis: "x", count: 1, offset: 1 }],
|
|
119
123
|
},
|
|
120
124
|
},
|
|
121
125
|
});
|
|
@@ -123,12 +127,20 @@ export function createModelNode(filename, name) {
|
|
|
123
127
|
export function createImageNode(texturePath, name) {
|
|
124
128
|
return createNode(getNodeNameFromPath(texturePath, name), {
|
|
125
129
|
geometry: {
|
|
126
|
-
type:
|
|
127
|
-
properties: { geometryType:
|
|
130
|
+
type: "Geometry",
|
|
131
|
+
properties: { geometryType: "plane", args: [1, 1] },
|
|
128
132
|
},
|
|
129
133
|
material: {
|
|
130
|
-
type:
|
|
131
|
-
properties: { color:
|
|
134
|
+
type: "Material",
|
|
135
|
+
properties: { color: "#ffffff", texture: texturePath },
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
export function createPackedPrefabNode(url) {
|
|
140
|
+
return createNode("Packed Prefab", {
|
|
141
|
+
prefabref: {
|
|
142
|
+
type: "PrefabRef",
|
|
143
|
+
properties: { url },
|
|
132
144
|
},
|
|
133
145
|
});
|
|
134
146
|
}
|
|
@@ -151,10 +163,12 @@ export function normalizePrefab(prefab) {
|
|
|
151
163
|
}
|
|
152
164
|
export function createPrefabPatch(state, patch, nextAssetRefCounts = state.assetRefCounts) {
|
|
153
165
|
const assetRefsChanged = nextAssetRefCounts !== state.assetRefCounts;
|
|
154
|
-
return Object.assign(Object.assign({}, patch), (assetRefsChanged
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
166
|
+
return Object.assign(Object.assign({}, patch), (assetRefsChanged
|
|
167
|
+
? {
|
|
168
|
+
assetRefCounts: nextAssetRefCounts,
|
|
169
|
+
assetManifestKey: getAssetManifestKey(nextAssetRefCounts),
|
|
170
|
+
}
|
|
171
|
+
: null));
|
|
158
172
|
}
|
|
159
173
|
export function denormalizePrefab(state) {
|
|
160
174
|
return {
|
|
@@ -175,9 +189,11 @@ export function insertSubtree(node, parentId, nodesById, childIdsById, parentIdB
|
|
|
175
189
|
var _a;
|
|
176
190
|
const { children } = node, nodeRecord = __rest(node, ["children"]);
|
|
177
191
|
nodesById[node.id] = nodeRecord;
|
|
178
|
-
childIdsById[node.id] = (_a = children === null || children === void 0 ? void 0 : children.map(child => child.id)) !== null && _a !== void 0 ? _a : [];
|
|
192
|
+
childIdsById[node.id] = (_a = children === null || children === void 0 ? void 0 : children.map((child) => child.id)) !== null && _a !== void 0 ? _a : [];
|
|
179
193
|
parentIdById[node.id] = parentId;
|
|
180
|
-
children === null || children === void 0 ? void 0 : children.forEach(child =>
|
|
194
|
+
children === null || children === void 0 ? void 0 : children.forEach((child) => {
|
|
195
|
+
insertSubtree(child, node.id, nodesById, childIdsById, parentIdById);
|
|
196
|
+
});
|
|
181
197
|
}
|
|
182
198
|
export function cloneSubtree(id, parentId, source, nodesById, childIdsById, parentIdById) {
|
|
183
199
|
var _a, _b;
|
|
@@ -189,7 +205,7 @@ export function cloneSubtree(id, parentId, source, nodesById, childIdsById, pare
|
|
|
189
205
|
nodesById[clonedId] = clonedNode;
|
|
190
206
|
parentIdById[clonedId] = parentId;
|
|
191
207
|
const clonedChildIds = ((_b = source.childIdsById[id]) !== null && _b !== void 0 ? _b : [])
|
|
192
|
-
.map(childId => cloneSubtree(childId, clonedId, source, nodesById, childIdsById, parentIdById))
|
|
208
|
+
.map((childId) => cloneSubtree(childId, clonedId, source, nodesById, childIdsById, parentIdById))
|
|
193
209
|
.filter((childId) => Boolean(childId));
|
|
194
210
|
childIdsById[clonedId] = clonedChildIds;
|
|
195
211
|
return clonedId;
|
|
@@ -217,7 +233,9 @@ export function updateAssetRefsForNodeChange(assetRefCounts, currentNode, nextNo
|
|
|
217
233
|
export function collectSubtreeAssetRefs(node) {
|
|
218
234
|
var _a;
|
|
219
235
|
const refs = getAssetRefs(node);
|
|
220
|
-
(_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(child =>
|
|
236
|
+
(_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
|
|
237
|
+
refs.push(...collectSubtreeAssetRefs(child));
|
|
238
|
+
});
|
|
221
239
|
return refs;
|
|
222
240
|
}
|
|
223
241
|
export function collectAssetRefsForIds(ids, nodesById) {
|
|
@@ -15,7 +15,7 @@ export type PrefabStoreApi = StoreApi<PrefabStoreState>;
|
|
|
15
15
|
export declare function PrefabStoreProvider({ store, children, }: {
|
|
16
16
|
store: PrefabStoreApi;
|
|
17
17
|
children: ReactNode;
|
|
18
|
-
}): import("react").FunctionComponentElement<import("react").ProviderProps<PrefabStoreApi | null>>;
|
|
18
|
+
}): import("react").FunctionComponentElement<import("react").FragmentProps> | import("react").FunctionComponentElement<import("react").ProviderProps<PrefabStoreApi | null>>;
|
|
19
19
|
export declare function usePrefabStoreApi(): PrefabStoreApi;
|
|
20
20
|
export declare function usePrefabStore<T>(selector: (state: PrefabStoreState) => T): T;
|
|
21
21
|
export declare function usePrefabRootId(): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, createElement, useContext } from "react";
|
|
1
|
+
import { Fragment, createContext, createElement, useContext } from "react";
|
|
2
2
|
import { subscribeWithSelector } from "zustand/middleware";
|
|
3
3
|
import { useStore } from "zustand";
|
|
4
4
|
import { createStore } from "zustand/vanilla";
|
|
@@ -45,6 +45,10 @@ function insertSubtreeIntoGraph(node, parentId, next) {
|
|
|
45
45
|
addAssetRefs(next.assetRefCounts, collectSubtreeAssetRefs(node));
|
|
46
46
|
}
|
|
47
47
|
export function PrefabStoreProvider({ store, children, }) {
|
|
48
|
+
const parentStore = useContext(PrefabStoreContext);
|
|
49
|
+
if (parentStore === store) {
|
|
50
|
+
return createElement(Fragment, null, children);
|
|
51
|
+
}
|
|
48
52
|
return createElement(PrefabStoreContext.Provider, { value: store }, children);
|
|
49
53
|
}
|
|
50
54
|
export function usePrefabStoreApi() {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Matrix4 } from "three";
|
|
2
|
+
export declare function isExternalPath(path: string): boolean;
|
|
3
|
+
export declare function withBasePath(basePath: string | undefined, path: string): string;
|
|
4
|
+
export declare function decompose(m: Matrix4): {
|
|
5
|
+
position: [number, number, number];
|
|
6
|
+
rotation: [number, number, number];
|
|
7
|
+
scale: [number, number, number];
|
|
8
|
+
};
|
|
9
|
+
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
10
|
+
export declare function composeTransform(position?: [number, number, number], rotation?: [number, number, number], scale?: [number, number, number]): Matrix4;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
2
|
+
export function isExternalPath(path) {
|
|
3
|
+
return (path.startsWith("data:") ||
|
|
4
|
+
path.startsWith("http://") ||
|
|
5
|
+
path.startsWith("https://"));
|
|
6
|
+
}
|
|
7
|
+
export function withBasePath(basePath, path) {
|
|
8
|
+
if (!path)
|
|
9
|
+
return (basePath !== null && basePath !== void 0 ? basePath : "").replace(/\/$/, "");
|
|
10
|
+
if (isExternalPath(path))
|
|
11
|
+
return path;
|
|
12
|
+
const normalizedBasePath = (basePath !== null && basePath !== void 0 ? basePath : "").replace(/\/$/, "");
|
|
13
|
+
return path.startsWith("/") ? `${normalizedBasePath}${path}` : `${normalizedBasePath}/${path}`;
|
|
14
|
+
}
|
|
15
|
+
export function decompose(m) {
|
|
16
|
+
const p = new Vector3();
|
|
17
|
+
const q = new Quaternion();
|
|
18
|
+
const s = new Vector3();
|
|
19
|
+
m.decompose(p, q, s);
|
|
20
|
+
const e = new Euler().setFromQuaternion(q);
|
|
21
|
+
return {
|
|
22
|
+
position: [p.x, p.y, p.z],
|
|
23
|
+
rotation: [e.x, e.y, e.z],
|
|
24
|
+
scale: [s.x, s.y, s.z],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
28
|
+
export function composeTransform(position = [0, 0, 0], rotation = [0, 0, 0], scale = [1, 1, 1]) {
|
|
29
|
+
return new Matrix4().compose(new Vector3(...position), new Quaternion().setFromEuler(new Euler(...rotation)), new Vector3(...scale));
|
|
30
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GameObject, Prefab } from "./types";
|
|
2
|
-
import { Matrix4, Object3D, Vector3 } from
|
|
2
|
+
import { Matrix4, Object3D, Vector3 } from "three";
|
|
3
|
+
export { composeTransform, decompose, isExternalPath, withBasePath } from "./runtimeUtils";
|
|
3
4
|
export interface ExportGLBOptions {
|
|
4
5
|
filename?: string;
|
|
5
6
|
}
|
|
@@ -7,6 +8,11 @@ export interface ExportGLBOptions {
|
|
|
7
8
|
export declare function saveJson(data: Prefab, filename: string): Promise<void>;
|
|
8
9
|
/** Load scene JSON from a file */
|
|
9
10
|
export declare function loadJson(): Promise<Prefab | undefined>;
|
|
11
|
+
/** Load scene JSON from a file, also returning the original filename */
|
|
12
|
+
export declare function loadJsonFile(): Promise<{
|
|
13
|
+
prefab: Prefab;
|
|
14
|
+
filename: string;
|
|
15
|
+
} | undefined>;
|
|
10
16
|
/**
|
|
11
17
|
* Export a Three.js scene or object to GLB binary data
|
|
12
18
|
*/
|
|
@@ -16,13 +22,6 @@ export declare function exportGLBData(sceneRoot: Object3D): Promise<ArrayBuffer>
|
|
|
16
22
|
*/
|
|
17
23
|
export declare function exportGLB(sceneRoot: Object3D, options?: ExportGLBOptions): Promise<ArrayBuffer>;
|
|
18
24
|
export declare function focusCameraOnObject(object: Object3D, camera: Object3D, target: Vector3, update?: () => void): void;
|
|
19
|
-
export declare function decompose(m: Matrix4): {
|
|
20
|
-
position: [number, number, number];
|
|
21
|
-
rotation: [number, number, number];
|
|
22
|
-
scale: [number, number, number];
|
|
23
|
-
};
|
|
24
|
-
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
25
|
-
export declare function composeTransform(position?: [number, number, number], rotation?: [number, number, number], scale?: [number, number, number]): Matrix4;
|
|
26
25
|
/** Compute the parent world matrix for a node using the normalized store data */
|
|
27
26
|
export declare function computeParentWorldMatrix(state: {
|
|
28
27
|
nodesById: Record<string, {
|
|
@@ -8,17 +8,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { findComponent } from "./types";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { composeTransform } from "./runtimeUtils";
|
|
12
|
+
import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
13
|
+
import { Box3, Matrix4, PerspectiveCamera, Quaternion, Vector3, } from "three";
|
|
14
|
+
export { composeTransform, decompose, isExternalPath, withBasePath } from "./runtimeUtils";
|
|
13
15
|
/** Save scene JSON, showing a Save As dialog when supported */
|
|
14
16
|
export function saveJson(data, filename) {
|
|
15
17
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16
18
|
const json = JSON.stringify(data, null, 2);
|
|
17
|
-
if (
|
|
19
|
+
if ("showSaveFilePicker" in window) {
|
|
18
20
|
try {
|
|
19
21
|
const handle = yield window.showSaveFilePicker({
|
|
20
|
-
suggestedName: `${filename ||
|
|
21
|
-
types: [
|
|
22
|
+
suggestedName: `${filename || "scene"}.json`,
|
|
23
|
+
types: [
|
|
24
|
+
{ description: "JSON", accept: { "application/json": [".json"] } },
|
|
25
|
+
],
|
|
22
26
|
});
|
|
23
27
|
const writable = yield handle.createWritable();
|
|
24
28
|
yield writable.write(json);
|
|
@@ -26,38 +30,70 @@ export function saveJson(data, filename) {
|
|
|
26
30
|
return;
|
|
27
31
|
}
|
|
28
32
|
catch (e) {
|
|
29
|
-
if ((e === null || e === void 0 ? void 0 : e.name) ===
|
|
33
|
+
if ((e === null || e === void 0 ? void 0 : e.name) === "AbortError")
|
|
30
34
|
return; // user cancelled
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
// Fallback for browsers without File System Access API
|
|
34
|
-
const a = document.createElement(
|
|
38
|
+
const a = document.createElement("a");
|
|
35
39
|
a.href = "data:text/json;charset=utf-8," + encodeURIComponent(json);
|
|
36
|
-
a.download = `${filename ||
|
|
40
|
+
a.download = `${filename || "scene"}.json`;
|
|
37
41
|
a.click();
|
|
38
42
|
});
|
|
39
43
|
}
|
|
40
44
|
/** Load scene JSON from a file */
|
|
41
45
|
export function loadJson() {
|
|
42
|
-
return new Promise(resolve => {
|
|
43
|
-
const input = document.createElement(
|
|
44
|
-
input.type =
|
|
45
|
-
input.accept =
|
|
46
|
-
input.onchange = e => {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const input = document.createElement("input");
|
|
48
|
+
input.type = "file";
|
|
49
|
+
input.accept = ".json,application/json";
|
|
50
|
+
input.onchange = (e) => {
|
|
47
51
|
var _a;
|
|
48
52
|
const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
49
53
|
if (!file)
|
|
50
54
|
return resolve(undefined);
|
|
51
55
|
const reader = new FileReader();
|
|
52
|
-
reader.onload = e => {
|
|
56
|
+
reader.onload = (e) => {
|
|
53
57
|
var _a;
|
|
54
58
|
try {
|
|
55
59
|
const text = (_a = e.target) === null || _a === void 0 ? void 0 : _a.result;
|
|
56
|
-
if (typeof text ===
|
|
60
|
+
if (typeof text === "string")
|
|
57
61
|
resolve(JSON.parse(text));
|
|
58
62
|
}
|
|
59
63
|
catch (err) {
|
|
60
|
-
console.error(
|
|
64
|
+
console.error("Error parsing scene JSON:", err);
|
|
65
|
+
resolve(undefined);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
reader.readAsText(file);
|
|
69
|
+
};
|
|
70
|
+
input.click();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** Load scene JSON from a file, also returning the original filename */
|
|
74
|
+
export function loadJsonFile() {
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
const input = document.createElement("input");
|
|
77
|
+
input.type = "file";
|
|
78
|
+
input.accept = ".json,application/json";
|
|
79
|
+
input.onchange = (e) => {
|
|
80
|
+
var _a;
|
|
81
|
+
const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
82
|
+
if (!file)
|
|
83
|
+
return resolve(undefined);
|
|
84
|
+
const reader = new FileReader();
|
|
85
|
+
reader.onload = (ev) => {
|
|
86
|
+
var _a;
|
|
87
|
+
try {
|
|
88
|
+
const text = (_a = ev.target) === null || _a === void 0 ? void 0 : _a.result;
|
|
89
|
+
if (typeof text === "string")
|
|
90
|
+
resolve({
|
|
91
|
+
prefab: JSON.parse(text),
|
|
92
|
+
filename: file.name,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
console.error("Error parsing scene JSON:", err);
|
|
61
97
|
resolve(undefined);
|
|
62
98
|
}
|
|
63
99
|
};
|
|
@@ -79,12 +115,12 @@ export function exportGLBData(sceneRoot) {
|
|
|
79
115
|
*/
|
|
80
116
|
export function exportGLB(sceneRoot_1) {
|
|
81
117
|
return __awaiter(this, arguments, void 0, function* (sceneRoot, options = {}) {
|
|
82
|
-
const { filename =
|
|
118
|
+
const { filename = "scene.glb" } = options;
|
|
83
119
|
const data = yield exportGLBData(sceneRoot);
|
|
84
120
|
if (filename) {
|
|
85
|
-
const blob = new Blob([data], { type:
|
|
121
|
+
const blob = new Blob([data], { type: "application/octet-stream" });
|
|
86
122
|
const url = URL.createObjectURL(blob);
|
|
87
|
-
const a = document.createElement(
|
|
123
|
+
const a = document.createElement("a");
|
|
88
124
|
a.href = url;
|
|
89
125
|
a.download = filename;
|
|
90
126
|
a.click();
|
|
@@ -110,30 +146,21 @@ export function focusCameraOnObject(object, camera, target, update) {
|
|
|
110
146
|
const radius = Math.max(size.length() * 0.5, 1);
|
|
111
147
|
const forward = new Vector3(0, 0, 1).applyQuaternion(quaternion).normalize();
|
|
112
148
|
const worldUp = new Vector3(0, 1, 0);
|
|
113
|
-
const elevatedDirection = forward
|
|
149
|
+
const elevatedDirection = forward
|
|
150
|
+
.clone()
|
|
151
|
+
.addScaledVector(worldUp, 0.65)
|
|
152
|
+
.normalize();
|
|
114
153
|
const distance = camera instanceof PerspectiveCamera
|
|
115
|
-
? Math.max(radius / Math.tan((camera.fov * Math.PI) / 360) * 1.8, radius * 3.5)
|
|
154
|
+
? Math.max((radius / Math.tan((camera.fov * Math.PI) / 360)) * 1.8, radius * 3.5)
|
|
116
155
|
: radius * 4.5;
|
|
117
|
-
const nextPosition = center
|
|
156
|
+
const nextPosition = center
|
|
157
|
+
.clone()
|
|
158
|
+
.add(elevatedDirection.multiplyScalar(distance));
|
|
118
159
|
camera.position.copy(nextPosition);
|
|
119
160
|
camera.lookAt(center);
|
|
120
161
|
target.copy(center);
|
|
121
162
|
update === null || update === void 0 ? void 0 : update();
|
|
122
163
|
}
|
|
123
|
-
export function decompose(m) {
|
|
124
|
-
const p = new Vector3(), q = new Quaternion(), s = new Vector3();
|
|
125
|
-
m.decompose(p, q, s);
|
|
126
|
-
const e = new Euler().setFromQuaternion(q);
|
|
127
|
-
return {
|
|
128
|
-
position: [p.x, p.y, p.z],
|
|
129
|
-
rotation: [e.x, e.y, e.z],
|
|
130
|
-
scale: [s.x, s.y, s.z],
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/** Build a local Matrix4 from position/rotation/scale arrays. */
|
|
134
|
-
export function composeTransform(position = [0, 0, 0], rotation = [0, 0, 0], scale = [1, 1, 1]) {
|
|
135
|
-
return new Matrix4().compose(new Vector3(...position), new Quaternion().setFromEuler(new Euler(...rotation)), new Vector3(...scale));
|
|
136
|
-
}
|
|
137
164
|
/** Compute the parent world matrix for a node using the normalized store data */
|
|
138
165
|
export function computeParentWorldMatrix(state, targetId) {
|
|
139
166
|
var _a;
|
package/dist/viewer.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { registerRuntimeComponents } from "./tools/prefabeditor/components/runtime";
|
|
2
|
+
export { registerRuntimeComponents };
|
|
3
|
+
export { default as GameCanvas } from "./shared/GameCanvas";
|
|
4
|
+
export type { GameCanvasProps } from "./shared/GameCanvas";
|
|
5
|
+
export { ground } from "./helpers";
|
|
6
|
+
export type { GroundOptions, Vec3 } from "./helpers";
|
|
7
|
+
export { sound as soundManager } from "./helpers/SoundManager";
|
|
8
|
+
export { default as PrefabRoot } from "./tools/prefabeditor/PrefabRoot";
|
|
9
|
+
export type { PrefabRootProps } from "./tools/prefabeditor/PrefabRoot";
|
|
10
|
+
export { PrefabEditorMode, SceneContext, useScene } from "./tools/prefabeditor/SceneContext";
|
|
11
|
+
export type { PrefabNode, Scene } from "./tools/prefabeditor/SceneContext";
|
|
12
|
+
export type { AssetRuntime, NodeApi, LiveRef } from "./tools/prefabeditor/assetRuntime";
|
|
13
|
+
export { useAssetRuntime, useNode, useNodeHandle, useNodeObject } from "./tools/prefabeditor/assetRuntime";
|
|
14
|
+
export { gameEvents, useClickEvent, useGameEvent } from "./tools/prefabeditor/GameEvents";
|
|
15
|
+
export type { ClickEventPayload, ContactEventPayload, GameEventHandler, GameEventMap } from "./tools/prefabeditor/GameEvents";
|
|
16
|
+
export { registerComponent } from "./tools/prefabeditor/components/ComponentRegistry";
|
|
17
|
+
export type { Component, ComponentViewProps } from "./tools/prefabeditor/components/ComponentRegistry";
|
|
18
|
+
export { denormalizePrefab, createModelNode, createImageNode } from "./tools/prefabeditor/prefab";
|
|
19
|
+
export type { Prefab, GameObject, ComponentData } from "./tools/prefabeditor/types";
|
|
20
|
+
export { findComponent, findComponentEntry, hasComponent } from "./tools/prefabeditor/types";
|
|
21
|
+
export { loadModel, loadSound, loadTexture } from "./tools/dragdrop/modelLoader";
|
|
22
|
+
export type { LoadedModel, LoadedModels, ModelLoadResult, LoadedSound, LoadedSounds, SoundLoadResult, LoadedTexture, LoadedTextures, TextureLoadResult, ProgressCallback, } from "./tools/dragdrop/modelLoader";
|
package/dist/viewer.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { registerRuntimeComponents } from "./tools/prefabeditor/components/runtime";
|
|
2
|
+
registerRuntimeComponents();
|
|
3
|
+
export { registerRuntimeComponents };
|
|
4
|
+
export { default as GameCanvas } from "./shared/GameCanvas";
|
|
5
|
+
export { ground } from "./helpers";
|
|
6
|
+
export { sound as soundManager } from "./helpers/SoundManager";
|
|
7
|
+
export { default as PrefabRoot } from "./tools/prefabeditor/PrefabRoot";
|
|
8
|
+
export { PrefabEditorMode, SceneContext, useScene } from "./tools/prefabeditor/SceneContext";
|
|
9
|
+
export { useAssetRuntime, useNode, useNodeHandle, useNodeObject } from "./tools/prefabeditor/assetRuntime";
|
|
10
|
+
export { gameEvents, useClickEvent, useGameEvent } from "./tools/prefabeditor/GameEvents";
|
|
11
|
+
export { registerComponent } from "./tools/prefabeditor/components/ComponentRegistry";
|
|
12
|
+
export { denormalizePrefab, createModelNode, createImageNode } from "./tools/prefabeditor/prefab";
|
|
13
|
+
export { findComponent, findComponentEntry, hasComponent } from "./tools/prefabeditor/types";
|
|
14
|
+
export { loadModel, loadSound, loadTexture } from "./tools/dragdrop/modelLoader";
|
package/package.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-three-game",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.109",
|
|
4
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
5
|
"exports": {
|
|
9
|
-
"
|
|
10
|
-
"types": "./dist/
|
|
11
|
-
"import": "./dist/
|
|
12
|
-
"default": "./dist/
|
|
6
|
+
"./viewer": {
|
|
7
|
+
"types": "./dist/viewer.d.ts",
|
|
8
|
+
"import": "./dist/viewer.js",
|
|
9
|
+
"default": "./dist/viewer.js"
|
|
10
|
+
},
|
|
11
|
+
"./editor": {
|
|
12
|
+
"types": "./dist/editor.d.ts",
|
|
13
|
+
"import": "./dist/editor.js",
|
|
14
|
+
"default": "./dist/editor.js"
|
|
13
15
|
},
|
|
14
16
|
"./plugins": {
|
|
15
17
|
"types": "./dist/plugins/index.d.ts",
|
|
@@ -57,18 +59,18 @@
|
|
|
57
59
|
}
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
|
-
"@react-three/drei": "
|
|
61
|
-
"@react-three/fiber": "
|
|
62
|
-
"@types/react": "
|
|
63
|
-
"@types/react-dom": "
|
|
64
|
-
"@types/three": "
|
|
65
|
-
"concurrently": "
|
|
66
|
-
"crashcat": "
|
|
67
|
-
"react": "
|
|
68
|
-
"react-dom": "
|
|
69
|
-
"three": "
|
|
70
|
-
"typescript": "
|
|
71
|
-
"vite": "
|
|
62
|
+
"@react-three/drei": ">=10.7.7",
|
|
63
|
+
"@react-three/fiber": ">=9.6.0",
|
|
64
|
+
"@types/react": ">=19.2.9",
|
|
65
|
+
"@types/react-dom": ">=19.2.3",
|
|
66
|
+
"@types/three": ">=0.184.0",
|
|
67
|
+
"concurrently": ">=9.2.1",
|
|
68
|
+
"crashcat": ">=0.0.4",
|
|
69
|
+
"react": ">=19.2.5",
|
|
70
|
+
"react-dom": ">=19.2.5",
|
|
71
|
+
"three": ">=0.184.0",
|
|
72
|
+
"typescript": ">=6.0.3",
|
|
73
|
+
"vite": ">=8.0.10"
|
|
72
74
|
},
|
|
73
75
|
"dependencies": {
|
|
74
76
|
"zustand": "^5.0.12"
|
package/dist/index.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export { default as GameCanvas } from './shared/GameCanvas';
|
|
2
|
-
export type { GameCanvasProps } from './shared/GameCanvas';
|
|
3
|
-
export { ground } from './helpers';
|
|
4
|
-
export type { GroundOptions, Vec3 } from './helpers';
|
|
5
|
-
export { sound as soundManager } from './helpers/SoundManager';
|
|
6
|
-
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
7
|
-
export { PrefabEditorMode } from './tools/prefabeditor/PrefabRoot';
|
|
8
|
-
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
9
|
-
export { useEditorContext, useEditorRef } from './tools/prefabeditor/PrefabEditor';
|
|
10
|
-
export type { EditorContextType } from './tools/prefabeditor/PrefabEditor';
|
|
11
|
-
export { usePrefabStore, usePrefabStoreApi } from './tools/prefabeditor/prefabStore';
|
|
12
|
-
export type { PrefabStoreApi, PrefabStoreState } from './tools/prefabeditor/prefabStore';
|
|
13
|
-
export { denormalizePrefab } from './tools/prefabeditor/prefab';
|
|
14
|
-
export { gameEvents, useClickEvent, useGameEvent } from './tools/prefabeditor/GameEvents';
|
|
15
|
-
export type { ClickEventPayload, ContactEventPayload, GameEventHandler, GameEventMap } from './tools/prefabeditor/GameEvents';
|
|
16
|
-
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
17
|
-
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
18
|
-
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from './tools/prefabeditor/utils';
|
|
19
|
-
export type { ExportGLBOptions } from './tools/prefabeditor/utils';
|
|
20
|
-
export { createModelNode, createImageNode, } from './tools/prefabeditor/prefab';
|
|
21
|
-
export { decomposeModelToPrefabNodes } from './tools/prefabeditor/modelPrefab';
|
|
22
|
-
export type { DecomposeModelOptions } from './tools/prefabeditor/modelPrefab';
|
|
23
|
-
export type { PrefabEditorProps, PrefabNode, PrefabEditorRef, } from './tools/prefabeditor/PrefabEditor';
|
|
24
|
-
export type { PrefabRootProps } from './tools/prefabeditor/PrefabRoot';
|
|
25
|
-
export type { AssetRuntime, NodeApi, LiveRef } from './tools/prefabeditor/assetRuntime';
|
|
26
|
-
export { useAssetRuntime, useNode, useNodeHandle, useNodeObject } from './tools/prefabeditor/assetRuntime';
|
|
27
|
-
export type { Scene } from './tools/prefabeditor/PrefabRoot';
|
|
28
|
-
export { useScene } from './tools/prefabeditor/PrefabRoot';
|
|
29
|
-
export type { Component, ComponentViewProps } from './tools/prefabeditor/components/ComponentRegistry';
|
|
30
|
-
export type { FieldDefinition, FieldType } from './tools/prefabeditor/components/Input';
|
|
31
|
-
export { MaterialOverridesProvider, useMaterialOverrides } from './tools/prefabeditor/components/MaterialComponent';
|
|
32
|
-
export type { MaterialOverrides } from './tools/prefabeditor/components/MaterialComponent';
|
|
33
|
-
export type { Prefab, GameObject, ComponentData } from './tools/prefabeditor/types';
|
|
34
|
-
export { findComponent, findComponentEntry, hasComponent } from './tools/prefabeditor/types';
|
|
35
|
-
export { float, positionLocal, sin, time, uniform, vec3, } from 'three/tsl';
|
|
36
|
-
export { loadFiles } from './tools/dragdrop/DragDropLoader';
|
|
37
|
-
export type { AssetLoadOptions } from './tools/dragdrop/DragDropLoader';
|
|
38
|
-
export { loadModel, loadSound, loadTexture } from './tools/dragdrop/modelLoader';
|
|
39
|
-
export type { LoadedModel, LoadedModels, ModelLoadResult, LoadedSound, LoadedSounds, SoundLoadResult, LoadedTexture, LoadedTextures, TextureLoadResult, ProgressCallback, } from './tools/dragdrop/modelLoader';
|
|
40
|
-
export { ModelListViewer, SoundListViewer, ModelPicker, SoundPicker, TextureListViewer, TexturePicker, SingleModelViewer, SingleSoundViewer, SingleTextureViewer, SharedCanvas, } from './tools/assetviewer/page';
|
package/dist/index.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// Core
|
|
2
|
-
export { default as GameCanvas } from './shared/GameCanvas';
|
|
3
|
-
// Helpers
|
|
4
|
-
export { ground } from './helpers';
|
|
5
|
-
export { sound as soundManager } from './helpers/SoundManager';
|
|
6
|
-
// Prefab Editor
|
|
7
|
-
export { default as PrefabEditor } from './tools/prefabeditor/PrefabEditor';
|
|
8
|
-
export { PrefabEditorMode } from './tools/prefabeditor/PrefabRoot';
|
|
9
|
-
export { default as PrefabRoot } from './tools/prefabeditor/PrefabRoot';
|
|
10
|
-
export { useEditorContext, useEditorRef } from './tools/prefabeditor/PrefabEditor';
|
|
11
|
-
export { usePrefabStore, usePrefabStoreApi } from './tools/prefabeditor/prefabStore';
|
|
12
|
-
// Prefab Editor - Data API
|
|
13
|
-
export { denormalizePrefab } from './tools/prefabeditor/prefab';
|
|
14
|
-
export { gameEvents, useClickEvent, useGameEvent } from './tools/prefabeditor/GameEvents';
|
|
15
|
-
// Prefab Editor - Component Registry
|
|
16
|
-
export { registerComponent } from './tools/prefabeditor/components/ComponentRegistry';
|
|
17
|
-
// Prefab Editor - Input Components
|
|
18
|
-
export { FieldRenderer, FieldGroup, ListEditor, Label, Vector3Input, Vector3Field, NumberField, ColorInput, ColorField, StringInput, StringField, BooleanInput, BooleanField, SelectInput, SelectField, } from './tools/prefabeditor/components/Input';
|
|
19
|
-
// Prefab Editor - Utils
|
|
20
|
-
export { loadJson, saveJson, exportGLB, exportGLBData, regenerateIds, computeParentWorldMatrix, } from './tools/prefabeditor/utils';
|
|
21
|
-
export { createModelNode, createImageNode, } from './tools/prefabeditor/prefab';
|
|
22
|
-
export { decomposeModelToPrefabNodes } from './tools/prefabeditor/modelPrefab';
|
|
23
|
-
export { useAssetRuntime, useNode, useNodeHandle, useNodeObject } from './tools/prefabeditor/assetRuntime';
|
|
24
|
-
export { useScene } from './tools/prefabeditor/PrefabRoot';
|
|
25
|
-
export { MaterialOverridesProvider, useMaterialOverrides } from './tools/prefabeditor/components/MaterialComponent';
|
|
26
|
-
export { findComponent, findComponentEntry, hasComponent } from './tools/prefabeditor/types';
|
|
27
|
-
export { float, positionLocal, sin, time, uniform, vec3, } from 'three/tsl';
|
|
28
|
-
// Asset Loading
|
|
29
|
-
export { loadFiles } from './tools/dragdrop/DragDropLoader';
|
|
30
|
-
export { loadModel, loadSound, loadTexture } from './tools/dragdrop/modelLoader';
|
|
31
|
-
// Asset Viewer
|
|
32
|
-
export { ModelListViewer, SoundListViewer, ModelPicker, SoundPicker, TextureListViewer, TexturePicker, SingleModelViewer, SingleSoundViewer, SingleTextureViewer, SharedCanvas, } from './tools/assetviewer/page';
|