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
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
11
|
var t = {};
|
|
3
12
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -10,25 +19,22 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
19
|
return t;
|
|
11
20
|
};
|
|
12
21
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
|
-
import {
|
|
22
|
+
import { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
14
23
|
import { Euler, Matrix4 } from "three";
|
|
24
|
+
import { useThree } from "@react-three/fiber";
|
|
15
25
|
import { useStore } from "zustand";
|
|
16
26
|
import { useClickValid } from "./useClickValid";
|
|
17
27
|
import { findComponent, getNodeUserData } from "./types";
|
|
18
|
-
import { getComponentDef
|
|
19
|
-
import { builtinComponents } from "./components";
|
|
28
|
+
import { getComponentDef } from "./components/ComponentRegistry";
|
|
20
29
|
import { loadModel, loadSound, loadTexture } from "../dragdrop";
|
|
21
30
|
import { GameInstance, GameInstanceProvider, getRepeatAxesFromModelProperties } from "./InstanceProvider";
|
|
22
|
-
import { composeTransform, decompose } from "./
|
|
31
|
+
import { composeTransform, decompose, withBasePath } from "./runtimeUtils";
|
|
23
32
|
import { createPrefabStore, PrefabStoreProvider, usePrefabChildIds, usePrefabNode, usePrefabRootId } from "./prefabStore";
|
|
24
33
|
import { AssetRuntimeContext, NodeScope } from "./assetRuntime";
|
|
25
34
|
import { gameEvents } from "./GameEvents";
|
|
26
35
|
import { sound as soundManager } from "../../helpers/SoundManager";
|
|
27
|
-
|
|
36
|
+
import { PrefabEditorMode, SceneContext } from "./SceneContext";
|
|
28
37
|
const IDENTITY = new Matrix4();
|
|
29
|
-
const EMPTY_MODELS = {};
|
|
30
|
-
const EMPTY_TEXTURES = {};
|
|
31
|
-
const EMPTY_SOUNDS = {};
|
|
32
38
|
const EMPTY_NODE_COMPONENTS = {
|
|
33
39
|
geometry: undefined,
|
|
34
40
|
materials: [],
|
|
@@ -37,13 +43,19 @@ const EMPTY_NODE_COMPONENTS = {
|
|
|
37
43
|
clickEventName: null,
|
|
38
44
|
composition: [],
|
|
39
45
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
function precompileModel(model, renderer, camera) {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
try {
|
|
49
|
+
if (typeof renderer.compileAsync === "function") {
|
|
50
|
+
yield renderer.compileAsync(model, camera);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
renderer.compile(model, camera);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.warn("Failed to precompile model before adding it to the scene", error);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
47
59
|
}
|
|
48
60
|
/** Check if a model component's assets are loaded. */
|
|
49
61
|
function isNodeReady(model, loadedModels) {
|
|
@@ -60,30 +72,19 @@ function getNodeMetadataProps(node) {
|
|
|
60
72
|
userData: Object.assign(Object.assign({ prefabNodeId: node.id }, (nodeName ? { prefabNodeName: nodeName } : {})), getNodeUserData(node)),
|
|
61
73
|
};
|
|
62
74
|
}
|
|
63
|
-
export var PrefabEditorMode;
|
|
64
|
-
(function (PrefabEditorMode) {
|
|
65
|
-
PrefabEditorMode["Edit"] = "edit";
|
|
66
|
-
PrefabEditorMode["Play"] = "play";
|
|
67
|
-
})(PrefabEditorMode || (PrefabEditorMode = {}));
|
|
68
|
-
export const SceneContext = createContext(null);
|
|
69
|
-
export function useScene() {
|
|
70
|
-
const scene = useContext(SceneContext);
|
|
71
|
-
if (!scene) {
|
|
72
|
-
throw new Error("useScene must be used within a PrefabRoot or PrefabEditor scene provider");
|
|
73
|
-
}
|
|
74
|
-
return scene;
|
|
75
|
-
}
|
|
76
75
|
export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSelect, onClick, onEditNodeClick, basePath = "", children }, ref) => {
|
|
76
|
+
const parentScene = useContext(SceneContext);
|
|
77
|
+
const parentAssetRuntime = useContext(AssetRuntimeContext);
|
|
78
|
+
const renderer = useThree(state => state.gl);
|
|
79
|
+
const camera = useThree(state => state.camera);
|
|
77
80
|
const [models, setModels] = useState({});
|
|
78
81
|
const [textures, setTextures] = useState({});
|
|
79
82
|
const [sounds, setSounds] = useState({});
|
|
80
|
-
const [injectedModels, setInjectedModels] = useState(EMPTY_MODELS);
|
|
81
|
-
const [injectedTextures, setInjectedTextures] = useState(EMPTY_TEXTURES);
|
|
82
|
-
const [injectedSounds, setInjectedSounds] = useState(EMPTY_SOUNDS);
|
|
83
83
|
const loading = useRef(new Set());
|
|
84
84
|
const failedModels = useRef(new Set());
|
|
85
85
|
const failedTextures = useRef(new Set());
|
|
86
86
|
const failedSounds = useRef(new Set());
|
|
87
|
+
const injectedModelVersions = useRef({});
|
|
87
88
|
const objectRefs = useRef({});
|
|
88
89
|
const nodeHandles = useRef(new Map());
|
|
89
90
|
const [ownedStore] = useState(() => {
|
|
@@ -100,19 +101,18 @@ export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSel
|
|
|
100
101
|
const usesOwnedStore = resolvedStore === ownedStore;
|
|
101
102
|
const rootId = useStore(resolvedStore, state => state.rootId);
|
|
102
103
|
const assetRefCounts = useStore(resolvedStore, state => state.assetRefCounts);
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
const assetRevision = useMemo(() => `${Object.keys(textures).concat(Object.keys(injectedTextures)).sort().join('|')}::${Object.keys(availableModels).sort().join('|')}`, [availableModels, injectedTextures, textures]);
|
|
104
|
+
const getModel = useCallback((path) => { var _a, _b; return (_b = (_a = models[path]) !== null && _a !== void 0 ? _a : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getModel(path)) !== null && _b !== void 0 ? _b : null; }, [models, parentAssetRuntime]);
|
|
105
|
+
const getTexture = useCallback((path) => { var _a, _b; return (_b = (_a = textures[path]) !== null && _a !== void 0 ? _a : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getTexture(path)) !== null && _b !== void 0 ? _b : null; }, [parentAssetRuntime, textures]);
|
|
106
|
+
const getSound = useCallback((path) => { var _a, _b; return (_b = (_a = sounds[path]) !== null && _a !== void 0 ? _a : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getSound(path)) !== null && _b !== void 0 ? _b : null; }, [parentAssetRuntime, sounds]);
|
|
107
|
+
const assetRevision = useMemo(() => { var _a; return `${(_a = parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getAssetRevision()) !== null && _a !== void 0 ? _a : ""}::${Object.keys(textures).sort().join('|')}::${Object.keys(models).sort().join('|')}`; }, [models, parentAssetRuntime, textures]);
|
|
108
108
|
const getObject = useCallback((id) => {
|
|
109
|
-
var _a;
|
|
110
|
-
return (_a = objectRefs.current[id]) !== null && _a !== void 0 ? _a : null;
|
|
111
|
-
}, []);
|
|
112
|
-
const getHandle = useCallback((id, kind) => {
|
|
113
109
|
var _a, _b;
|
|
114
|
-
return (_b = (_a =
|
|
115
|
-
}, []);
|
|
110
|
+
return (_b = (_a = objectRefs.current[id]) !== null && _a !== void 0 ? _a : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getObject(id)) !== null && _b !== void 0 ? _b : null;
|
|
111
|
+
}, [parentAssetRuntime]);
|
|
112
|
+
const getHandle = useCallback((id, kind) => {
|
|
113
|
+
var _a, _b, _c;
|
|
114
|
+
return (_c = (_b = (_a = nodeHandles.current.get(id)) === null || _a === void 0 ? void 0 : _a.get(kind)) !== null && _b !== void 0 ? _b : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getHandle(id, kind)) !== null && _c !== void 0 ? _c : null;
|
|
115
|
+
}, [parentAssetRuntime]);
|
|
116
116
|
const getNode = useCallback((nodeId) => {
|
|
117
117
|
var _a;
|
|
118
118
|
return (_a = resolvedStore.getState().nodesById[nodeId]) !== null && _a !== void 0 ? _a : null;
|
|
@@ -120,6 +120,7 @@ export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSel
|
|
|
120
120
|
const registerHandle = useCallback((id, kind, handle) => {
|
|
121
121
|
const current = nodeHandles.current.get(id);
|
|
122
122
|
if (handle == null) {
|
|
123
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerHandle(id, kind, null);
|
|
123
124
|
if (!current)
|
|
124
125
|
return;
|
|
125
126
|
current.delete(kind);
|
|
@@ -130,16 +131,41 @@ export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSel
|
|
|
130
131
|
}
|
|
131
132
|
if (current) {
|
|
132
133
|
current.set(kind, handle);
|
|
134
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerHandle(id, kind, handle);
|
|
133
135
|
return;
|
|
134
136
|
}
|
|
135
137
|
nodeHandles.current.set(id, new Map([[kind, handle]]));
|
|
136
|
-
|
|
138
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerHandle(id, kind, handle);
|
|
139
|
+
}, [parentAssetRuntime]);
|
|
140
|
+
const registerObject = useCallback((id, obj) => {
|
|
141
|
+
if (obj) {
|
|
142
|
+
objectRefs.current[id] = obj;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
delete objectRefs.current[id];
|
|
146
|
+
}
|
|
147
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerObject(id, obj);
|
|
148
|
+
}, [parentAssetRuntime]);
|
|
149
|
+
const registerModel = useCallback((path, model) => {
|
|
150
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerModel(path, model);
|
|
151
|
+
setModels(prev => prev[path] === model ? prev : Object.assign(Object.assign({}, prev), { [path]: model }));
|
|
152
|
+
}, [parentAssetRuntime]);
|
|
153
|
+
const registerTexture = useCallback((path, texture) => {
|
|
154
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerTexture(path, texture);
|
|
155
|
+
setTextures(prev => prev[path] === texture ? prev : Object.assign(Object.assign({}, prev), { [path]: texture }));
|
|
156
|
+
}, [parentAssetRuntime]);
|
|
157
|
+
const registerSound = useCallback((path, sound) => {
|
|
158
|
+
parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.registerSound(path, sound);
|
|
159
|
+
soundManager.setBuffer(path, sound);
|
|
160
|
+
setSounds(prev => prev[path] === sound ? prev : Object.assign(Object.assign({}, prev), { [path]: sound }));
|
|
161
|
+
}, [parentAssetRuntime]);
|
|
137
162
|
const sceneValue = useMemo(() => ({
|
|
138
163
|
get root() {
|
|
139
164
|
var _a;
|
|
140
165
|
return (_a = objectRefs.current[rootId]) !== null && _a !== void 0 ? _a : null;
|
|
141
166
|
},
|
|
142
167
|
mode: editMode ? PrefabEditorMode.Edit : PrefabEditorMode.Play,
|
|
168
|
+
basePath,
|
|
143
169
|
get: getNode,
|
|
144
170
|
getObject,
|
|
145
171
|
getHandle,
|
|
@@ -155,28 +181,31 @@ export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSel
|
|
|
155
181
|
duplicate: (id) => resolvedStore.getState().duplicateNode(id),
|
|
156
182
|
move: (draggedId, targetId, position) => resolvedStore.getState().moveNode(draggedId, targetId, position),
|
|
157
183
|
replace: (prefab) => resolvedStore.getState().replacePrefab(prefab),
|
|
158
|
-
addModel: (path, model) =>
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
184
|
+
addModel: (path, model) => {
|
|
185
|
+
var _a;
|
|
186
|
+
const version = ((_a = injectedModelVersions.current[path]) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
187
|
+
injectedModelVersions.current[path] = version;
|
|
188
|
+
void precompileModel(model, renderer, camera).then(() => {
|
|
189
|
+
if (injectedModelVersions.current[path] !== version)
|
|
190
|
+
return;
|
|
191
|
+
registerModel(path, model);
|
|
192
|
+
});
|
|
163
193
|
},
|
|
164
|
-
|
|
194
|
+
addTexture: registerTexture,
|
|
195
|
+
addSound: registerSound,
|
|
196
|
+
}), [basePath, camera, editMode, getHandle, getModel, getNode, getObject, registerModel, registerSound, registerTexture, renderer, resolvedStore, rootId]);
|
|
165
197
|
useImperativeHandle(ref, () => sceneValue, [sceneValue]);
|
|
166
|
-
const registerRef = useCallback((id, obj) => {
|
|
167
|
-
objectRefs.current[id] = obj;
|
|
168
|
-
}, []);
|
|
169
198
|
useEffect(() => {
|
|
170
199
|
if (usesOwnedStore && data) {
|
|
171
200
|
resolvedStore.getState().replacePrefab(data);
|
|
172
201
|
}
|
|
173
202
|
}, [data, resolvedStore, usesOwnedStore]);
|
|
174
203
|
useEffect(() => {
|
|
175
|
-
const loadAsset = (file, loaded,
|
|
176
|
-
if (loaded[file] ||
|
|
204
|
+
const loadAsset = (file, loaded, failed, loader) => {
|
|
205
|
+
if (loaded[file] || loading.current.has(file) || failed.has(file))
|
|
177
206
|
return;
|
|
178
207
|
loading.current.add(file);
|
|
179
|
-
void loader(
|
|
208
|
+
void loader(withBasePath(basePath, file)).then(result => {
|
|
180
209
|
loading.current.delete(file);
|
|
181
210
|
if (!result.success) {
|
|
182
211
|
console.warn(`Failed to load asset: ${file}`, result.error);
|
|
@@ -189,44 +218,63 @@ export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSel
|
|
|
189
218
|
const type = entry.slice(0, separator);
|
|
190
219
|
const file = entry.slice(separator + 1);
|
|
191
220
|
if (type === 'model') {
|
|
192
|
-
|
|
221
|
+
const inheritedModel = models[file] ? null : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getModel(file);
|
|
222
|
+
if (inheritedModel) {
|
|
223
|
+
registerModel(file, inheritedModel);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
loadAsset(file, models, failedModels.current, path => loadModel(path).then((result) => __awaiter(void 0, void 0, void 0, function* () {
|
|
193
227
|
const loadedModel = result.model;
|
|
194
228
|
if (result.success && loadedModel) {
|
|
195
|
-
|
|
229
|
+
yield precompileModel(loadedModel, renderer, camera);
|
|
230
|
+
registerModel(file, loadedModel);
|
|
196
231
|
}
|
|
197
232
|
return result;
|
|
198
|
-
}));
|
|
233
|
+
})));
|
|
199
234
|
}
|
|
200
235
|
else if (type === 'texture') {
|
|
201
|
-
|
|
236
|
+
const inheritedTexture = textures[file] ? null : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getTexture(file);
|
|
237
|
+
if (inheritedTexture) {
|
|
238
|
+
registerTexture(file, inheritedTexture);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
loadAsset(file, textures, failedTextures.current, path => loadTexture(path).then(result => {
|
|
202
242
|
const loadedTexture = result.texture;
|
|
203
243
|
if (result.success && loadedTexture) {
|
|
204
|
-
|
|
244
|
+
registerTexture(file, loadedTexture);
|
|
205
245
|
}
|
|
206
246
|
return result;
|
|
207
247
|
}));
|
|
208
248
|
}
|
|
209
249
|
else if (type === 'sound') {
|
|
210
|
-
|
|
250
|
+
const inheritedSound = sounds[file] ? null : parentAssetRuntime === null || parentAssetRuntime === void 0 ? void 0 : parentAssetRuntime.getSound(file);
|
|
251
|
+
if (inheritedSound) {
|
|
252
|
+
registerSound(file, inheritedSound);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
loadAsset(file, sounds, failedSounds.current, path => loadSound(path).then(result => {
|
|
211
256
|
const loadedSound = result.sound;
|
|
212
257
|
if (result.success && loadedSound) {
|
|
213
|
-
|
|
214
|
-
setSounds(currentSounds => (Object.assign(Object.assign({}, currentSounds), { [file]: loadedSound })));
|
|
258
|
+
registerSound(file, loadedSound);
|
|
215
259
|
}
|
|
216
260
|
return result;
|
|
217
261
|
}));
|
|
218
262
|
}
|
|
219
263
|
});
|
|
220
|
-
}, [assetRefCounts, basePath,
|
|
264
|
+
}, [assetRefCounts, basePath, camera, models, parentAssetRuntime, registerModel, registerSound, registerTexture, renderer, sounds, textures]);
|
|
221
265
|
const assetRuntime = useMemo(() => ({
|
|
266
|
+
registerObject,
|
|
222
267
|
registerHandle,
|
|
268
|
+
registerModel,
|
|
269
|
+
registerTexture,
|
|
270
|
+
registerSound,
|
|
223
271
|
getHandle,
|
|
224
272
|
getObject,
|
|
225
273
|
getModel,
|
|
226
274
|
getTexture,
|
|
227
275
|
getSound,
|
|
228
276
|
getAssetRevision: () => assetRevision,
|
|
229
|
-
}), [registerHandle, getHandle, getObject, getModel, getTexture, getSound, assetRevision]);
|
|
277
|
+
}), [registerObject, registerHandle, registerModel, registerTexture, registerSound, getHandle, getObject, getModel, getTexture, getSound, assetRevision]);
|
|
230
278
|
const handleNodeClick = useCallback((event, nodeId, fallbackObject) => {
|
|
231
279
|
const node = resolvedStore.getState().nodesById[nodeId];
|
|
232
280
|
if (!node)
|
|
@@ -235,9 +283,10 @@ export const PrefabRoot = forwardRef(({ editMode, data, store, selectedId, onSel
|
|
|
235
283
|
emitNodePointerEvent(clickEventName, event, nodeId, node, fallbackObject);
|
|
236
284
|
onClick === null || onClick === void 0 ? void 0 : onClick(event, node);
|
|
237
285
|
}, [onClick, resolvedStore]);
|
|
238
|
-
const content = (_jsxs(GameInstanceProvider, { models:
|
|
239
|
-
const runtimeContent =
|
|
240
|
-
|
|
286
|
+
const content = (_jsxs(GameInstanceProvider, { models: models, selectedId: selectedId, editMode: editMode, onSelect: editMode ? onSelect : undefined, onClick: editMode ? undefined : handleNodeClick, registerRef: registerObject, children: [_jsx(StoreRootNode, { selectedId: selectedId, onSelect: editMode ? onSelect : undefined, onClick: editMode ? undefined : handleNodeClick, onEditNodeClick: editMode ? onEditNodeClick : undefined, registerRef: registerObject, loadedModels: models, editMode: editMode, parentMatrix: IDENTITY, basePath: basePath }), children] }));
|
|
287
|
+
const runtimeContent = parentAssetRuntime ? content : (_jsx(AssetRuntimeContext.Provider, { value: assetRuntime, children: content }));
|
|
288
|
+
const sceneContent = parentScene ? runtimeContent : (_jsx(SceneContext.Provider, { value: sceneValue, children: runtimeContent }));
|
|
289
|
+
return _jsx(PrefabStoreProvider, { store: resolvedStore, children: sceneContent });
|
|
241
290
|
});
|
|
242
291
|
function StoreRootNode(props) {
|
|
243
292
|
const rootId = usePrefabRootId();
|
|
@@ -303,10 +352,7 @@ function analyzeNodeComponents(node) {
|
|
|
303
352
|
}
|
|
304
353
|
function emitNodePointerEvent(eventName, event, nodeId, node, fallbackObject) {
|
|
305
354
|
var _a;
|
|
306
|
-
const
|
|
307
|
-
if (!trimmedEventName)
|
|
308
|
-
return;
|
|
309
|
-
gameEvents.emit(trimmedEventName, {
|
|
355
|
+
const payload = {
|
|
310
356
|
sourceEntityId: nodeId,
|
|
311
357
|
sourceNodeId: nodeId,
|
|
312
358
|
nodeId,
|
|
@@ -319,7 +365,12 @@ function emitNodePointerEvent(eventName, event, nodeId, node, fallbackObject) {
|
|
|
319
365
|
metaKey: event.nativeEvent.metaKey,
|
|
320
366
|
shiftKey: event.nativeEvent.shiftKey,
|
|
321
367
|
r3fEvent: event,
|
|
322
|
-
}
|
|
368
|
+
};
|
|
369
|
+
gameEvents.emit('click', payload);
|
|
370
|
+
const trimmedEventName = eventName === null || eventName === void 0 ? void 0 : eventName.trim();
|
|
371
|
+
if (!trimmedEventName)
|
|
372
|
+
return;
|
|
373
|
+
gameEvents.emit(trimmedEventName, payload);
|
|
323
374
|
}
|
|
324
375
|
export function GameObjectRenderer(props) {
|
|
325
376
|
var _a, _b;
|
|
@@ -374,7 +425,7 @@ function InstancedNode({ nodeId, parentMatrix = IDENTITY, editMode, registerRef,
|
|
|
374
425
|
}
|
|
375
426
|
return _jsx(_Fragment, { children: renderedInstances });
|
|
376
427
|
}
|
|
377
|
-
function StandardNode({ nodeId, selectedId, onSelect, onClick, onEditNodeClick, registerRef, loadedModels, editMode, parentMatrix = IDENTITY, isVisible = true, }) {
|
|
428
|
+
function StandardNode({ nodeId, selectedId, onSelect, onClick, onEditNodeClick, registerRef, loadedModels, editMode, parentMatrix = IDENTITY, isVisible = true, basePath = "", }) {
|
|
378
429
|
const gameObject = usePrefabNode(nodeId);
|
|
379
430
|
const childIds = usePrefabChildIds(nodeId);
|
|
380
431
|
const analyzedComponents = useMemo(() => gameObject ? analyzeNodeComponents(gameObject) : EMPTY_NODE_COMPONENTS, [gameObject]);
|
|
@@ -410,9 +461,13 @@ function StandardNode({ nodeId, selectedId, onSelect, onClick, onEditNodeClick,
|
|
|
410
461
|
rotation: transform.rotation,
|
|
411
462
|
scale: transform.scale,
|
|
412
463
|
};
|
|
464
|
+
const worldTransform = decompose(world);
|
|
413
465
|
const groupProps = Object.assign(Object.assign({}, metadataProps), transformProps);
|
|
414
|
-
const childNodes = _jsx(ChildNodes, { childIds: childIds, parentMatrix: world, selectedId: selectedId, onSelect: onSelect, onClick: onClick, onEditNodeClick: onEditNodeClick, registerRef: registerRef, loadedModels: loadedModels, editMode: editMode, isVisible: nodeVisible });
|
|
415
|
-
const
|
|
466
|
+
const childNodes = _jsx(ChildNodes, { childIds: childIds, parentMatrix: world, selectedId: selectedId, onSelect: onSelect, onClick: onClick, onEditNodeClick: onEditNodeClick, registerRef: registerRef, loadedModels: loadedModels, editMode: editMode, isVisible: nodeVisible, basePath: basePath });
|
|
467
|
+
const nodeInteractionHandlers = editMode ? editClickHandlers : primaryClickHandlers;
|
|
468
|
+
const componentRuntimeProps = Object.assign(Object.assign({ editMode,
|
|
469
|
+
nodeInteractionHandlers }, transformProps), { worldPosition: worldTransform.position });
|
|
470
|
+
const inner = renderNodeContent(analyzedComponents, loadedModels, primaryClickHandlers, childNodes, basePath, componentRuntimeProps);
|
|
416
471
|
const editAnchor = editMode ? (_jsx("mesh", { visible: false, children: _jsx("boxGeometry", { args: [0.01, 0.01, 0.01] }) })) : null;
|
|
417
472
|
const standardNode = (_jsxs("group", Object.assign({ ref: handleGroupRef }, groupProps, { visible: nodeVisible }, (editMode ? editClickHandlers : undefined), { children: [editAnchor, inner] })));
|
|
418
473
|
return (_jsx(NodeScope, { nodeId: nodeId, editMode: editMode, isSelected: isSelected, children: standardNode }));
|
|
@@ -485,7 +540,7 @@ function getNodeTransformProps(node) {
|
|
|
485
540
|
scale: (_d = t === null || t === void 0 ? void 0 : t.scale) !== null && _d !== void 0 ? _d : [1, 1, 1],
|
|
486
541
|
};
|
|
487
542
|
}
|
|
488
|
-
function renderNodeContent(analyzedComponents, loadedModels, primaryClickHandlers, childNodes) {
|
|
543
|
+
function renderNodeContent(analyzedComponents, loadedModels, primaryClickHandlers, childNodes, basePath = "", componentRuntimeProps) {
|
|
489
544
|
var _a, _b, _c, _d, _e, _f;
|
|
490
545
|
const geometry = analyzedComponents.geometry;
|
|
491
546
|
const models = analyzedComponents.models;
|
|
@@ -550,7 +605,7 @@ function renderNodeContent(analyzedComponents, loadedModels, primaryClickHandler
|
|
|
550
605
|
}
|
|
551
606
|
let content = _jsxs(_Fragment, { children: [primaryContent, contentChildren] });
|
|
552
607
|
for (const { key, View, properties } of analyzedComponents.composition) {
|
|
553
|
-
content = (_jsx(View, { properties: properties, children: content }, key));
|
|
608
|
+
content = (_jsx(View, Object.assign({ properties: properties, basePath: basePath }, componentRuntimeProps, { children: content }), key));
|
|
554
609
|
}
|
|
555
610
|
return content;
|
|
556
611
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Object3D, Texture } from "three";
|
|
2
|
+
import type { GameObject, Prefab } from "./types";
|
|
3
|
+
export declare enum PrefabEditorMode {
|
|
4
|
+
Edit = "edit",
|
|
5
|
+
Play = "play"
|
|
6
|
+
}
|
|
7
|
+
export type PrefabNode = Omit<GameObject, "children">;
|
|
8
|
+
export interface Scene {
|
|
9
|
+
root: Object3D | null;
|
|
10
|
+
mode: PrefabEditorMode;
|
|
11
|
+
basePath: string;
|
|
12
|
+
get(id: string): GameObject | null;
|
|
13
|
+
getObject(id: string): Object3D | null;
|
|
14
|
+
getHandle<T = unknown>(id: string, kind: string): T | null;
|
|
15
|
+
getModel(path: string): Object3D | null;
|
|
16
|
+
add(node: GameObject, parentId?: string): GameObject;
|
|
17
|
+
update(id: string, fn: (node: PrefabNode) => PrefabNode): void;
|
|
18
|
+
replaceNode(id: string, node: GameObject): void;
|
|
19
|
+
remove(id: string): void;
|
|
20
|
+
duplicate(id: string): string | null;
|
|
21
|
+
move(draggedId: string, targetId: string, position: "before" | "inside"): void;
|
|
22
|
+
replace(prefab: Prefab): void;
|
|
23
|
+
addModel(path: string, model: Object3D): void;
|
|
24
|
+
addTexture(path: string, texture: Texture): void;
|
|
25
|
+
addSound(path: string, sound: AudioBuffer): void;
|
|
26
|
+
}
|
|
27
|
+
export declare const SceneContext: import("react").Context<Scene | null>;
|
|
28
|
+
export declare function useScene(): Scene;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
export var PrefabEditorMode;
|
|
3
|
+
(function (PrefabEditorMode) {
|
|
4
|
+
PrefabEditorMode["Edit"] = "edit";
|
|
5
|
+
PrefabEditorMode["Play"] = "play";
|
|
6
|
+
})(PrefabEditorMode || (PrefabEditorMode = {}));
|
|
7
|
+
export const SceneContext = createContext(null);
|
|
8
|
+
export function useScene() {
|
|
9
|
+
const scene = useContext(SceneContext);
|
|
10
|
+
if (!scene) {
|
|
11
|
+
throw new Error("useScene must be used within a PrefabRoot or PrefabEditor scene provider");
|
|
12
|
+
}
|
|
13
|
+
return scene;
|
|
14
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { Object3D, Texture } from "three";
|
|
3
3
|
export interface AssetRuntime {
|
|
4
|
+
registerObject: (id: string, object: Object3D | null) => void;
|
|
4
5
|
registerHandle: (id: string, kind: string, handle: unknown) => void;
|
|
6
|
+
registerModel: (path: string, model: Object3D) => void;
|
|
7
|
+
registerTexture: (path: string, texture: Texture) => void;
|
|
8
|
+
registerSound: (path: string, sound: AudioBuffer) => void;
|
|
5
9
|
getHandle: <T = unknown>(id: string, kind: string) => T | null;
|
|
6
10
|
getModel: (path: string) => Object3D | null;
|
|
7
11
|
getTexture: (path: string) => Texture | null;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FC } from "react";
|
|
2
|
+
import type { ThreeEvent } from "@react-three/fiber";
|
|
2
3
|
import type { ComponentData, GameObject } from "../types";
|
|
3
4
|
export type AssetRef = {
|
|
4
5
|
type: "model" | "texture" | "sound";
|
|
@@ -12,18 +13,32 @@ export interface ComponentViewProps<P = Record<string, unknown>> {
|
|
|
12
13
|
properties: P;
|
|
13
14
|
/** Children to render for components that wrap the current subtree. */
|
|
14
15
|
children?: React.ReactNode;
|
|
16
|
+
/** Whether this node is currently rendered in editor mode. */
|
|
17
|
+
editMode?: boolean;
|
|
18
|
+
/** Node-level pointer/click handlers for custom components that render their own pickable objects. */
|
|
19
|
+
nodeInteractionHandlers?: NodeInteractionHandlers;
|
|
15
20
|
/** Current node local position for wrapper components. */
|
|
16
21
|
position?: [number, number, number];
|
|
17
22
|
/** Current node local rotation in radians for wrapper components. */
|
|
18
23
|
rotation?: [number, number, number];
|
|
19
24
|
/** Current node local scale for wrapper components. */
|
|
20
25
|
scale?: [number, number, number];
|
|
26
|
+
/** Current node world position. Components that create world-space resources should prefer this. */
|
|
27
|
+
worldPosition?: [number, number, number];
|
|
28
|
+
/** Public asset URL prefix, such as a Next.js basePath. */
|
|
29
|
+
basePath?: string;
|
|
21
30
|
}
|
|
31
|
+
export type NodeInteractionHandlers = {
|
|
32
|
+
onClick?: (event: ThreeEvent<PointerEvent>) => void;
|
|
33
|
+
onPointerDown?: (event: ThreeEvent<PointerEvent>) => void;
|
|
34
|
+
onPointerMove?: (event: ThreeEvent<PointerEvent>) => void;
|
|
35
|
+
onPointerUp?: (event: ThreeEvent<PointerEvent>) => void;
|
|
36
|
+
};
|
|
22
37
|
export interface Component {
|
|
23
38
|
name: string;
|
|
24
39
|
/** Set when this component occupies a single slot on a node. Use a string to share a slot across component types. */
|
|
25
40
|
disableSiblingComposition?: boolean | string;
|
|
26
|
-
Editor
|
|
41
|
+
Editor?: FC<{
|
|
27
42
|
node?: GameObject;
|
|
28
43
|
component: ComponentData;
|
|
29
44
|
onUpdate: (newComp: Record<string, unknown>) => void;
|
|
@@ -5,7 +5,7 @@ import { Mesh } from 'three';
|
|
|
5
5
|
import { assetRef, assetRefs } from './ComponentRegistry';
|
|
6
6
|
import { BooleanField, FieldGroup, Label, ListEditor, NumberInput, SelectInput, StringField } from './Input';
|
|
7
7
|
import { useAssetRuntime } from '../assetRuntime';
|
|
8
|
-
import { useEditorContext, useEditorRef } from '../
|
|
8
|
+
import { useEditorContext, useEditorRef } from '../EditorContext';
|
|
9
9
|
import { getRepeatAxesFromModelProperties, normalizeRepeatAxes } from '../InstanceProvider';
|
|
10
10
|
import { base, colors, ui } from '../styles';
|
|
11
11
|
import { decomposeModelToPrefabNodes } from '../modelPrefab';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { lazy, Suspense, useEffect, useState } from 'react';
|
|
12
|
+
import { useEditorRef } from '../EditorContext';
|
|
13
|
+
import { withBasePath } from '../utils';
|
|
14
|
+
import { base, colors } from '../styles';
|
|
15
|
+
import { FieldGroup, Label } from './Input';
|
|
16
|
+
const PrefabRoot = lazy(() => import('../PrefabRoot'));
|
|
17
|
+
function PrefabRefView({ properties, children, basePath = '' }) {
|
|
18
|
+
var _a;
|
|
19
|
+
const [loadedPrefab, setLoadedPrefab] = useState(null);
|
|
20
|
+
const url = (_a = properties.url) !== null && _a !== void 0 ? _a : '';
|
|
21
|
+
const resolvedUrl = url ? withBasePath(basePath, url) : '';
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!resolvedUrl)
|
|
24
|
+
return;
|
|
25
|
+
let cancelled = false;
|
|
26
|
+
fetch(resolvedUrl)
|
|
27
|
+
.then(r => r.json())
|
|
28
|
+
.then(data => { if (!cancelled)
|
|
29
|
+
setLoadedPrefab(data); })
|
|
30
|
+
.catch(err => console.warn('[PrefabRef] Failed to load:', resolvedUrl, err));
|
|
31
|
+
return () => { cancelled = true; };
|
|
32
|
+
}, [resolvedUrl]);
|
|
33
|
+
return (_jsxs(_Fragment, { children: [loadedPrefab && (_jsx(Suspense, { fallback: null, children: _jsx(PrefabRoot, { data: loadedPrefab, editMode: false, basePath: basePath }) })), children] }));
|
|
34
|
+
}
|
|
35
|
+
function PrefabRefEditor({ node, component, onUpdate, basePath = '', }) {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const url = (_b = (_a = component.properties) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '';
|
|
38
|
+
const [manifest, setManifest] = useState([]);
|
|
39
|
+
const [unpacking, setUnpacking] = useState(false);
|
|
40
|
+
const editor = useEditorRef();
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
fetch(withBasePath(basePath, '/prefabs/manifest.json'))
|
|
43
|
+
.then(r => r.json())
|
|
44
|
+
.then(data => setManifest(data))
|
|
45
|
+
.catch(() => setManifest([]));
|
|
46
|
+
}, []);
|
|
47
|
+
const handleUnpack = () => __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
if (!node || !url)
|
|
49
|
+
return;
|
|
50
|
+
setUnpacking(true);
|
|
51
|
+
try {
|
|
52
|
+
const prefab = yield fetch(withBasePath(basePath, url)).then(r => r.json());
|
|
53
|
+
editor.replaceNode(node.id, prefab.root);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.error('[PrefabRef] Unpack failed:', err);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
setUnpacking(false);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return (_jsxs(FieldGroup, { children: [_jsxs("div", { children: [_jsx(Label, { children: "Prefab URL" }), _jsx("input", { type: "text", style: Object.assign(Object.assign({}, base.input), { width: '100%', boxSizing: 'border-box', fontFamily: 'monospace' }), value: url, onChange: e => onUpdate({ url: e.target.value }), placeholder: "/prefabs/my-prefab.json" }), manifest.length > 0 && (_jsxs("select", { style: Object.assign(Object.assign({}, base.input), { width: '100%', marginTop: 4, background: colors.bgInput, boxSizing: 'border-box' }), value: url, onChange: e => onUpdate({ url: e.target.value }), children: [_jsx("option", { value: "", children: "\u2014 pick from manifest \u2014" }), manifest.map(entry => (_jsx("option", { value: entry, children: entry.replace(/^.*\//, '') }, entry)))] }))] }), _jsx("button", { type: "button", style: Object.assign(Object.assign({}, base.btn), { width: '100%', opacity: unpacking || !url ? 0.5 : 1 }), disabled: unpacking || !url, onClick: handleUnpack, children: unpacking ? 'Unpacking…' : 'Unpack' })] }));
|
|
63
|
+
}
|
|
64
|
+
const PrefabRefComponent = {
|
|
65
|
+
name: 'PrefabRef',
|
|
66
|
+
Editor: PrefabRefEditor,
|
|
67
|
+
View: PrefabRefView,
|
|
68
|
+
defaultProperties: {
|
|
69
|
+
url: '',
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
export default PrefabRefComponent;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ColorField, FieldGroup, NumberField, SelectField, StringField } from "./Input";
|
|
3
3
|
import { Text } from 'three-text/three/react';
|
|
4
|
-
import { useRef, useState, useCallback } from 'react';
|
|
5
|
-
|
|
6
|
-
Text.setHarfBuzzPath('/fonts/hb.wasm');
|
|
4
|
+
import { useRef, useState, useCallback, useEffect } from 'react';
|
|
5
|
+
import { withBasePath } from "../utils";
|
|
7
6
|
function TextComponentEditor({ component, onUpdate, }) {
|
|
8
7
|
return (_jsxs(FieldGroup, { children: [_jsx(StringField, { name: "text", label: "Text", values: component.properties, onChange: onUpdate, placeholder: "Enter text..." }), _jsx(ColorField, { name: "color", label: "Color", values: component.properties, onChange: onUpdate }), _jsx(StringField, { name: "font", label: "Font", values: component.properties, onChange: onUpdate, placeholder: "/fonts/NotoSans-Regular.ttf" }), _jsx(NumberField, { name: "size", label: "Size", values: component.properties, onChange: onUpdate, min: 0.01, step: 0.1 }), _jsx(NumberField, { name: "depth", label: "Depth", values: component.properties, onChange: onUpdate, min: 0, step: 0.1 }), _jsx(NumberField, { name: "width", label: "Width", values: component.properties, onChange: onUpdate, min: 0, step: 0.5 }), _jsx(SelectField, { name: "align", label: "Align", values: component.properties, onChange: onUpdate, options: [
|
|
9
8
|
{ value: 'left', label: 'Left' },
|
|
@@ -11,11 +10,15 @@ function TextComponentEditor({ component, onUpdate, }) {
|
|
|
11
10
|
{ value: 'right', label: 'Right' },
|
|
12
11
|
] })] }));
|
|
13
12
|
}
|
|
14
|
-
function TextComponentView({ properties, children }) {
|
|
13
|
+
function TextComponentView({ properties, children, basePath = "" }) {
|
|
15
14
|
const { text = '', font, size, depth, width, align, color } = properties;
|
|
16
15
|
const textContent = String(text || '');
|
|
16
|
+
const resolvedFont = font ? withBasePath(basePath, font) : font;
|
|
17
17
|
const meshRef = useRef(null);
|
|
18
18
|
const [offset, setOffset] = useState([0, 0, 0]);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
Text.setHarfBuzzPath(withBasePath(basePath, '/fonts/hb.wasm'));
|
|
21
|
+
}, [basePath]);
|
|
19
22
|
const handleLoad = useCallback((_geometry, info) => {
|
|
20
23
|
if (info === null || info === void 0 ? void 0 : info.planeBounds) {
|
|
21
24
|
const bounds = info.planeBounds;
|
|
@@ -37,7 +40,7 @@ function TextComponentView({ properties, children }) {
|
|
|
37
40
|
}, [align]);
|
|
38
41
|
if (!textContent)
|
|
39
42
|
return null;
|
|
40
|
-
return (_jsxs("group", { position: offset, children: [_jsx(Text, { ref: meshRef, font:
|
|
43
|
+
return (_jsxs("group", { position: offset, children: [_jsx(Text, { ref: meshRef, font: resolvedFont, size: size, depth: depth, layout: { align, width }, color: color, onLoad: handleLoad, children: textContent }), children] }));
|
|
41
44
|
}
|
|
42
45
|
const TextComponent = {
|
|
43
46
|
name: 'Text',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Label, Vector3Input } from "./Input";
|
|
3
|
-
import { useEditorContext } from "../
|
|
3
|
+
import { useEditorContext } from "../EditorContext";
|
|
4
4
|
import { colors } from "../styles";
|
|
5
5
|
const buttonStyle = {
|
|
6
6
|
padding: '2px 6px',
|