mujoco-react 5.0.0 → 6.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mujoco-react",
3
- "version": "5.0.0",
3
+ "version": "6.0.1",
4
4
  "description": "Composable React Three Fiber building blocks for MuJoCo WASM simulations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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 form of SelectionHighlight (spec 6.5)
5
+ * useSelectionHighlight — convenience hook for emissive body highlights.
6
6
  *
7
- * Applies emissive highlight to all meshes belonging to a body.
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 { scene } = useThree();
21
- const prevMeshesRef = useRef<{ mesh: THREE.Mesh; originalEmissive: THREE.Color; originalIntensity: number }[]>([]);
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 highlights
25
- for (const entry of prevMeshesRef.current) {
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
- prevMeshesRef.current = [];
31
+ prevRef.current = [];
33
32
 
34
- if (bodyId === null || bodyId < 0) return;
35
-
36
- // Find all meshes belonging to this body
33
+ // Apply new
37
34
  const highlightColor = new THREE.Color(color);
38
- scene.traverse((obj) => {
39
- if (obj.userData.bodyID === bodyId && (obj as THREE.Mesh).isMesh) {
40
- const mesh = obj as THREE.Mesh;
41
- const mat = mesh.material as THREE.MeshStandardMaterial;
42
- if (mat.emissive) {
43
- prevMeshesRef.current.push({
44
- mesh,
45
- originalEmissive: mat.emissive.clone(),
46
- originalIntensity: mat.emissiveIntensity ?? 0,
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 prevMeshesRef.current) {
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
- prevMeshesRef.current = [];
56
+ prevRef.current = [];
63
57
  };
64
- }, [bodyId, color, emissiveIntensity, scene]);
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,