react-three-game 0.0.70 → 0.0.72

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 (34) hide show
  1. package/dist/index.d.ts +9 -5
  2. package/dist/index.js +5 -2
  3. package/dist/tools/prefabeditor/EditorTree.js +2 -12
  4. package/dist/tools/prefabeditor/EditorTreeMenus.js +1 -19
  5. package/dist/tools/prefabeditor/EditorUI.js +2 -1
  6. package/dist/tools/prefabeditor/PrefabEditor.d.ts +1 -3
  7. package/dist/tools/prefabeditor/PrefabEditor.js +23 -42
  8. package/dist/tools/prefabeditor/PrefabRoot.d.ts +39 -13
  9. package/dist/tools/prefabeditor/PrefabRoot.js +105 -49
  10. package/dist/tools/prefabeditor/components/AmbientLightComponent.js +10 -7
  11. package/dist/tools/prefabeditor/components/CameraComponent.js +11 -15
  12. package/dist/tools/prefabeditor/components/ClickComponent.js +5 -1
  13. package/dist/tools/prefabeditor/components/ComponentRegistry.d.ts +15 -1
  14. package/dist/tools/prefabeditor/components/DirectionalLightComponent.js +127 -53
  15. package/dist/tools/prefabeditor/components/EnvironmentComponent.js +5 -3
  16. package/dist/tools/prefabeditor/components/MaterialComponent.js +9 -6
  17. package/dist/tools/prefabeditor/components/ModelComponent.js +4 -2
  18. package/dist/tools/prefabeditor/components/PhysicsComponent.js +6 -3
  19. package/dist/tools/prefabeditor/components/PointLightComponent.d.ts +3 -0
  20. package/dist/tools/prefabeditor/components/PointLightComponent.js +57 -0
  21. package/dist/tools/prefabeditor/components/SoundComponent.js +21 -16
  22. package/dist/tools/prefabeditor/components/SpotLightComponent.js +49 -24
  23. package/dist/tools/prefabeditor/components/index.js +2 -0
  24. package/dist/tools/prefabeditor/components/lightUtils.d.ts +13 -0
  25. package/dist/tools/prefabeditor/components/lightUtils.js +64 -0
  26. package/dist/tools/prefabeditor/prefab.d.ts +37 -0
  27. package/dist/tools/prefabeditor/prefab.js +229 -0
  28. package/dist/tools/prefabeditor/prefabStore.d.ts +3 -16
  29. package/dist/tools/prefabeditor/prefabStore.js +29 -168
  30. package/dist/tools/prefabeditor/{sceneApi.d.ts → scene.d.ts} +6 -2
  31. package/dist/tools/prefabeditor/{sceneApi.js → scene.js} +13 -19
  32. package/dist/tools/prefabeditor/utils.d.ts +0 -4
  33. package/dist/tools/prefabeditor/utils.js +0 -37
  34. package/package.json +1 -1
