mujoco-react 4.0.0 → 6.0.0
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 +23 -27
- package/dist/index.d.ts +34 -24
- package/dist/index.js +70 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/SceneLoader.ts +1 -3
- package/src/hooks/useBodyMeshes.ts +45 -0
- package/src/hooks/useSelectionHighlight.ts +23 -29
- package/src/index.ts +1 -2
- package/src/types.ts +3 -2
package/package.json
CHANGED
package/src/core/SceneLoader.ts
CHANGED
|
@@ -154,9 +154,7 @@ export async function loadScene(
|
|
|
154
154
|
try { mujoco.FS.unmount('/working'); } catch { /* ignore */ }
|
|
155
155
|
try { mujoco.FS.mkdir('/working'); } catch { /* ignore */ }
|
|
156
156
|
|
|
157
|
-
const baseUrl =
|
|
158
|
-
config.baseUrl ||
|
|
159
|
-
`https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/${config.modelId}/`;
|
|
157
|
+
const baseUrl = config.src.endsWith('/') ? config.src : config.src + '/';
|
|
160
158
|
|
|
161
159
|
const downloaded = new Set<string>();
|
|
162
160
|
const queue: string[] = [config.sceneFile];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*
|
|
5
|
+
* useBodyMeshes — returns Three.js meshes belonging to a MuJoCo body.
|
|
6
|
+
*
|
|
7
|
+
* Low-level primitive for custom selection visuals, outlines,
|
|
8
|
+
* postprocessing effects, or any per-body mesh manipulation.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useMemo } from 'react';
|
|
12
|
+
import { useThree } from '@react-three/fiber';
|
|
13
|
+
import * as THREE from 'three';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Returns all Three.js meshes belonging to the given MuJoCo body ID.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const meshes = useBodyMeshes(selectedBodyId);
|
|
21
|
+
*
|
|
22
|
+
* // Use with drei Outline
|
|
23
|
+
* <Outline selection={meshes} />
|
|
24
|
+
*
|
|
25
|
+
* // Or manipulate directly
|
|
26
|
+
* useFrame(() => {
|
|
27
|
+
* meshes.forEach(m => { m.scale.setScalar(1.05); });
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function useBodyMeshes(bodyId: number | null): THREE.Mesh[] {
|
|
32
|
+
const { scene } = useThree();
|
|
33
|
+
|
|
34
|
+
return useMemo(() => {
|
|
35
|
+
if (bodyId === null || bodyId < 0) return [];
|
|
36
|
+
|
|
37
|
+
const meshes: THREE.Mesh[] = [];
|
|
38
|
+
scene.traverse((obj) => {
|
|
39
|
+
if (obj.userData.bodyID === bodyId && (obj as THREE.Mesh).isMesh) {
|
|
40
|
+
meshes.push(obj as THREE.Mesh);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return meshes;
|
|
44
|
+
}, [bodyId, scene]);
|
|
45
|
+
}
|
|
@@ -2,64 +2,58 @@
|
|
|
2
2
|
* @license
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*
|
|
5
|
-
* useSelectionHighlight — hook
|
|
5
|
+
* useSelectionHighlight — convenience hook for emissive body highlights.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* Restores original emissive when bodyId changes or hook unmounts.
|
|
7
|
+
* Built on useBodyMeshes. For custom visuals, use useBodyMeshes directly.
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
import { useEffect, useRef } from 'react';
|
|
12
|
-
import { useThree } from '@react-three/fiber';
|
|
13
11
|
import * as THREE from 'three';
|
|
12
|
+
import { useBodyMeshes } from './useBodyMeshes';
|
|
14
13
|
|
|
15
14
|
export function useSelectionHighlight(
|
|
16
15
|
bodyId: number | null,
|
|
17
16
|
options: { color?: string; emissiveIntensity?: number } = {},
|
|
18
17
|
) {
|
|
19
18
|
const { color = '#ff4444', emissiveIntensity = 0.3 } = options;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
19
|
+
const meshes = useBodyMeshes(bodyId);
|
|
20
|
+
const prevRef = useRef<{ mesh: THREE.Mesh; originalEmissive: THREE.Color; originalIntensity: number }[]>([]);
|
|
22
21
|
|
|
23
22
|
useEffect(() => {
|
|
24
|
-
// Restore previous
|
|
25
|
-
for (const entry of
|
|
23
|
+
// Restore previous
|
|
24
|
+
for (const entry of prevRef.current) {
|
|
26
25
|
const mat = entry.mesh.material as THREE.MeshStandardMaterial;
|
|
27
26
|
if (mat.emissive) {
|
|
28
27
|
mat.emissive.copy(entry.originalEmissive);
|
|
29
28
|
mat.emissiveIntensity = entry.originalIntensity;
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
|
|
31
|
+
prevRef.current = [];
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// Find all meshes belonging to this body
|
|
33
|
+
// Apply new
|
|
37
34
|
const highlightColor = new THREE.Color(color);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
mat.emissive.copy(highlightColor);
|
|
49
|
-
mat.emissiveIntensity = emissiveIntensity;
|
|
50
|
-
}
|
|
35
|
+
for (const mesh of meshes) {
|
|
36
|
+
const mat = mesh.material as THREE.MeshStandardMaterial;
|
|
37
|
+
if (mat.emissive) {
|
|
38
|
+
prevRef.current.push({
|
|
39
|
+
mesh,
|
|
40
|
+
originalEmissive: mat.emissive.clone(),
|
|
41
|
+
originalIntensity: mat.emissiveIntensity ?? 0,
|
|
42
|
+
});
|
|
43
|
+
mat.emissive.copy(highlightColor);
|
|
44
|
+
mat.emissiveIntensity = emissiveIntensity;
|
|
51
45
|
}
|
|
52
|
-
}
|
|
46
|
+
}
|
|
53
47
|
|
|
54
48
|
return () => {
|
|
55
|
-
for (const entry of
|
|
49
|
+
for (const entry of prevRef.current) {
|
|
56
50
|
const mat = entry.mesh.material as THREE.MeshStandardMaterial;
|
|
57
51
|
if (mat.emissive) {
|
|
58
52
|
mat.emissive.copy(entry.originalEmissive);
|
|
59
53
|
mat.emissiveIntensity = entry.originalIntensity;
|
|
60
54
|
}
|
|
61
55
|
}
|
|
62
|
-
|
|
56
|
+
prevRef.current = [];
|
|
63
57
|
};
|
|
64
|
-
}, [
|
|
58
|
+
}, [meshes, color, emissiveIntensity]);
|
|
65
59
|
}
|
package/src/index.ts
CHANGED
|
@@ -41,7 +41,6 @@ export { TendonRenderer } from './components/TendonRenderer';
|
|
|
41
41
|
export { FlexRenderer } from './components/FlexRenderer';
|
|
42
42
|
export { ContactListener } from './components/ContactListener';
|
|
43
43
|
export { TrajectoryPlayer } from './components/TrajectoryPlayer';
|
|
44
|
-
export { SelectionHighlight } from './components/SelectionHighlight';
|
|
45
44
|
|
|
46
45
|
// Hooks
|
|
47
46
|
export { useActuators } from './hooks/useActuators';
|
|
@@ -59,6 +58,7 @@ export { useTrajectoryRecorder } from './hooks/useTrajectoryRecorder';
|
|
|
59
58
|
export { useGamepad } from './hooks/useGamepad';
|
|
60
59
|
export { useVideoRecorder } from './hooks/useVideoRecorder';
|
|
61
60
|
export { useCtrlNoise } from './hooks/useCtrlNoise';
|
|
61
|
+
export { useBodyMeshes } from './hooks/useBodyMeshes';
|
|
62
62
|
export { useSelectionHighlight } from './hooks/useSelectionHighlight';
|
|
63
63
|
export { useSceneLights } from './hooks/useSceneLights';
|
|
64
64
|
export { useCameraAnimation } from './hooks/useCameraAnimation';
|
|
@@ -106,7 +106,6 @@ export type {
|
|
|
106
106
|
DebugProps,
|
|
107
107
|
SceneLightsProps,
|
|
108
108
|
TrajectoryPlayerProps,
|
|
109
|
-
SelectionHighlightProps,
|
|
110
109
|
ContactListenerProps,
|
|
111
110
|
// API
|
|
112
111
|
MujocoSimAPI,
|
package/src/types.ts
CHANGED
|
@@ -284,9 +284,10 @@ export interface XmlPatch {
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
export interface SceneConfig {
|
|
287
|
-
|
|
287
|
+
/** Base URL for fetching model files. The loader fetches `src + sceneFile` and follows dependencies. */
|
|
288
|
+
src: string;
|
|
289
|
+
/** Entry MJCF XML file name, e.g. 'scene.xml'. */
|
|
288
290
|
sceneFile: string;
|
|
289
|
-
baseUrl?: string;
|
|
290
291
|
sceneObjects?: SceneObject[];
|
|
291
292
|
homeJoints?: number[];
|
|
292
293
|
xmlPatches?: XmlPatch[];
|