react-three-game 0.0.20 → 0.0.21
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.
|
@@ -108,7 +108,7 @@ export const PrefabRoot = forwardRef(({ editMode, data, onPrefabChange, selected
|
|
|
108
108
|
return _jsxs("group", { ref: ref, children: [_jsx(GameInstanceProvider, { models: loadedModels, onSelect: editMode ? onSelect : undefined, registerRef: registerRef, children: _jsx(GameObjectRenderer, { gameObject: data.root, selectedId: selectedId, onSelect: editMode ? onSelect : undefined, registerRef: registerRef, loadedModels: loadedModels, loadedTextures: loadedTextures, editMode: editMode, parentMatrix: new Matrix4() }) }), editMode && _jsxs(_Fragment, { children: [_jsx(MapControls, { makeDefault: true }), selectedId && selectedObject && (_jsx(TransformControls, { object: selectedObject, mode: transformMode, space: "local", onObjectChange: onTransformChange }))] })] });
|
|
109
109
|
});
|
|
110
110
|
function GameObjectRenderer({ gameObject, selectedId, onSelect, registerRef, loadedModels, loadedTextures, editMode, parentMatrix = new Matrix4(), }) {
|
|
111
|
-
var _a, _b, _c, _d;
|
|
111
|
+
var _a, _b, _c, _d, _e;
|
|
112
112
|
// Early return if gameObject is null or undefined
|
|
113
113
|
if (!gameObject)
|
|
114
114
|
return null;
|
|
@@ -144,12 +144,28 @@ function GameObjectRenderer({ gameObject, selectedId, onSelect, registerRef, loa
|
|
|
144
144
|
}
|
|
145
145
|
// --- 4. Render core content using component system ---
|
|
146
146
|
const core = renderCoreNode(gameObject, ctx, parentMatrix);
|
|
147
|
-
// --- 5.
|
|
148
|
-
const physicsWrapped = wrapPhysicsIfNeeded(gameObject, core, ctx);
|
|
149
|
-
// --- 6. Render children recursively (always relative transforms) ---
|
|
147
|
+
// --- 5. Render children recursively (always relative transforms) ---
|
|
150
148
|
const children = ((_d = gameObject.children) !== null && _d !== void 0 ? _d : []).map((child) => (_jsx(GameObjectRenderer, { gameObject: child, selectedId: selectedId, onSelect: onSelect, registerRef: registerRef, loadedModels: loadedModels, loadedTextures: loadedTextures, editMode: editMode, parentMatrix: worldMatrix }, child.id)));
|
|
151
|
-
// ---
|
|
152
|
-
|
|
149
|
+
// --- 6. Common props for the wrapper element ---
|
|
150
|
+
const wrapperProps = {
|
|
151
|
+
position: transformProps.position,
|
|
152
|
+
rotation: transformProps.rotation,
|
|
153
|
+
onPointerDown: handlePointerDown,
|
|
154
|
+
onPointerMove: handlePointerMove,
|
|
155
|
+
onPointerUp: handlePointerUp,
|
|
156
|
+
};
|
|
157
|
+
// --- 7. Check if physics is needed ---
|
|
158
|
+
const physics = (_e = gameObject.components) === null || _e === void 0 ? void 0 : _e.physics;
|
|
159
|
+
const hasPhysics = physics && !editMode;
|
|
160
|
+
// --- 8. Final structure: RigidBody outside with position/rotation, scale inside ---
|
|
161
|
+
if (hasPhysics) {
|
|
162
|
+
const physicsDef = getComponent('Physics');
|
|
163
|
+
if (physicsDef === null || physicsDef === void 0 ? void 0 : physicsDef.View) {
|
|
164
|
+
return (_jsx(physicsDef.View, Object.assign({ properties: physics.properties, ref: (obj) => registerRef(gameObject.id, obj) }, wrapperProps, { children: _jsxs("group", { scale: transformProps.scale, children: [core, children] }) })));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// --- 9. No physics - standard group wrapper ---
|
|
168
|
+
return (_jsxs("group", Object.assign({ ref: (el) => registerRef(gameObject.id, el), scale: transformProps.scale }, wrapperProps, { children: [core, children] })));
|
|
153
169
|
}
|
|
154
170
|
// Helper: render an instanced GameInstance (terminal node)
|
|
155
171
|
function renderInstancedNode(gameObject, worldMatrix, ctx) {
|
|
@@ -223,17 +239,6 @@ function renderCoreNode(gameObject, ctx, parentMatrix) {
|
|
|
223
239
|
return _jsx(View, Object.assign({ properties: properties }, contextProps, { children: content }), key);
|
|
224
240
|
}, coreContent);
|
|
225
241
|
}
|
|
226
|
-
// Helper: wrap core content with physics component when necessary
|
|
227
|
-
function wrapPhysicsIfNeeded(gameObject, content, ctx) {
|
|
228
|
-
var _a;
|
|
229
|
-
const physics = (_a = gameObject.components) === null || _a === void 0 ? void 0 : _a.physics;
|
|
230
|
-
if (!physics)
|
|
231
|
-
return content;
|
|
232
|
-
const physicsDef = getComponent('Physics');
|
|
233
|
-
if (!physicsDef || !physicsDef.View)
|
|
234
|
-
return content;
|
|
235
|
-
return (_jsx(physicsDef.View, { properties: Object.assign(Object.assign({}, physics.properties), { id: gameObject.id }), editMode: ctx.editMode, children: content }));
|
|
236
|
-
}
|
|
237
242
|
export default PrefabRoot;
|
|
238
243
|
function getNodeTransformProps(node) {
|
|
239
244
|
var _a, _b, _c, _d, _e;
|
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
|
|
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 { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
|
+
import { RigidBody } from "@react-three/rapier";
|
|
14
|
+
const selectClass = "w-full bg-black/40 border border-cyan-500/30 px-1 py-0.5 text-[10px] text-cyan-300 font-mono focus:outline-none focus:border-cyan-400/50";
|
|
15
|
+
const labelClass = "block text-[9px] text-cyan-400/60 uppercase tracking-wider mb-0.5";
|
|
2
16
|
function PhysicsComponentEditor({ component, onUpdate }) {
|
|
3
|
-
|
|
17
|
+
const { type, collider = 'hull' } = component.properties;
|
|
18
|
+
return (_jsxs("div", { children: [_jsx("label", { className: labelClass, children: "Type" }), _jsxs("select", { className: selectClass, value: type, onChange: e => onUpdate({ type: e.target.value }), children: [_jsx("option", { value: "dynamic", children: "Dynamic" }), _jsx("option", { value: "fixed", children: "Fixed" })] }), _jsx("label", { className: `${labelClass} mt-2`, children: "Collider" }), _jsxs("select", { className: selectClass, value: collider, onChange: e => onUpdate({ collider: e.target.value }), children: [_jsx("option", { value: "hull", children: "Hull (convex)" }), _jsx("option", { value: "trimesh", children: "Trimesh (exact)" }), _jsx("option", { value: "cuboid", children: "Cuboid (box)" }), _jsx("option", { value: "ball", children: "Ball (sphere)" })] })] }));
|
|
4
19
|
}
|
|
5
|
-
|
|
6
|
-
|
|
20
|
+
function PhysicsComponentView(_a) {
|
|
21
|
+
var { properties, editMode, children } = _a, rigidBodyProps = __rest(_a, ["properties", "editMode", "children"]);
|
|
7
22
|
if (editMode)
|
|
8
|
-
return children;
|
|
9
|
-
|
|
23
|
+
return _jsx(_Fragment, { children: children });
|
|
24
|
+
const colliders = properties.collider || (properties.type === 'fixed' ? 'trimesh' : 'hull');
|
|
25
|
+
return (_jsx(RigidBody, Object.assign({ type: properties.type, colliders: colliders }, rigidBodyProps, { children: children })));
|
|
10
26
|
}
|
|
11
27
|
const PhysicsComponent = {
|
|
12
28
|
name: 'Physics',
|
|
13
29
|
Editor: PhysicsComponentEditor,
|
|
14
30
|
View: PhysicsComponentView,
|
|
15
|
-
defaultProperties: {
|
|
16
|
-
type: 'dynamic'
|
|
17
|
-
}
|
|
31
|
+
defaultProperties: { type: 'dynamic', collider: 'hull' }
|
|
18
32
|
};
|
|
19
33
|
export default PhysicsComponent;
|
package/package.json
CHANGED
|
@@ -222,10 +222,7 @@ function GameObjectRenderer({
|
|
|
222
222
|
// --- 4. Render core content using component system ---
|
|
223
223
|
const core = renderCoreNode(gameObject, ctx, parentMatrix);
|
|
224
224
|
|
|
225
|
-
// --- 5.
|
|
226
|
-
const physicsWrapped = wrapPhysicsIfNeeded(gameObject, core, ctx);
|
|
227
|
-
|
|
228
|
-
// --- 6. Render children recursively (always relative transforms) ---
|
|
225
|
+
// --- 5. Render children recursively (always relative transforms) ---
|
|
229
226
|
const children = (gameObject.children ?? []).map((child) => (
|
|
230
227
|
<GameObjectRenderer
|
|
231
228
|
key={child.id}
|
|
@@ -240,18 +237,46 @@ function GameObjectRenderer({
|
|
|
240
237
|
/>
|
|
241
238
|
));
|
|
242
239
|
|
|
243
|
-
// ---
|
|
240
|
+
// --- 6. Common props for the wrapper element ---
|
|
241
|
+
const wrapperProps = {
|
|
242
|
+
position: transformProps.position,
|
|
243
|
+
rotation: transformProps.rotation,
|
|
244
|
+
onPointerDown: handlePointerDown,
|
|
245
|
+
onPointerMove: handlePointerMove,
|
|
246
|
+
onPointerUp: handlePointerUp,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// --- 7. Check if physics is needed ---
|
|
250
|
+
const physics = gameObject.components?.physics;
|
|
251
|
+
const hasPhysics = physics && !editMode;
|
|
252
|
+
|
|
253
|
+
// --- 8. Final structure: RigidBody outside with position/rotation, scale inside ---
|
|
254
|
+
if (hasPhysics) {
|
|
255
|
+
const physicsDef = getComponent('Physics');
|
|
256
|
+
if (physicsDef?.View) {
|
|
257
|
+
return (
|
|
258
|
+
<physicsDef.View
|
|
259
|
+
properties={physics.properties}
|
|
260
|
+
ref={(obj: Object3D | null) => registerRef(gameObject.id, obj)}
|
|
261
|
+
{...wrapperProps}
|
|
262
|
+
>
|
|
263
|
+
<group scale={transformProps.scale}>
|
|
264
|
+
{core}
|
|
265
|
+
{children}
|
|
266
|
+
</group>
|
|
267
|
+
</physicsDef.View>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// --- 9. No physics - standard group wrapper ---
|
|
244
273
|
return (
|
|
245
274
|
<group
|
|
246
275
|
ref={(el) => registerRef(gameObject.id, el)}
|
|
247
|
-
position={transformProps.position}
|
|
248
|
-
rotation={transformProps.rotation}
|
|
249
276
|
scale={transformProps.scale}
|
|
250
|
-
|
|
251
|
-
onPointerMove={handlePointerMove}
|
|
252
|
-
onPointerUp={handlePointerUp}
|
|
277
|
+
{...wrapperProps}
|
|
253
278
|
>
|
|
254
|
-
{
|
|
279
|
+
{core}
|
|
255
280
|
{children}
|
|
256
281
|
</group>
|
|
257
282
|
);
|
|
@@ -364,22 +389,6 @@ function renderCoreNode(gameObject: GameObjectType, ctx: any, parentMatrix: Matr
|
|
|
364
389
|
}, coreContent);
|
|
365
390
|
}
|
|
366
391
|
|
|
367
|
-
// Helper: wrap core content with physics component when necessary
|
|
368
|
-
function wrapPhysicsIfNeeded(gameObject: GameObjectType, content: React.ReactNode, ctx: any) {
|
|
369
|
-
const physics = gameObject.components?.physics;
|
|
370
|
-
if (!physics) return content;
|
|
371
|
-
const physicsDef = getComponent('Physics');
|
|
372
|
-
if (!physicsDef || !physicsDef.View) return content;
|
|
373
|
-
return (
|
|
374
|
-
<physicsDef.View
|
|
375
|
-
properties={{ ...physics.properties, id: gameObject.id }}
|
|
376
|
-
editMode={ctx.editMode}
|
|
377
|
-
>
|
|
378
|
-
{content}
|
|
379
|
-
</physicsDef.View>
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
392
|
|
|
384
393
|
|
|
385
394
|
|
|
@@ -1,29 +1,42 @@
|
|
|
1
|
+
import { RigidBody, RigidBodyProps } from "@react-three/rapier";
|
|
1
2
|
import { Component } from "./ComponentRegistry";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
const selectClass = "w-full bg-black/40 border border-cyan-500/30 px-1 py-0.5 text-[10px] text-cyan-300 font-mono focus:outline-none focus:border-cyan-400/50";
|
|
5
|
+
const labelClass = "block text-[9px] text-cyan-400/60 uppercase tracking-wider mb-0.5";
|
|
6
|
+
|
|
7
|
+
function PhysicsComponentEditor({ component, onUpdate }: { component: any; onUpdate: (props: any) => void }) {
|
|
8
|
+
const { type, collider = 'hull' } = component.properties;
|
|
9
|
+
return (
|
|
10
|
+
<div>
|
|
11
|
+
<label className={labelClass}>Type</label>
|
|
12
|
+
<select className={selectClass} value={type} onChange={e => onUpdate({ type: e.target.value })}>
|
|
13
|
+
<option value="dynamic">Dynamic</option>
|
|
14
|
+
<option value="fixed">Fixed</option>
|
|
15
|
+
</select>
|
|
16
|
+
|
|
17
|
+
<label className={`${labelClass} mt-2`}>Collider</label>
|
|
18
|
+
<select className={selectClass} value={collider} onChange={e => onUpdate({ collider: e.target.value })}>
|
|
19
|
+
<option value="hull">Hull (convex)</option>
|
|
20
|
+
<option value="trimesh">Trimesh (exact)</option>
|
|
21
|
+
<option value="cuboid">Cuboid (box)</option>
|
|
22
|
+
<option value="ball">Ball (sphere)</option>
|
|
23
|
+
</select>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface PhysicsViewProps extends Omit<RigidBodyProps, 'type' | 'colliders'> {
|
|
29
|
+
properties: { type: RigidBodyProps['type']; collider?: string };
|
|
30
|
+
editMode?: boolean;
|
|
15
31
|
}
|
|
16
32
|
|
|
33
|
+
function PhysicsComponentView({ properties, editMode, children, ...rigidBodyProps }: PhysicsViewProps) {
|
|
34
|
+
if (editMode) return <>{children}</>;
|
|
17
35
|
|
|
18
|
-
|
|
36
|
+
const colliders = properties.collider || (properties.type === 'fixed' ? 'trimesh' : 'hull');
|
|
19
37
|
|
|
20
|
-
function PhysicsComponentView({ properties, children, editMode }: any) {
|
|
21
|
-
if (editMode) return children;
|
|
22
38
|
return (
|
|
23
|
-
<RigidBody
|
|
24
|
-
type={properties.type}
|
|
25
|
-
colliders="cuboid"
|
|
26
|
-
>
|
|
39
|
+
<RigidBody type={properties.type} colliders={colliders as any} {...rigidBodyProps}>
|
|
27
40
|
{children}
|
|
28
41
|
</RigidBody>
|
|
29
42
|
);
|
|
@@ -33,9 +46,7 @@ const PhysicsComponent: Component = {
|
|
|
33
46
|
name: 'Physics',
|
|
34
47
|
Editor: PhysicsComponentEditor,
|
|
35
48
|
View: PhysicsComponentView,
|
|
36
|
-
defaultProperties: {
|
|
37
|
-
type: 'dynamic'
|
|
38
|
-
}
|
|
49
|
+
defaultProperties: { type: 'dynamic', collider: 'hull' }
|
|
39
50
|
};
|
|
40
51
|
|
|
41
52
|
export default PhysicsComponent;
|