@@ -0,0 +1,229 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { getComponentAssetRefs, getComponentDef } from './components/ComponentRegistry';
13
+ function clonePrefabValue(value) {
14
+ if (Array.isArray(value)) {
15
+ return value.map(item => clonePrefabValue(item));
16
+ }
17
+ if (value && typeof value === 'object') {
18
+ const clone = {};
19
+ Object.entries(value).forEach(([key, entry]) => {
20
+ clone[key] = clonePrefabValue(entry);
21
+ });
22
+ return clone;
23
+ }
24
+ return value;
25
+ }
26
+ function createComponentMap(components) {
27
+ const componentMap = {
28
+ transform: createComponentData('Transform'),
29
+ };
30
+ Object.entries(components).forEach(([key, component]) => {
31
+ componentMap[key] = createComponentData(component.type, component.properties);
32
+ });
33
+ return componentMap;
34
+ }
35
+ function getNodeNameFromPath(path, name) {
36
+ return name !== null && name !== void 0 ? name : path.replace(/^.*[\/]/, '').replace(/\.[^.]+$/, '');
37
+ }
38
+ function getAssetManifestKey(assetRefCounts) {
39
+ return Object.keys(assetRefCounts).sort().join('|');
40
+ }
41
+ function sameStringArrays(left, right) {
42
+ if (left.length !== right.length)
43
+ return false;
44
+ return left.every((value, index) => value === right[index]);
45
+ }
46
+ function getAssetRefs(node) {
47
+ var _a;
48
+ const refs = [];
49
+ Object.values((_a = node === null || node === void 0 ? void 0 : node.components) !== null && _a !== void 0 ? _a : {}).forEach(component => {
50
+ var _a;
51
+ if (!(component === null || component === void 0 ? void 0 : component.type))
52
+ return;
53
+ for (const ref of getComponentAssetRefs(component.type, (_a = component.properties) !== null && _a !== void 0 ? _a : {})) {
54
+ refs.push(`${ref.type}:${ref.path}`);
55
+ }
56
+ });
57
+ return refs.sort();
58
+ }
59
+ function addAssetRefs(assetRefCounts, refs) {
60
+ refs.forEach(ref => {
61
+ var _a;
62
+ assetRefCounts[ref] = ((_a = assetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) + 1;
63
+ });
64
+ }
65
+ function removeAssetRefs(assetRefCounts, refs) {
66
+ refs.forEach(ref => {
67
+ var _a;
68
+ const nextCount = ((_a = assetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) - 1;
69
+ if (nextCount > 0) {
70
+ assetRefCounts[ref] = nextCount;
71
+ return;
72
+ }
73
+ delete assetRefCounts[ref];
74
+ });
75
+ }
76
+ function createAssetRefCounts(nodesById) {
77
+ const assetRefCounts = {};
78
+ Object.values(nodesById).forEach(node => addAssetRefs(assetRefCounts, getAssetRefs(node)));
79
+ return assetRefCounts;
80
+ }
81
+ function denormalizeNode(id, nodesById, childIdsById) {
82
+ var _a;
83
+ 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)) });
85
+ }
86
+ export function createDefaultComponentProperties(type) {
87
+ var _a, _b;
88
+ return clonePrefabValue((_b = (_a = getComponentDef(type)) === null || _a === void 0 ? void 0 : _a.defaultProperties) !== null && _b !== void 0 ? _b : {});
89
+ }
90
+ export function createComponentData(type, properties) {
91
+ return {
92
+ type,
93
+ properties: properties ? clonePrefabValue(properties) : createDefaultComponentProperties(type),
94
+ };
95
+ }
96
+ export function createNode(name, components = {}, options) {
97
+ var _a;
98
+ 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
+ }
100
+ export function createEmptyNode(name = 'New Node') {
101
+ return createNode(name);
102
+ }
103
+ export function createEmptyPrefab() {
104
+ return {
105
+ id: crypto.randomUUID(),
106
+ name: 'New Prefab',
107
+ root: createNode('Root', {}, { id: crypto.randomUUID(), children: [] }),
108
+ };
109
+ }
110
+ export function createModelNode(filename, name) {
111
+ return createNode(getNodeNameFromPath(filename, name), {
112
+ model: {
113
+ type: 'Model',
114
+ properties: {
115
+ filename,
116
+ instanced: false,
117
+ repeat: false,
118
+ repeatAxes: [{ axis: 'x', count: 1, offset: 1 }],
119
+ },
120
+ },
121
+ });
122
+ }
123
+ export function createImageNode(texturePath, name) {
124
+ return createNode(getNodeNameFromPath(texturePath, name), {
125
+ geometry: {
126
+ type: 'Geometry',
127
+ properties: { geometryType: 'plane', args: [1, 1] },
128
+ },
129
+ material: {
130
+ type: 'Material',
131
+ properties: { color: '#ffffff', texture: texturePath },
132
+ },
133
+ });
134
+ }
135
+ export function normalizePrefab(prefab, revision = 0) {
136
+ const nodesById = {};
137
+ const childIdsById = {};
138
+ const parentIdById = {};
139
+ insertSubtree(prefab.root, null, nodesById, childIdsById, parentIdById);
140
+ const assetRefCounts = createAssetRefCounts(nodesById);
141
+ return {
142
+ prefabId: prefab.id,
143
+ prefabName: prefab.name,
144
+ rootId: prefab.root.id,
145
+ nodesById,
146
+ childIdsById,
147
+ parentIdById,
148
+ revision,
149
+ assetManifestKey: getAssetManifestKey(assetRefCounts),
150
+ assetRefCounts,
151
+ };
152
+ }
153
+ export function createPrefabPatch(state, patch, nextAssetRefCounts = state.assetRefCounts) {
154
+ const assetRefsChanged = nextAssetRefCounts !== state.assetRefCounts;
155
+ return Object.assign(Object.assign(Object.assign({}, patch), { revision: state.revision + 1 }), (assetRefsChanged ? {
156
+ assetRefCounts: nextAssetRefCounts,
157
+ assetManifestKey: getAssetManifestKey(nextAssetRefCounts),
158
+ } : null));
159
+ }
160
+ export function denormalizePrefab(state) {
161
+ return {
162
+ id: state.prefabId,
163
+ name: state.prefabName,
164
+ root: denormalizeNode(state.rootId, state.nodesById, state.childIdsById),
165
+ };
166
+ }
167
+ export function collectSubtreeIds(id, childIdsById) {
168
+ var _a;
169
+ const ids = [id];
170
+ for (const childId of (_a = childIdsById[id]) !== null && _a !== void 0 ? _a : []) {
171
+ ids.push(...collectSubtreeIds(childId, childIdsById));
172
+ }
173
+ return ids;
174
+ }
175
+ export function insertSubtree(node, parentId, nodesById, childIdsById, parentIdById) {
176
+ var _a;
177
+ const { children } = node, nodeRecord = __rest(node, ["children"]);
178
+ nodesById[node.id] = nodeRecord;
179
+ childIdsById[node.id] = (_a = children === null || children === void 0 ? void 0 : children.map(child => child.id)) !== null && _a !== void 0 ? _a : [];
180
+ parentIdById[node.id] = parentId;
181
+ children === null || children === void 0 ? void 0 : children.forEach(child => insertSubtree(child, node.id, nodesById, childIdsById, parentIdById));
182
+ }
183
+ export function cloneSubtree(id, parentId, source, nodesById, childIdsById, parentIdById) {
184
+ var _a, _b;
185
+ const originalNode = source.nodesById[id];
186
+ if (!originalNode)
187
+ return null;
188
+ const clonedId = crypto.randomUUID();
189
+ const clonedNode = Object.assign(Object.assign({}, originalNode), { id: clonedId, name: `${(_a = originalNode.name) !== null && _a !== void 0 ? _a : originalNode.id} Copy` });
190
+ nodesById[clonedId] = clonedNode;
191
+ parentIdById[clonedId] = parentId;
192
+ const clonedChildIds = ((_b = source.childIdsById[id]) !== null && _b !== void 0 ? _b : [])
193
+ .map(childId => cloneSubtree(childId, clonedId, source, nodesById, childIdsById, parentIdById))
194
+ .filter((childId) => Boolean(childId));
195
+ childIdsById[clonedId] = clonedChildIds;
196
+ return clonedId;
197
+ }
198
+ export function isDescendant(id, potentialAncestorId, parentIdById) {
199
+ let currentId = id;
200
+ while (currentId) {
201
+ if (currentId === potentialAncestorId)
202
+ return true;
203
+ currentId = parentIdById[currentId];
204
+ }
205
+ return false;
206
+ }
207
+ export function updateAssetRefsForNodeChange(assetRefCounts, currentNode, nextNode) {
208
+ const currentRefs = getAssetRefs(currentNode);
209
+ const nextRefs = getAssetRefs(nextNode);
210
+ if (sameStringArrays(currentRefs, nextRefs)) {
211
+ return assetRefCounts;
212
+ }
213
+ const nextAssetRefCounts = Object.assign({}, assetRefCounts);
214
+ removeAssetRefs(nextAssetRefCounts, currentRefs);
215
+ addAssetRefs(nextAssetRefCounts, nextRefs);
216
+ return nextAssetRefCounts;
217
+ }
218
+ export function collectSubtreeAssetRefs(node) {
219
+ var _a;
220
+ const refs = getAssetRefs(node);
221
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(child => refs.push(...collectSubtreeAssetRefs(child)));
222
+ return refs;
223
+ }
224
+ export function collectAssetRefsForIds(ids, nodesById) {
225
+ return ids.reduce((refs, id) => {
226
+ refs.push(...getAssetRefs(nodesById[id]));
227
+ return refs;
228
+ }, []);
229
+ }
@@ -1,20 +1,8 @@
1
1
  import { type ReactNode } from "react";
2
2
  import { type StoreApi } from "zustand/vanilla";
3
3
  import { GameObject, Prefab } from "./types";
4
- export type PrefabNodeRecord = Omit<GameObject, "children">;
5
- type PrefabAssetRefCounts = Record<string, number>;
6
- type PrefabDocumentSnapshot = {
7
- prefabId?: string;
8
- prefabName?: string;
9
- rootId: string;
10
- nodesById: Record<string, PrefabNodeRecord>;
11
- childIdsById: Record<string, string[]>;
12
- parentIdById: Record<string, string | null>;
13
- revision: number;
14
- assetManifestKey: string;
15
- assetRefCounts: PrefabAssetRefCounts;
16
- };
17
- export interface PrefabStoreState extends PrefabDocumentSnapshot {
4
+ import { denormalizePrefab, PrefabState, PrefabNodeRecord } from "./prefab";
5
+ export interface PrefabStoreState extends PrefabState {
18
6
  replacePrefab: (prefab: Prefab) => void;
19
7
  updateNode: (id: string, update: (node: PrefabNodeRecord) => PrefabNodeRecord) => void;
20
8
  updateNodes: (updates: Array<{
@@ -39,5 +27,4 @@ export declare function usePrefabRootId(): string;
39
27
  export declare function usePrefabNode(nodeId: string | null | undefined): PrefabNodeRecord | null;
40
28
  export declare function usePrefabChildIds(nodeId: string | null | undefined): string[];
41
29
  export declare function createPrefabStore(prefab: Prefab): PrefabStoreApi;
42
- export declare function prefabStoreToPrefab(state: Pick<PrefabDocumentSnapshot, "prefabId" | "prefabName" | "rootId" | "nodesById" | "childIdsById">): Prefab;
43
- export {};
30
+ export declare const prefabStoreToPrefab: typeof denormalizePrefab;
@@ -1,19 +1,8 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
1
  import { createContext, createElement, useContext } from "react";
13
2
  import { subscribeWithSelector } from "zustand/middleware";
14
3
  import { useStore } from "zustand";
15
4
  import { createStore } from "zustand/vanilla";
16
- import { getComponentAssetRefs } from "./components/ComponentRegistry";
5
+ import { collectAssetRefsForIds, collectSubtreeAssetRefs, collectSubtreeIds, cloneSubtree, createPrefabPatch, denormalizePrefab, insertSubtree, isDescendant, normalizePrefab, updateAssetRefsForNodeChange, } from "./prefab";
17
6
  const PrefabStoreContext = createContext(null);
18
7
  const EMPTY_CHILD_IDS = [];
19
8
  export function PrefabStoreProvider({ store, children, }) {
@@ -42,8 +31,8 @@ export function usePrefabChildIds(nodeId) {
42
31
  return usePrefabStore(state => { var _a; return nodeId ? (_a = state.childIdsById[nodeId]) !== null && _a !== void 0 ? _a : EMPTY_CHILD_IDS : EMPTY_CHILD_IDS; });
43
32
  }
44
33
  export function createPrefabStore(prefab) {
45
- return createStore()(subscribeWithSelector((set, get) => (Object.assign(Object.assign({}, createDocumentState(prefab)), { replacePrefab: (nextPrefab) => {
46
- set(createDocumentState(nextPrefab, get().revision + 1));
34
+ return createStore()(subscribeWithSelector((set, get) => (Object.assign(Object.assign({}, normalizePrefab(prefab)), { replacePrefab: (nextPrefab) => {
35
+ set(normalizePrefab(nextPrefab, get().revision + 1));
47
36
  }, updateNode: (id, update) => {
48
37
  const state = get();
49
38
  const node = state.nodesById[id];
@@ -53,7 +42,7 @@ export function createPrefabStore(prefab) {
53
42
  if (nextNode === node)
54
43
  return;
55
44
  const nextAssetRefCounts = updateAssetRefsForNodeChange(state.assetRefCounts, node, nextNode);
56
- set(createMutationPatch(state, {
45
+ set(createPrefabPatch(state, {
57
46
  nodesById: Object.assign(Object.assign({}, state.nodesById), { [id]: nextNode }),
58
47
  }, nextAssetRefCounts));
59
48
  }, updateNodes: (updates) => {
@@ -75,7 +64,7 @@ export function createPrefabStore(prefab) {
75
64
  }
76
65
  if (!nextNodesById)
77
66
  return;
78
- set(createMutationPatch(state, { nodesById: nextNodesById }, nextAssetRefCounts));
67
+ set(createPrefabPatch(state, { nodesById: nextNodesById }, nextAssetRefCounts));
79
68
  }, addChild: (parentId, node) => {
80
69
  var _a;
81
70
  const state = get();
@@ -87,8 +76,11 @@ export function createPrefabStore(prefab) {
87
76
  const nextAssetRefCounts = Object.assign({}, state.assetRefCounts);
88
77
  insertSubtree(node, parentId, nextNodesById, nextChildIdsById, nextParentIdById);
89
78
  nextChildIdsById[parentId] = [...((_a = nextChildIdsById[parentId]) !== null && _a !== void 0 ? _a : []), node.id];
90
- addAssetRefs(nextAssetRefCounts, collectSubtreeAssetRefs(node));
91
- set(createMutationPatch(state, {
79
+ collectSubtreeAssetRefs(node).forEach(ref => {
80
+ var _a;
81
+ nextAssetRefCounts[ref] = ((_a = nextAssetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) + 1;
82
+ });
83
+ set(createPrefabPatch(state, {
92
84
  nodesById: nextNodesById,
93
85
  childIdsById: nextChildIdsById,
94
86
  parentIdById: nextParentIdById,
@@ -106,14 +98,22 @@ export function createPrefabStore(prefab) {
106
98
  const nextChildIdsById = Object.assign({}, state.childIdsById);
107
99
  const nextParentIdById = Object.assign({}, state.parentIdById);
108
100
  const nextAssetRefCounts = Object.assign({}, state.assetRefCounts);
109
- removeAssetRefs(nextAssetRefCounts, collectAssetRefsForIds(idsToDelete, state.nodesById));
101
+ collectAssetRefsForIds(idsToDelete, state.nodesById).forEach(ref => {
102
+ var _a;
103
+ const nextCount = ((_a = nextAssetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) - 1;
104
+ if (nextCount > 0) {
105
+ nextAssetRefCounts[ref] = nextCount;
106
+ return;
107
+ }
108
+ delete nextAssetRefCounts[ref];
109
+ });
110
110
  idsToDelete.forEach(nodeId => {
111
111
  delete nextNodesById[nodeId];
112
112
  delete nextChildIdsById[nodeId];
113
113
  delete nextParentIdById[nodeId];
114
114
  });
115
115
  nextChildIdsById[parentId] = ((_a = nextChildIdsById[parentId]) !== null && _a !== void 0 ? _a : []).filter(childId => childId !== id);
116
- set(createMutationPatch(state, {
116
+ set(createPrefabPatch(state, {
117
117
  nodesById: nextNodesById,
118
118
  childIdsById: nextChildIdsById,
119
119
  parentIdById: nextParentIdById,
@@ -129,7 +129,7 @@ export function createPrefabStore(prefab) {
129
129
  const nextNodesById = Object.assign({}, state.nodesById);
130
130
  const nextChildIdsById = Object.assign({}, state.childIdsById);
131
131
  const nextParentIdById = Object.assign({}, state.parentIdById);
132
- const duplicatedRootId = cloneSubtreeIntoMaps(id, parentId, state, nextNodesById, nextChildIdsById, nextParentIdById);
132
+ const duplicatedRootId = cloneSubtree(id, parentId, state, nextNodesById, nextChildIdsById, nextParentIdById);
133
133
  if (!duplicatedRootId)
134
134
  return null;
135
135
  const siblings = [...((_a = nextChildIdsById[parentId]) !== null && _a !== void 0 ? _a : [])];
@@ -142,8 +142,11 @@ export function createPrefabStore(prefab) {
142
142
  }
143
143
  nextChildIdsById[parentId] = siblings;
144
144
  const nextAssetRefCounts = Object.assign({}, state.assetRefCounts);
145
- addAssetRefs(nextAssetRefCounts, collectAssetRefsForIds(collectSubtreeIds(id, state.childIdsById), state.nodesById));
146
- set(createMutationPatch(state, {
145
+ collectAssetRefsForIds(collectSubtreeIds(id, state.childIdsById), state.nodesById).forEach(ref => {
146
+ var _a;
147
+ nextAssetRefCounts[ref] = ((_a = nextAssetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) + 1;
148
+ });
149
+ set(createPrefabPatch(state, {
147
150
  nodesById: nextNodesById,
148
151
  childIdsById: nextChildIdsById,
149
152
  parentIdById: nextParentIdById,
@@ -155,7 +158,7 @@ export function createPrefabStore(prefab) {
155
158
  if (!node)
156
159
  return;
157
160
  const nextNode = Object.assign(Object.assign({}, node), { [key]: !node[key] });
158
- set(createMutationPatch(state, {
161
+ set(createPrefabPatch(state, {
159
162
  nodesById: Object.assign(Object.assign({}, state.nodesById), { [id]: nextNode }),
160
163
  }));
161
164
  }, moveNode: (draggedId, targetId, position) => {
@@ -194,152 +197,10 @@ export function createPrefabStore(prefab) {
194
197
  destinationChildren.splice(targetIndex, 0, draggedId);
195
198
  nextChildIdsById[destinationParentId] = destinationChildren;
196
199
  }
197
- set(createMutationPatch(state, {
200
+ set(createPrefabPatch(state, {
198
201
  childIdsById: nextChildIdsById,
199
202
  parentIdById: nextParentIdById,
200
203
  }));
201
204
  } }))));
202
205
  }
203
- export function prefabStoreToPrefab(state) {
204
- return {
205
- id: state.prefabId,
206
- name: state.prefabName,
207
- root: denormalizeNode(state.rootId, state.nodesById, state.childIdsById),
208
- };
209
- }
210
- function createDocumentState(prefab, revision = 0) {
211
- const nodesById = {};
212
- const childIdsById = {};
213
- const parentIdById = {};
214
- insertSubtree(prefab.root, null, nodesById, childIdsById, parentIdById);
215
- const assetRefCounts = createAssetRefCounts(nodesById);
216
- return {
217
- prefabId: prefab.id,
218
- prefabName: prefab.name,
219
- rootId: prefab.root.id,
220
- nodesById,
221
- childIdsById,
222
- parentIdById,
223
- revision,
224
- assetManifestKey: getAssetManifestKey(assetRefCounts),
225
- assetRefCounts,
226
- };
227
- }
228
- function createMutationPatch(state, patch, nextAssetRefCounts = state.assetRefCounts) {
229
- const assetRefsChanged = nextAssetRefCounts !== state.assetRefCounts;
230
- return Object.assign(Object.assign(Object.assign({}, patch), { revision: state.revision + 1 }), (assetRefsChanged ? {
231
- assetRefCounts: nextAssetRefCounts,
232
- assetManifestKey: getAssetManifestKey(nextAssetRefCounts),
233
- } : null));
234
- }
235
- function denormalizeNode(id, nodesById, childIdsById) {
236
- var _a;
237
- const node = nodesById[id];
238
- return Object.assign(Object.assign({}, node), { children: ((_a = childIdsById[id]) !== null && _a !== void 0 ? _a : []).map(childId => denormalizeNode(childId, nodesById, childIdsById)) });
239
- }
240
- function collectSubtreeIds(id, childIdsById) {
241
- var _a;
242
- const ids = [id];
243
- for (const childId of (_a = childIdsById[id]) !== null && _a !== void 0 ? _a : []) {
244
- ids.push(...collectSubtreeIds(childId, childIdsById));
245
- }
246
- return ids;
247
- }
248
- function insertSubtree(node, parentId, nodesById, childIdsById, parentIdById) {
249
- var _a;
250
- const { children } = node, nodeRecord = __rest(node, ["children"]);
251
- nodesById[node.id] = nodeRecord;
252
- childIdsById[node.id] = (_a = children === null || children === void 0 ? void 0 : children.map(child => child.id)) !== null && _a !== void 0 ? _a : [];
253
- parentIdById[node.id] = parentId;
254
- children === null || children === void 0 ? void 0 : children.forEach(child => insertSubtree(child, node.id, nodesById, childIdsById, parentIdById));
255
- }
256
- function cloneSubtreeIntoMaps(id, parentId, source, nodesById, childIdsById, parentIdById) {
257
- var _a, _b;
258
- const originalNode = source.nodesById[id];
259
- if (!originalNode)
260
- return null;
261
- const clonedId = crypto.randomUUID();
262
- const clonedNode = Object.assign(Object.assign({}, originalNode), { id: clonedId, name: `${(_a = originalNode.name) !== null && _a !== void 0 ? _a : originalNode.id} Copy` });
263
- nodesById[clonedId] = clonedNode;
264
- parentIdById[clonedId] = parentId;
265
- const clonedChildIds = ((_b = source.childIdsById[id]) !== null && _b !== void 0 ? _b : [])
266
- .map(childId => cloneSubtreeIntoMaps(childId, clonedId, source, nodesById, childIdsById, parentIdById))
267
- .filter((childId) => Boolean(childId));
268
- childIdsById[clonedId] = clonedChildIds;
269
- return clonedId;
270
- }
271
- function isDescendant(id, potentialAncestorId, parentIdById) {
272
- let currentId = id;
273
- while (currentId) {
274
- if (currentId === potentialAncestorId)
275
- return true;
276
- currentId = parentIdById[currentId];
277
- }
278
- return false;
279
- }
280
- function createAssetRefCounts(nodesById) {
281
- const assetRefCounts = {};
282
- Object.values(nodesById).forEach(node => addAssetRefs(assetRefCounts, getAssetRefs(node)));
283
- return assetRefCounts;
284
- }
285
- function updateAssetRefsForNodeChange(assetRefCounts, currentNode, nextNode) {
286
- const currentRefs = getAssetRefs(currentNode);
287
- const nextRefs = getAssetRefs(nextNode);
288
- if (sameStringArrays(currentRefs, nextRefs)) {
289
- return assetRefCounts;
290
- }
291
- const nextAssetRefCounts = Object.assign({}, assetRefCounts);
292
- removeAssetRefs(nextAssetRefCounts, currentRefs);
293
- addAssetRefs(nextAssetRefCounts, nextRefs);
294
- return nextAssetRefCounts;
295
- }
296
- function collectSubtreeAssetRefs(node) {
297
- var _a;
298
- const refs = getAssetRefs(node);
299
- (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(child => refs.push(...collectSubtreeAssetRefs(child)));
300
- return refs;
301
- }
302
- function collectAssetRefsForIds(ids, nodesById) {
303
- return ids.reduce((refs, id) => {
304
- refs.push(...getAssetRefs(nodesById[id]));
305
- return refs;
306
- }, []);
307
- }
308
- function getAssetRefs(node) {
309
- var _a;
310
- const refs = [];
311
- Object.values((_a = node === null || node === void 0 ? void 0 : node.components) !== null && _a !== void 0 ? _a : {}).forEach(component => {
312
- var _a;
313
- if (!(component === null || component === void 0 ? void 0 : component.type))
314
- return;
315
- for (const ref of getComponentAssetRefs(component.type, (_a = component.properties) !== null && _a !== void 0 ? _a : {})) {
316
- refs.push(`${ref.type}:${ref.path}`);
317
- }
318
- });
319
- return refs.sort();
320
- }
321
- function addAssetRefs(assetRefCounts, refs) {
322
- refs.forEach(ref => {
323
- var _a;
324
- assetRefCounts[ref] = ((_a = assetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) + 1;
325
- });
326
- }
327
- function removeAssetRefs(assetRefCounts, refs) {
328
- refs.forEach(ref => {
329
- var _a;
330
- const nextCount = ((_a = assetRefCounts[ref]) !== null && _a !== void 0 ? _a : 0) - 1;
331
- if (nextCount > 0) {
332
- assetRefCounts[ref] = nextCount;
333
- return;
334
- }
335
- delete assetRefCounts[ref];
336
- });
337
- }
338
- function getAssetManifestKey(assetRefCounts) {
339
- return Object.keys(assetRefCounts).sort().join("|");
340
- }
341
- function sameStringArrays(left, right) {
342
- if (left.length !== right.length)
343
- return false;
344
- return left.every((value, index) => value === right[index]);
345
- }
206
+ export const prefabStoreToPrefab = denormalizePrefab;
@@ -1,3 +1,4 @@
1
+ import type { Object3D } from "three";
1
2
  import type { GameObject } from "./types";
2
3
  export interface SpawnOptions {
3
4
  name?: string;
@@ -19,6 +20,8 @@ export interface Entity {
19
20
  readonly enabled: boolean;
20
21
  readonly parent: Entity | null;
21
22
  readonly children: Entity[];
23
+ readonly object: Object3D | null;
24
+ readonly rigidBody: any;
22
25
  set: (data: EntityData) => void;
23
26
  update: (update: (node: EntityData) => EntityData) => void;
24
27
  getComponent: <TProperties = Record<string, any>>(name: string) => EntityComponent<TProperties> | null;
@@ -30,7 +33,7 @@ export type EntityUpdate = (node: EntityData) => EntityData;
30
33
  export type SceneUpdates = Record<string, EntityUpdate>;
31
34
  export interface Scene {
32
35
  readonly rootId: string;
33
- find: (nameOrId: string) => Entity | null;
36
+ find: (id: string) => Entity | null;
34
37
  get: (id: string) => Entity;
35
38
  create: (name: string, components?: Record<string, {
36
39
  type: string;
@@ -48,11 +51,12 @@ interface SceneAdapter {
48
51
  getNode: (id: string) => EntityData | null;
49
52
  getChildIds: (id: string) => string[];
50
53
  getParentId: (id: string) => string | null;
51
- findByName: (name: string) => string | null;
52
54
  updateNode: (id: string, update: (node: EntityData) => EntityData) => void;
53
55
  updateNodes: (updates: Record<string, (node: EntityData) => EntityData>) => void;
54
56
  addNode: (node: GameObject, options?: SpawnOptions) => string;
55
57
  removeNode: (id: string) => void;
58
+ getObject?: (id: string) => Object3D | null;
59
+ getRigidBody?: (id: string) => any;
56
60
  }
57
61
  export declare function createScene(adapter: SceneAdapter): Scene;
58
62
  export {};
@@ -10,7 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { findComponentEntry } from "./types";
13
- import { getComponentDef } from "./components/ComponentRegistry";
13
+ import { createComponentData, createNode as createPrefabNode } from "./prefab";
14
14
  function missingNode(id) {
15
15
  throw new Error(`Scene node not found: ${id}`);
16
16
  }
@@ -119,6 +119,14 @@ export function createScene(adapter) {
119
119
  get children() {
120
120
  return adapter.getChildIds(id).map(createNode);
121
121
  },
122
+ get object() {
123
+ var _a, _b;
124
+ return (_b = (_a = adapter.getObject) === null || _a === void 0 ? void 0 : _a.call(adapter, id)) !== null && _b !== void 0 ? _b : null;
125
+ },
126
+ get rigidBody() {
127
+ var _a, _b;
128
+ return (_b = (_a = adapter.getRigidBody) === null || _a === void 0 ? void 0 : _a.call(adapter, id)) !== null && _b !== void 0 ? _b : null;
129
+ },
122
130
  set(data) {
123
131
  adapter.updateNode(id, () => data);
124
132
  },
@@ -136,11 +144,8 @@ export function createScene(adapter) {
136
144
  return createComponent(id, componentKey, component.type);
137
145
  },
138
146
  addComponent(type, properties) {
139
- var _a;
140
- const def = getComponentDef(type);
141
147
  const key = type.toLowerCase();
142
- const props = (_a = properties !== null && properties !== void 0 ? properties : def === null || def === void 0 ? void 0 : def.defaultProperties) !== null && _a !== void 0 ? _a : {};
143
- adapter.updateNode(id, node => (Object.assign(Object.assign({}, node), { components: Object.assign(Object.assign({}, node.components), { [key]: { type, properties: props } }) })));
148
+ adapter.updateNode(id, node => (Object.assign(Object.assign({}, node), { components: Object.assign(Object.assign({}, node.components), { [key]: createComponentData(type, properties) }) })));
144
149
  return createComponent(id, key, type);
145
150
  },
146
151
  removeComponent(name) {
@@ -176,23 +181,12 @@ export function createScene(adapter) {
176
181
  get rootId() {
177
182
  return adapter.getRootId();
178
183
  },
179
- find(nameOrId) {
180
- // Try by ID first, then by name
181
- if (adapter.getNode(nameOrId))
182
- return createNode(nameOrId);
183
- const foundId = adapter.findByName(nameOrId);
184
- return foundId ? createNode(foundId) : null;
184
+ find(id) {
185
+ return adapter.getNode(id) ? createNode(id) : null;
185
186
  },
186
187
  get: getNode,
187
188
  create(name, components, options) {
188
- const node = {
189
- id: crypto.randomUUID(),
190
- name,
191
- components: Object.assign({ transform: {
192
- type: "Transform",
193
- properties: { position: [0, 0, 0], rotation: [0, 0, 0], scale: [1, 1, 1] },
194
- } }, components),
195
- };
189
+ const node = createPrefabNode(name, components);
196
190
  return createNode(adapter.addNode(node, options));
197
191
  },
198
192
  update,
@@ -34,7 +34,3 @@ export declare function computeParentWorldMatrix(state: {
34
34
  }, targetId: string): Matrix4;
35
35
  /** Recursively update all IDs in a node tree */
36
36
  export declare function regenerateIds(node: GameObject): GameObject;
37
- /** Create a GameObject node for a 3D model file */
38
- export declare function createModelNode(filename: string, name?: string): GameObject;
39
- /** Create a GameObject node for an image as a textured plane */
40
- export declare function createImageNode(texturePath: string, name?: string): GameObject;