mujoco-react 9.3.0 → 9.4.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/dist/spark.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as _sparkjsdev_spark from '@sparkjsdev/spark';
3
- import { n as SplatEnvironmentProps, q as PairedSplatEnvironmentConfig, S as SceneConfig, t as SplatEnvironmentReadiness, o as VisualScenarioConfig } from './types-oxbxOkAx.js';
3
+ import { n as SplatEnvironmentProps, q as PairedSplatEnvironmentConfig, S as SceneConfig, t as SplatEnvironmentReadiness, o as VisualScenarioConfig } from './types-BuJ4boaq.js';
4
4
  import 'react';
5
5
  import '@react-three/fiber';
6
6
  import 'three';
package/dist/spark.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useSplatSceneConfig, useSplatEnvironment, SplatEnvironment } from './chunk-T3GVZJ4F.js';
1
+ import { useSplatSceneConfig, useSplatEnvironment, SplatEnvironment } from './chunk-VDSEPZYQ.js';
2
2
  import { useThree } from '@react-three/fiber';
3
3
  import { useMemo, useState, useEffect, useCallback, useRef } from 'react';
4
4
  import * as THREE from 'three';
@@ -713,8 +713,8 @@ interface PairedSplatEnvironmentConfig {
713
713
  description?: string;
714
714
  /** Visual-only Gaussian splat asset. */
715
715
  splat: SplatAssetConfig;
716
- /** MJCF/XML contact geometry paired with the visual splat. */
717
- collisionProxy: SplatCollisionProxyConfig & {
716
+ /** Optional MJCF/XML contact geometry paired with the visual splat. */
717
+ collisionProxy?: SplatCollisionProxyConfig & {
718
718
  xmlPath: string;
719
719
  };
720
720
  }
@@ -750,6 +750,44 @@ interface SplatEnvironmentMetadata {
750
750
  readiness: SplatEnvironmentReadiness;
751
751
  userData: Record<string, unknown>;
752
752
  }
753
+ interface ResolvedScenarioCameraConfig {
754
+ jitter: number;
755
+ exposure: number;
756
+ noise: number;
757
+ blur: number;
758
+ }
759
+ interface ResolvedScenarioMaterialConfig {
760
+ randomizeObjectColors: boolean;
761
+ randomizeTableMaterial: boolean;
762
+ roughness?: number;
763
+ metalness?: number;
764
+ }
765
+ interface VisualScenarioExecutionContext {
766
+ scenarioId: string;
767
+ scenarioLabel: string;
768
+ variantId?: string;
769
+ seed: number;
770
+ lighting: ScenarioLightingPreset;
771
+ environment?: string;
772
+ camera: ResolvedScenarioCameraConfig;
773
+ materials: ResolvedScenarioMaterialConfig;
774
+ splatEnabled: boolean;
775
+ splatSrc?: string;
776
+ splatFormat: SplatFormat;
777
+ splatRenderer?: SplatRendererKind;
778
+ collisionProxyXmlPath?: string;
779
+ collisionProxyStatus?: SplatCollisionProxyConfig['status'];
780
+ collisionProxyPrimitives: SplatCollisionPrimitive[];
781
+ readiness: SplatEnvironmentReadiness;
782
+ transformSource: 'visualScenario.camera';
783
+ }
784
+ interface VisualScenarioExecutionContextInput {
785
+ scenario?: VisualScenarioConfig;
786
+ environment?: PairedSplatEnvironmentConfig;
787
+ renderer?: SplatRendererKind;
788
+ variantId?: string;
789
+ enabled?: boolean;
790
+ }
753
791
  type SplatSceneInput = PairedSplatEnvironmentConfig | VisualScenarioConfig | undefined | null;
754
792
  interface SplatSceneConfigInput {
755
793
  sceneConfig: SceneConfig;
@@ -1126,4 +1164,4 @@ interface JointStateResult {
1126
1164
  velocity: React__default.RefObject<number | Float64Array>;
1127
1165
  }
1128
1166
 
1129
- export { type Actuators as $, type ActuatedJointInfo as A, type BodyProps as B, type ControlGroupInfo as C, type DragInteractionProps as D, type SplatSceneConfigState as E, type SplatSceneInput as F, type DebugProps as G, type GeomInfo as H, type IkConfig as I, type ContactListenerProps as J, type ActuatorInfo as K, type Sites as L, type MujocoContextValue as M, type SitePositionResult as N, type ObservationConfig as O, type PhysicsStepCallback as P, type Sensors as Q, type ReadyCallbackInput as R, type SceneConfig as S, type TrajectoryPlayerProps as T, type SensorHandle as U, type VisualScenarioEffectsProps as V, type SensorInfo as W, type Joints as X, type JointStateResult as Y, type Bodies as Z, type BodyStateResult as _, type MujocoCanvasProps as a, RobotJoints as a$, type CtrlHandle as a0, type ContactInfo as a1, type KeyboardTeleopConfig as a2, type PolicyConfig as a3, type PolicyVector as a4, type ObservationHandle as a5, type TrajectoryInput as a6, type TrajectoryStateChangeInput as a7, type PlaybackState as a8, type TrajectoryFrame as a9, type Geoms as aA, type IKSolveFn as aB, type IkGizmoDragInput as aC, type IkSolveInput as aD, type JointInfo as aE, type KeyBinding as aF, type Keyframes as aG, type ModelOptions as aH, type MujocoContact as aI, type MujocoContactArray as aJ, type MujocoFrameCaptureOptions as aK, type ObservationLayoutItem as aL, type ObservationOutput as aM, type PhysicsConfig as aN, type PhysicsStepInput as aO, type PolicyActionInput as aP, type PolicyInferenceInput as aQ, type PolicyObservationInput as aR, type RayHit as aS, type Register as aT, type RegisteredRobotMap as aU, type ResetCallbackInput as aV, type ResourceSelector as aW, RobotActuators as aX, RobotBodies as aY, RobotCameras as aZ, RobotGeoms as a_, type FrameCaptureOptions as aa, type FrameCaptureResult as ab, type FrameCaptureBlobResult as ac, type FrameCaptureAPI as ad, type CameraFrameCaptureOptions as ae, type CameraFrameCaptureAPI as af, type CameraFrameSequenceRecorderAPI as ag, type Cameras as ah, type CameraFrameSequenceCamera as ai, type CameraFrameCaptureSource as aj, type CameraFrameSequenceOptions as ak, type CameraFrameSequenceResult as al, type CameraFrameCaptureResult as am, type CameraFrameCaptureBlobResult as an, type BodyInfo as ao, type CameraFrameCaptureQuaternion as ap, type CameraFrameCaptureVector3 as aq, type CameraFrameSequenceCameraSummary as ar, type CameraFrameSequenceFrame as as, type CameraFrameSequenceSampleInput as at, type CameraFrameSequenceStepInput as au, type CameraInfo as av, type ControlJointInfo as aw, type FrameCaptureStatus as ax, type FrameCaptureTarget as ay, type FrameCaptureTargetRef as az, type MujocoSimAPI as b, RobotKeyframes as b0, type RobotResource as b1, RobotResources as b2, RobotSensors as b3, RobotSites as b4, type Robots as b5, type ScenarioCameraConfig as b6, type ScenarioMaterialConfig as b7, type SceneMarker as b8, type SceneObject as b9, type SensorResult as ba, type SiteInfo as bb, type SplatAssetConfig as bc, type SplatScenarioConfig as bd, type StateSnapshot as be, type TrajectoryData as bf, type TrajectoryFrameCallbackInput as bg, type VisualScenarioMaterialFilterInput as bh, type XmlPatch as bi, getContact as bj, registerRobotResources as bk, type StepCallbackInput as c, type SelectionCallbackInput as d, type MujocoModule as e, type MujocoModel as f, type MujocoData as g, type ControlGroupSelector as h, type ObservationResult as i, type IkContextValue as j, type IkGizmoProps as k, type SceneLightsProps as l, type ScenarioLightingProps as m, type SplatEnvironmentProps as n, type VisualScenarioConfig as o, type SplatRendererKind as p, type PairedSplatEnvironmentConfig as q, type SplatFormat as r, type SplatCollisionProxyConfig as s, type SplatEnvironmentReadiness as t, type SplatCollisionPrimitive as u, SplatEnvironmentReadinessStatus as v, type ScenarioLightingPreset as w, type SplatEnvironmentMetadataInput as x, type SplatEnvironmentMetadata as y, type SplatSceneConfigInput as z };
1167
+ export { type Bodies as $, type ActuatedJointInfo as A, type BodyProps as B, type ControlGroupInfo as C, type DragInteractionProps as D, type ScenarioLightingPreset as E, type SplatEnvironmentMetadataInput as F, type SplatEnvironmentMetadata as G, type SplatSceneInput as H, type IkConfig as I, type DebugProps as J, type GeomInfo as K, type ContactListenerProps as L, type MujocoContextValue as M, type ActuatorInfo as N, type ObservationConfig as O, type PhysicsStepCallback as P, type Sites as Q, type ReadyCallbackInput as R, type SceneConfig as S, type TrajectoryPlayerProps as T, type SitePositionResult as U, type VisualScenarioEffectsProps as V, type Sensors as W, type SensorHandle as X, type SensorInfo as Y, type Joints as Z, type JointStateResult as _, type MujocoCanvasProps as a, RobotActuators as a$, type BodyStateResult as a0, type Actuators as a1, type CtrlHandle as a2, type ContactInfo as a3, type KeyboardTeleopConfig as a4, type PolicyConfig as a5, type PolicyVector as a6, type ObservationHandle as a7, type TrajectoryInput as a8, type TrajectoryStateChangeInput as a9, type FrameCaptureTarget as aA, type FrameCaptureTargetRef as aB, type Geoms as aC, type IKSolveFn as aD, type IkGizmoDragInput as aE, type IkSolveInput as aF, type JointInfo as aG, type KeyBinding as aH, type Keyframes as aI, type ModelOptions as aJ, type MujocoContact as aK, type MujocoContactArray as aL, type MujocoFrameCaptureOptions as aM, type ObservationLayoutItem as aN, type ObservationOutput as aO, type PhysicsConfig as aP, type PhysicsStepInput as aQ, type PolicyActionInput as aR, type PolicyInferenceInput as aS, type PolicyObservationInput as aT, type RayHit as aU, type Register as aV, type RegisteredRobotMap as aW, type ResetCallbackInput as aX, type ResolvedScenarioCameraConfig as aY, type ResolvedScenarioMaterialConfig as aZ, type ResourceSelector as a_, type PlaybackState as aa, type TrajectoryFrame as ab, type FrameCaptureOptions as ac, type FrameCaptureResult as ad, type FrameCaptureBlobResult as ae, type FrameCaptureAPI as af, type CameraFrameCaptureOptions as ag, type CameraFrameCaptureAPI as ah, type CameraFrameSequenceRecorderAPI as ai, type Cameras as aj, type CameraFrameSequenceCamera as ak, type CameraFrameCaptureSource as al, type CameraFrameSequenceOptions as am, type CameraFrameSequenceResult as an, type CameraFrameCaptureResult as ao, type CameraFrameCaptureBlobResult as ap, type BodyInfo as aq, type CameraFrameCaptureQuaternion as ar, type CameraFrameCaptureVector3 as as, type CameraFrameSequenceCameraSummary as at, type CameraFrameSequenceFrame as au, type CameraFrameSequenceSampleInput as av, type CameraFrameSequenceStepInput as aw, type CameraInfo as ax, type ControlJointInfo as ay, type FrameCaptureStatus as az, type MujocoSimAPI as b, RobotBodies as b0, RobotCameras as b1, RobotGeoms as b2, RobotJoints as b3, RobotKeyframes as b4, type RobotResource as b5, RobotResources as b6, RobotSensors as b7, RobotSites as b8, type Robots as b9, type ScenarioCameraConfig as ba, type ScenarioMaterialConfig as bb, type SceneMarker as bc, type SceneObject as bd, type SensorResult as be, type SiteInfo as bf, type SplatAssetConfig as bg, type SplatScenarioConfig as bh, type StateSnapshot as bi, type TrajectoryData as bj, type TrajectoryFrameCallbackInput as bk, type VisualScenarioMaterialFilterInput as bl, type XmlPatch as bm, getContact as bn, registerRobotResources as bo, type StepCallbackInput as c, type SelectionCallbackInput as d, type MujocoModule as e, type MujocoModel as f, type MujocoData as g, type ControlGroupSelector as h, type ObservationResult as i, type IkContextValue as j, type IkGizmoProps as k, type SceneLightsProps as l, type ScenarioLightingProps as m, type SplatEnvironmentProps as n, type VisualScenarioConfig as o, type SplatRendererKind as p, type PairedSplatEnvironmentConfig as q, type SplatFormat as r, type SplatCollisionProxyConfig as s, type SplatEnvironmentReadiness as t, type SplatCollisionPrimitive as u, SplatEnvironmentReadinessStatus as v, type SplatSceneConfigInput as w, type SplatSceneConfigState as x, type VisualScenarioExecutionContextInput as y, type VisualScenarioExecutionContext as z };
package/dist/vite.js CHANGED
@@ -92,7 +92,7 @@ async function generateMujocoRegister(options) {
92
92
  };
93
93
  }
94
94
  async function scanModel(filePath, root, seen, names) {
95
- const normalized = path.normalize(filePath);
95
+ const normalized = path.resolve(filePath);
96
96
  if (seen.has(normalized)) return;
97
97
  seen.add(normalized);
98
98
  const xml = await readFile(normalized, "utf8");
@@ -106,7 +106,7 @@ async function scanModel(filePath, root, seen, names) {
106
106
  collectSectionNames(xml, "sensor", names.sensors);
107
107
  for (const includePath of collectIncludePaths(xml)) {
108
108
  const next = path.resolve(path.dirname(normalized), includePath);
109
- if (next.startsWith(root)) await scanModel(next, root, seen, names);
109
+ if (isPathInsideRoot(next, root)) await scanModel(next, root, seen, names);
110
110
  }
111
111
  }
112
112
  function collectSimpleTagNames(xml, tag, target) {
@@ -254,7 +254,7 @@ function shouldInjectRegisterImport(id, root, generatedRegister) {
254
254
  if (file.includes(`${path.sep}node_modules${path.sep}`)) return false;
255
255
  const absolute = path.resolve(file);
256
256
  if (absolute === generatedRegister) return false;
257
- return absolute.startsWith(root);
257
+ return isPathInsideRoot(absolute, root);
258
258
  }
259
259
  function renderGeneratedImport(id, generatedRegister) {
260
260
  const fromDir = path.dirname(stripQuery(id));
@@ -295,7 +295,11 @@ function shouldRegenerate(file, watchedFiles, models, root) {
295
295
  if (watchedFiles.includes(absolute)) return true;
296
296
  if (!MODEL_EXTENSIONS.has(path.extname(absolute).toLowerCase())) return false;
297
297
  const modelDirs = models.map((model) => path.dirname(path.resolve(root, model.file)));
298
- return modelDirs.some((dir) => absolute.startsWith(dir));
298
+ return modelDirs.some((dir) => isPathInsideRoot(absolute, dir));
299
+ }
300
+ function isPathInsideRoot(filePath, root) {
301
+ const relative = path.relative(path.resolve(root), path.resolve(filePath));
302
+ return relative === "" || relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
299
303
  }
300
304
  /**
301
305
  * @license
package/dist/vite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vite.ts"],"names":[],"mappings":"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","file":"vite.js","sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\n\ntype ViteConfig = { root: string };\ntype ViteServer = {\n watcher: {\n add(paths: string | string[]): void;\n on(event: 'add' | 'change' | 'unlink', listener: (file: string) => void): void;\n };\n};\n\nexport interface MujocoReactPluginOptions {\n /** Entry MJCF/URDF files to scan. Prefer a record for stable per-robot type names. */\n models: ModelInput;\n /** Generated resource module. Defaults to `src/mujoco-register.gen.ts`. */\n generatedRegister?: string;\n /** Module name to augment. Defaults to `mujoco-react`. */\n moduleName?: string;\n /** Disable console output. */\n disableLogging?: boolean;\n}\n\nexport interface MujocoRegisterCodegenOptions {\n models: ModelInput;\n out: string;\n moduleName?: string;\n root?: string;\n}\n\nexport interface MujocoRegisterCodegenResult {\n out: string;\n files: string[];\n counts: Record<RegisterKey, number>;\n}\n\ntype RegisterKey = 'actuators' | 'sensors' | 'bodies' | 'joints' | 'sites' | 'geoms' | 'keyframes' | 'cameras';\nexport type ModelInput = string | readonly string[] | Record<string, string>;\n\ninterface ModelEntry {\n id: string;\n file: string;\n names: Record<RegisterKey, Set<string>>;\n}\n\nconst REGISTER_KEYS: RegisterKey[] = ['actuators', 'sensors', 'bodies', 'joints', 'sites', 'geoms', 'keyframes', 'cameras'];\nconst MODEL_EXTENSIONS = new Set(['.xml', '.mjcf', '.urdf']);\n\nfunction createEmptyNames(): Record<RegisterKey, Set<string>> {\n return {\n actuators: new Set(),\n sensors: new Set(),\n bodies: new Set(),\n joints: new Set(),\n sites: new Set(),\n geoms: new Set(),\n keyframes: new Set(),\n cameras: new Set(),\n };\n}\n\nexport function mujocoReact(options: MujocoReactPluginOptions) {\n const models = normalizeModels(options.models);\n let root = process.cwd();\n let generatedRegister = options.generatedRegister ?? 'src/mujoco-register.gen.ts';\n let watchedFiles: string[] = [];\n\n async function generate() {\n const result = await generateMujocoRegister({\n models: options.models,\n out: generatedRegister,\n moduleName: options.moduleName,\n root,\n });\n watchedFiles = result.files;\n if (!options.disableLogging) {\n const total = Object.values(result.counts).reduce((sum, count) => sum + count, 0);\n console.log(`[mujoco-react] generated ${path.relative(root, result.out)} (${total} names)`);\n }\n return result;\n }\n\n return {\n name: 'mujoco-react',\n enforce: 'pre' as const,\n config(userConfig: { build?: { chunkSizeWarningLimit?: number } }) {\n // three + drei + MuJoCo WASM glue are inherently large; the large-chunk\n // warning is expected, not a failure. Raise the limit so consumers don't\n // see it. Vite merges plugin config on top of user config, so only set a\n // default when the consumer hasn't specified their own limit.\n if (userConfig.build?.chunkSizeWarningLimit !== undefined) return;\n return { build: { chunkSizeWarningLimit: 4000 } };\n },\n configResolved(config: ViteConfig) {\n root = config.root;\n generatedRegister = path.resolve(root, generatedRegister);\n },\n transform(code: string, id: string) {\n if (!shouldInjectRegisterImport(id, root, generatedRegister)) return;\n return `${renderGeneratedImport(id, generatedRegister)}\\n${code}`;\n },\n async buildStart(this: { addWatchFile?: (file: string) => void }) {\n const result = await generate();\n for (const file of result.files) this.addWatchFile?.(file);\n },\n configureServer(server: ViteServer) {\n generate().then((result) => server.watcher.add(result.files)).catch((error: unknown) => {\n console.error('[mujoco-react] register generation failed', error);\n });\n\n server.watcher.on('add', regenerateIfModelFile);\n server.watcher.on('change', regenerateIfModelFile);\n server.watcher.on('unlink', regenerateIfModelFile);\n\n function regenerateIfModelFile(file: string) {\n if (!shouldRegenerate(file, watchedFiles, models, root)) return;\n generate().then((result) => server.watcher.add(result.files)).catch((error: unknown) => {\n console.error('[mujoco-react] register generation failed', error);\n });\n }\n },\n };\n}\n\nexport async function generateMujocoRegister(\n options: MujocoRegisterCodegenOptions\n): Promise<MujocoRegisterCodegenResult> {\n const root = path.resolve(options.root ?? process.cwd());\n const out = path.resolve(root, options.out);\n const moduleName = options.moduleName ?? 'mujoco-react';\n const models = normalizeModels(options.models);\n const names = createEmptyNames();\n const seen = new Set<string>();\n const declarationsOnly = out.endsWith('.d.ts');\n\n for (const model of models) {\n await scanModel(path.resolve(root, model.file), root, seen, model.names);\n mergeNames(names, model.names);\n }\n\n await mkdir(path.dirname(out), { recursive: true });\n await writeFile(out, renderRegister(moduleName, names, models, declarationsOnly), 'utf8');\n\n return {\n out,\n files: [...seen].sort((a, b) => a.localeCompare(b)),\n counts: Object.fromEntries(REGISTER_KEYS.map((key) => [key, names[key].size])) as Record<RegisterKey, number>,\n };\n}\n\nasync function scanModel(\n filePath: string,\n root: string,\n seen: Set<string>,\n names: Record<RegisterKey, Set<string>>\n) {\n const normalized = path.normalize(filePath);\n if (seen.has(normalized)) return;\n seen.add(normalized);\n\n const xml = await readFile(normalized, 'utf8');\n collectSimpleTagNames(xml, 'body', names.bodies);\n collectSimpleTagNames(xml, 'joint', names.joints);\n collectSimpleTagNames(xml, 'site', names.sites);\n collectSimpleTagNames(xml, 'geom', names.geoms);\n collectSimpleTagNames(xml, 'camera', names.cameras);\n collectSimpleTagNames(xml, 'key', names.keyframes);\n collectSectionNames(xml, 'actuator', names.actuators);\n collectSectionNames(xml, 'sensor', names.sensors);\n\n for (const includePath of collectIncludePaths(xml)) {\n const next = path.resolve(path.dirname(normalized), includePath);\n if (next.startsWith(root)) await scanModel(next, root, seen, names);\n }\n}\n\nfunction collectSimpleTagNames(xml: string, tag: string, target: Set<string>) {\n const pattern = new RegExp(`<\\\\s*${tag}\\\\b([^>]*)>`, 'gi');\n for (const match of xml.matchAll(pattern)) {\n const name = readAttr(match[1], 'name');\n if (name) target.add(name);\n }\n}\n\nfunction collectSectionNames(xml: string, section: string, target: Set<string>) {\n const sectionPattern = new RegExp(`<\\\\s*${section}\\\\b[^>]*>([\\\\s\\\\S]*?)<\\\\s*/\\\\s*${section}\\\\s*>`, 'gi');\n for (const sectionMatch of xml.matchAll(sectionPattern)) {\n const tagPattern = /<\\s*[a-zA-Z0-9_:-]+\\b([^>]*)>/g;\n for (const tagMatch of sectionMatch[1].matchAll(tagPattern)) {\n const name = readAttr(tagMatch[1], 'name');\n if (name) target.add(name);\n }\n }\n}\n\nfunction collectIncludePaths(xml: string): string[] {\n const result: string[] = [];\n const pattern = /<\\s*include\\b([^>]*)>/gi;\n for (const match of xml.matchAll(pattern)) {\n const file = readAttr(match[1], 'file');\n if (file && !file.includes('://') && !file.startsWith('/')) result.push(file);\n }\n return result;\n}\n\nfunction readAttr(attrs: string, attr: string): string | undefined {\n const pattern = new RegExp(`\\\\b${attr}\\\\s*=\\\\s*(['\"])(.*?)\\\\1`, 'i');\n return attrs.match(pattern)?.[2];\n}\n\nfunction renderRegister(\n moduleName: string,\n names: Record<RegisterKey, Set<string>>,\n models: readonly ModelEntry[],\n declarationsOnly: boolean\n): string {\n const fields = REGISTER_KEYS\n .filter((key) => names[key].size > 0)\n .map((key) => ` ${key}: ${renderUnion(names[key])};`);\n const robots = models\n .map((model) => ` ${quoteProperty(model.id)}: {\\n${renderRobotFields(model.names)}\\n };`);\n const namespaceAliases = renderNamespaceAliases(models);\n const registerImport = declarationsOnly ? '' : `import { registerRobotResources } from '${moduleName}';\\n`;\n const resources = declarationsOnly ? '' : `${renderResourceTypes(models)}\\n\\n${renderResourceConstants(models)}\\n\\nregisterRobotResources(generatedRobotResources);\\n\\n`;\n\n return `// Auto-generated by mujoco-react. Do not edit.\n// Regenerate by running Vite with the mujocoReact() plugin or \\`mujoco-react codegen\\`.\n\n${registerImport}import type { RobotResource } from '${moduleName}';\n\n${resources}declare module '${moduleName}' {\n interface Register {\n robots: {\n${robots.join('\\n')}\n };\n${fields.join('\\n')}\n }\n\n${namespaceAliases}\n}\n`;\n}\n\nfunction renderResourceTypes(models: readonly ModelEntry[]): string {\n const modelTypes = models\n .map((model) => ` readonly ${quoteProperty(model.id)}: {\\n${renderResourceTypeFields(model.names)}\\n };`)\n .join('\\n');\n return `type GeneratedRobotResources = {\\n${modelTypes}\\n};`;\n}\n\nfunction renderResourceTypeFields(names: Record<RegisterKey, Set<string>>): string {\n return REGISTER_KEYS\n .map((key) => ` readonly ${key}: ${renderResourceObjectType(names[key])};`)\n .join('\\n');\n}\n\nfunction renderResourceObjectType(values: Set<string>): string {\n const entries = sortedValues(values)\n .map((value) => ` readonly ${quoteProperty(value)}: '${escapeTs(value)}';`);\n return entries.length > 0 ? `{\\n${entries.join('\\n')}\\n }` : '{}';\n}\n\nfunction renderResourceConstants(models: readonly ModelEntry[]): string {\n const entries = models\n .map((model) => ` ${quoteProperty(model.id)}: {\\n${renderResourceConstantFields(model.names)}\\n },`)\n .join('\\n');\n return `const generatedRobotResources: GeneratedRobotResources = {\\n${entries}\\n};`;\n}\n\nfunction renderResourceConstantFields(names: Record<RegisterKey, Set<string>>): string {\n return REGISTER_KEYS\n .map((key) => ` ${key}: ${renderResourceObject(names[key])},`)\n .join('\\n');\n}\n\nfunction renderResourceObject(values: Set<string>): string {\n const entries = sortedValues(values)\n .map((value) => ` ${quoteProperty(value)}: '${escapeTs(value)}',`);\n return entries.length > 0 ? `{\\n${entries.join('\\n')}\\n }` : '{}';\n}\n\nfunction renderRobotFields(names: Record<RegisterKey, Set<string>>): string {\n return REGISTER_KEYS\n .map((key) => ` ${key}: ${names[key].size > 0 ? renderUnion(names[key]) : 'never'};`)\n .join('\\n');\n}\n\nfunction renderUnion(values: Set<string>): string {\n return sortedValues(values).map((value) => `'${escapeTs(value)}'`).join(' | ');\n}\n\nfunction renderNamespaceAliases(models: readonly ModelEntry[]): string {\n const namespaces: Record<RegisterKey, string> = {\n actuators: 'RobotActuators',\n sensors: 'RobotSensors',\n bodies: 'RobotBodies',\n joints: 'RobotJoints',\n sites: 'RobotSites',\n geoms: 'RobotGeoms',\n keyframes: 'RobotKeyframes',\n cameras: 'RobotCameras',\n };\n\n const blocks = REGISTER_KEYS\n .map((key) => {\n const aliases = models\n .filter((model) => isIdentifier(model.id))\n .map((model) => ` export type ${model.id} = RobotResource<'${escapeTs(model.id)}', '${key}'>;`);\n if (aliases.length === 0) return '';\n return ` export namespace ${namespaces[key]} {\\n${aliases.join('\\n')}\\n }`;\n })\n .filter(Boolean)\n .join('\\n\\n');\n\n return blocks ? `${blocks}\\n` : '';\n}\n\nfunction escapeTs(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nfunction sortedValues(values: Set<string>): string[] {\n return [...values].sort((a, b) => a.localeCompare(b));\n}\n\nfunction quoteProperty(value: string): string {\n return isIdentifier(value) ? value : `'${escapeTs(value)}'`;\n}\n\nfunction isIdentifier(value: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);\n}\n\nfunction toPosixPath(value: string): string {\n return value.split(path.sep).join('/');\n}\n\nfunction shouldInjectRegisterImport(id: string, root: string, generatedRegister: string): boolean {\n if (generatedRegister.endsWith('.d.ts')) return false;\n const file = stripQuery(id);\n if (!/\\.[cm]?[jt]sx?$/.test(file)) return false;\n if (file.includes(`${path.sep}node_modules${path.sep}`)) return false;\n const absolute = path.resolve(file);\n if (absolute === generatedRegister) return false;\n return absolute.startsWith(root);\n}\n\nfunction renderGeneratedImport(id: string, generatedRegister: string): string {\n const fromDir = path.dirname(stripQuery(id));\n let relative = toPosixPath(path.relative(fromDir, generatedRegister));\n if (!relative.startsWith('.')) relative = `./${relative}`;\n return `import '${relative}';`;\n}\n\nfunction stripQuery(id: string): string {\n return id.split('?')[0];\n}\n\nfunction normalizeModels(input: ModelInput): ModelEntry[] {\n if (typeof input === 'string') return [createModelEntry(deriveModelId(input), input)];\n if (Array.isArray(input)) return input.map((file) => createModelEntry(deriveModelId(file), file));\n return Object.entries(input).map(([id, file]) => createModelEntry(sanitizeModelId(id), file));\n}\n\nfunction createModelEntry(id: string, file: string): ModelEntry {\n return { id, file, names: createEmptyNames() };\n}\n\nfunction deriveModelId(file: string): string {\n const normalized = file.replace(/\\\\/g, '/');\n const parts = normalized.split('/').filter(Boolean);\n const filename = parts.at(-1) ?? 'model';\n const parent = parts.length > 1 ? parts.at(-2) : undefined;\n const base = filename.replace(/\\.(xml|mjcf|urdf)$/i, '');\n return sanitizeModelId(parent && ['scene', 'model', 'robot'].includes(base.toLowerCase()) ? parent : base);\n}\n\nfunction sanitizeModelId(value: string): string {\n const sanitized = value.replace(/[^A-Za-z0-9_$]/g, '_').replace(/^[^A-Za-z_$]+/, '');\n return sanitized || 'model';\n}\n\nfunction mergeNames(target: Record<RegisterKey, Set<string>>, source: Record<RegisterKey, Set<string>>) {\n for (const key of REGISTER_KEYS) {\n for (const value of source[key]) target[key].add(value);\n }\n}\n\nfunction shouldRegenerate(file: string, watchedFiles: string[], models: readonly ModelEntry[], root: string): boolean {\n const absolute = path.resolve(file);\n if (watchedFiles.includes(absolute)) return true;\n if (!MODEL_EXTENSIONS.has(path.extname(absolute).toLowerCase())) return false;\n const modelDirs = models.map((model) => path.dirname(path.resolve(root, model.file)));\n return modelDirs.some((dir) => absolute.startsWith(dir));\n}\n"]}
1
+ {"version":3,"sources":["../src/vite.ts"],"names":[],"mappings":"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","file":"vite.js","sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\n\ntype ViteConfig = { root: string };\ntype ViteServer = {\n watcher: {\n add(paths: string | string[]): void;\n on(event: 'add' | 'change' | 'unlink', listener: (file: string) => void): void;\n };\n};\n\nexport interface MujocoReactPluginOptions {\n /** Entry MJCF/URDF files to scan. Prefer a record for stable per-robot type names. */\n models: ModelInput;\n /** Generated resource module. Defaults to `src/mujoco-register.gen.ts`. */\n generatedRegister?: string;\n /** Module name to augment. Defaults to `mujoco-react`. */\n moduleName?: string;\n /** Disable console output. */\n disableLogging?: boolean;\n}\n\nexport interface MujocoRegisterCodegenOptions {\n models: ModelInput;\n out: string;\n moduleName?: string;\n root?: string;\n}\n\nexport interface MujocoRegisterCodegenResult {\n out: string;\n files: string[];\n counts: Record<RegisterKey, number>;\n}\n\ntype RegisterKey = 'actuators' | 'sensors' | 'bodies' | 'joints' | 'sites' | 'geoms' | 'keyframes' | 'cameras';\nexport type ModelInput = string | readonly string[] | Record<string, string>;\n\ninterface ModelEntry {\n id: string;\n file: string;\n names: Record<RegisterKey, Set<string>>;\n}\n\nconst REGISTER_KEYS: RegisterKey[] = ['actuators', 'sensors', 'bodies', 'joints', 'sites', 'geoms', 'keyframes', 'cameras'];\nconst MODEL_EXTENSIONS = new Set(['.xml', '.mjcf', '.urdf']);\n\nfunction createEmptyNames(): Record<RegisterKey, Set<string>> {\n return {\n actuators: new Set(),\n sensors: new Set(),\n bodies: new Set(),\n joints: new Set(),\n sites: new Set(),\n geoms: new Set(),\n keyframes: new Set(),\n cameras: new Set(),\n };\n}\n\nexport function mujocoReact(options: MujocoReactPluginOptions) {\n const models = normalizeModels(options.models);\n let root = process.cwd();\n let generatedRegister = options.generatedRegister ?? 'src/mujoco-register.gen.ts';\n let watchedFiles: string[] = [];\n\n async function generate() {\n const result = await generateMujocoRegister({\n models: options.models,\n out: generatedRegister,\n moduleName: options.moduleName,\n root,\n });\n watchedFiles = result.files;\n if (!options.disableLogging) {\n const total = Object.values(result.counts).reduce((sum, count) => sum + count, 0);\n console.log(`[mujoco-react] generated ${path.relative(root, result.out)} (${total} names)`);\n }\n return result;\n }\n\n return {\n name: 'mujoco-react',\n enforce: 'pre' as const,\n config(userConfig: { build?: { chunkSizeWarningLimit?: number } }) {\n // three + drei + MuJoCo WASM glue are inherently large; the large-chunk\n // warning is expected, not a failure. Raise the limit so consumers don't\n // see it. Vite merges plugin config on top of user config, so only set a\n // default when the consumer hasn't specified their own limit.\n if (userConfig.build?.chunkSizeWarningLimit !== undefined) return;\n return { build: { chunkSizeWarningLimit: 4000 } };\n },\n configResolved(config: ViteConfig) {\n root = config.root;\n generatedRegister = path.resolve(root, generatedRegister);\n },\n transform(code: string, id: string) {\n if (!shouldInjectRegisterImport(id, root, generatedRegister)) return;\n return `${renderGeneratedImport(id, generatedRegister)}\\n${code}`;\n },\n async buildStart(this: { addWatchFile?: (file: string) => void }) {\n const result = await generate();\n for (const file of result.files) this.addWatchFile?.(file);\n },\n configureServer(server: ViteServer) {\n generate().then((result) => server.watcher.add(result.files)).catch((error: unknown) => {\n console.error('[mujoco-react] register generation failed', error);\n });\n\n server.watcher.on('add', regenerateIfModelFile);\n server.watcher.on('change', regenerateIfModelFile);\n server.watcher.on('unlink', regenerateIfModelFile);\n\n function regenerateIfModelFile(file: string) {\n if (!shouldRegenerate(file, watchedFiles, models, root)) return;\n generate().then((result) => server.watcher.add(result.files)).catch((error: unknown) => {\n console.error('[mujoco-react] register generation failed', error);\n });\n }\n },\n };\n}\n\nexport async function generateMujocoRegister(\n options: MujocoRegisterCodegenOptions\n): Promise<MujocoRegisterCodegenResult> {\n const root = path.resolve(options.root ?? process.cwd());\n const out = path.resolve(root, options.out);\n const moduleName = options.moduleName ?? 'mujoco-react';\n const models = normalizeModels(options.models);\n const names = createEmptyNames();\n const seen = new Set<string>();\n const declarationsOnly = out.endsWith('.d.ts');\n\n for (const model of models) {\n await scanModel(path.resolve(root, model.file), root, seen, model.names);\n mergeNames(names, model.names);\n }\n\n await mkdir(path.dirname(out), { recursive: true });\n await writeFile(out, renderRegister(moduleName, names, models, declarationsOnly), 'utf8');\n\n return {\n out,\n files: [...seen].sort((a, b) => a.localeCompare(b)),\n counts: Object.fromEntries(REGISTER_KEYS.map((key) => [key, names[key].size])) as Record<RegisterKey, number>,\n };\n}\n\nasync function scanModel(\n filePath: string,\n root: string,\n seen: Set<string>,\n names: Record<RegisterKey, Set<string>>\n) {\n const normalized = path.resolve(filePath);\n if (seen.has(normalized)) return;\n seen.add(normalized);\n\n const xml = await readFile(normalized, 'utf8');\n collectSimpleTagNames(xml, 'body', names.bodies);\n collectSimpleTagNames(xml, 'joint', names.joints);\n collectSimpleTagNames(xml, 'site', names.sites);\n collectSimpleTagNames(xml, 'geom', names.geoms);\n collectSimpleTagNames(xml, 'camera', names.cameras);\n collectSimpleTagNames(xml, 'key', names.keyframes);\n collectSectionNames(xml, 'actuator', names.actuators);\n collectSectionNames(xml, 'sensor', names.sensors);\n\n for (const includePath of collectIncludePaths(xml)) {\n const next = path.resolve(path.dirname(normalized), includePath);\n if (isPathInsideRoot(next, root)) await scanModel(next, root, seen, names);\n }\n}\n\nfunction collectSimpleTagNames(xml: string, tag: string, target: Set<string>) {\n const pattern = new RegExp(`<\\\\s*${tag}\\\\b([^>]*)>`, 'gi');\n for (const match of xml.matchAll(pattern)) {\n const name = readAttr(match[1], 'name');\n if (name) target.add(name);\n }\n}\n\nfunction collectSectionNames(xml: string, section: string, target: Set<string>) {\n const sectionPattern = new RegExp(`<\\\\s*${section}\\\\b[^>]*>([\\\\s\\\\S]*?)<\\\\s*/\\\\s*${section}\\\\s*>`, 'gi');\n for (const sectionMatch of xml.matchAll(sectionPattern)) {\n const tagPattern = /<\\s*[a-zA-Z0-9_:-]+\\b([^>]*)>/g;\n for (const tagMatch of sectionMatch[1].matchAll(tagPattern)) {\n const name = readAttr(tagMatch[1], 'name');\n if (name) target.add(name);\n }\n }\n}\n\nfunction collectIncludePaths(xml: string): string[] {\n const result: string[] = [];\n const pattern = /<\\s*include\\b([^>]*)>/gi;\n for (const match of xml.matchAll(pattern)) {\n const file = readAttr(match[1], 'file');\n if (file && !file.includes('://') && !file.startsWith('/')) result.push(file);\n }\n return result;\n}\n\nfunction readAttr(attrs: string, attr: string): string | undefined {\n const pattern = new RegExp(`\\\\b${attr}\\\\s*=\\\\s*(['\"])(.*?)\\\\1`, 'i');\n return attrs.match(pattern)?.[2];\n}\n\nfunction renderRegister(\n moduleName: string,\n names: Record<RegisterKey, Set<string>>,\n models: readonly ModelEntry[],\n declarationsOnly: boolean\n): string {\n const fields = REGISTER_KEYS\n .filter((key) => names[key].size > 0)\n .map((key) => ` ${key}: ${renderUnion(names[key])};`);\n const robots = models\n .map((model) => ` ${quoteProperty(model.id)}: {\\n${renderRobotFields(model.names)}\\n };`);\n const namespaceAliases = renderNamespaceAliases(models);\n const registerImport = declarationsOnly ? '' : `import { registerRobotResources } from '${moduleName}';\\n`;\n const resources = declarationsOnly ? '' : `${renderResourceTypes(models)}\\n\\n${renderResourceConstants(models)}\\n\\nregisterRobotResources(generatedRobotResources);\\n\\n`;\n\n return `// Auto-generated by mujoco-react. Do not edit.\n// Regenerate by running Vite with the mujocoReact() plugin or \\`mujoco-react codegen\\`.\n\n${registerImport}import type { RobotResource } from '${moduleName}';\n\n${resources}declare module '${moduleName}' {\n interface Register {\n robots: {\n${robots.join('\\n')}\n };\n${fields.join('\\n')}\n }\n\n${namespaceAliases}\n}\n`;\n}\n\nfunction renderResourceTypes(models: readonly ModelEntry[]): string {\n const modelTypes = models\n .map((model) => ` readonly ${quoteProperty(model.id)}: {\\n${renderResourceTypeFields(model.names)}\\n };`)\n .join('\\n');\n return `type GeneratedRobotResources = {\\n${modelTypes}\\n};`;\n}\n\nfunction renderResourceTypeFields(names: Record<RegisterKey, Set<string>>): string {\n return REGISTER_KEYS\n .map((key) => ` readonly ${key}: ${renderResourceObjectType(names[key])};`)\n .join('\\n');\n}\n\nfunction renderResourceObjectType(values: Set<string>): string {\n const entries = sortedValues(values)\n .map((value) => ` readonly ${quoteProperty(value)}: '${escapeTs(value)}';`);\n return entries.length > 0 ? `{\\n${entries.join('\\n')}\\n }` : '{}';\n}\n\nfunction renderResourceConstants(models: readonly ModelEntry[]): string {\n const entries = models\n .map((model) => ` ${quoteProperty(model.id)}: {\\n${renderResourceConstantFields(model.names)}\\n },`)\n .join('\\n');\n return `const generatedRobotResources: GeneratedRobotResources = {\\n${entries}\\n};`;\n}\n\nfunction renderResourceConstantFields(names: Record<RegisterKey, Set<string>>): string {\n return REGISTER_KEYS\n .map((key) => ` ${key}: ${renderResourceObject(names[key])},`)\n .join('\\n');\n}\n\nfunction renderResourceObject(values: Set<string>): string {\n const entries = sortedValues(values)\n .map((value) => ` ${quoteProperty(value)}: '${escapeTs(value)}',`);\n return entries.length > 0 ? `{\\n${entries.join('\\n')}\\n }` : '{}';\n}\n\nfunction renderRobotFields(names: Record<RegisterKey, Set<string>>): string {\n return REGISTER_KEYS\n .map((key) => ` ${key}: ${names[key].size > 0 ? renderUnion(names[key]) : 'never'};`)\n .join('\\n');\n}\n\nfunction renderUnion(values: Set<string>): string {\n return sortedValues(values).map((value) => `'${escapeTs(value)}'`).join(' | ');\n}\n\nfunction renderNamespaceAliases(models: readonly ModelEntry[]): string {\n const namespaces: Record<RegisterKey, string> = {\n actuators: 'RobotActuators',\n sensors: 'RobotSensors',\n bodies: 'RobotBodies',\n joints: 'RobotJoints',\n sites: 'RobotSites',\n geoms: 'RobotGeoms',\n keyframes: 'RobotKeyframes',\n cameras: 'RobotCameras',\n };\n\n const blocks = REGISTER_KEYS\n .map((key) => {\n const aliases = models\n .filter((model) => isIdentifier(model.id))\n .map((model) => ` export type ${model.id} = RobotResource<'${escapeTs(model.id)}', '${key}'>;`);\n if (aliases.length === 0) return '';\n return ` export namespace ${namespaces[key]} {\\n${aliases.join('\\n')}\\n }`;\n })\n .filter(Boolean)\n .join('\\n\\n');\n\n return blocks ? `${blocks}\\n` : '';\n}\n\nfunction escapeTs(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nfunction sortedValues(values: Set<string>): string[] {\n return [...values].sort((a, b) => a.localeCompare(b));\n}\n\nfunction quoteProperty(value: string): string {\n return isIdentifier(value) ? value : `'${escapeTs(value)}'`;\n}\n\nfunction isIdentifier(value: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value);\n}\n\nfunction toPosixPath(value: string): string {\n return value.split(path.sep).join('/');\n}\n\nfunction shouldInjectRegisterImport(id: string, root: string, generatedRegister: string): boolean {\n if (generatedRegister.endsWith('.d.ts')) return false;\n const file = stripQuery(id);\n if (!/\\.[cm]?[jt]sx?$/.test(file)) return false;\n if (file.includes(`${path.sep}node_modules${path.sep}`)) return false;\n const absolute = path.resolve(file);\n if (absolute === generatedRegister) return false;\n return isPathInsideRoot(absolute, root);\n}\n\nfunction renderGeneratedImport(id: string, generatedRegister: string): string {\n const fromDir = path.dirname(stripQuery(id));\n let relative = toPosixPath(path.relative(fromDir, generatedRegister));\n if (!relative.startsWith('.')) relative = `./${relative}`;\n return `import '${relative}';`;\n}\n\nfunction stripQuery(id: string): string {\n return id.split('?')[0];\n}\n\nfunction normalizeModels(input: ModelInput): ModelEntry[] {\n if (typeof input === 'string') return [createModelEntry(deriveModelId(input), input)];\n if (Array.isArray(input)) return input.map((file) => createModelEntry(deriveModelId(file), file));\n return Object.entries(input).map(([id, file]) => createModelEntry(sanitizeModelId(id), file));\n}\n\nfunction createModelEntry(id: string, file: string): ModelEntry {\n return { id, file, names: createEmptyNames() };\n}\n\nfunction deriveModelId(file: string): string {\n const normalized = file.replace(/\\\\/g, '/');\n const parts = normalized.split('/').filter(Boolean);\n const filename = parts.at(-1) ?? 'model';\n const parent = parts.length > 1 ? parts.at(-2) : undefined;\n const base = filename.replace(/\\.(xml|mjcf|urdf)$/i, '');\n return sanitizeModelId(parent && ['scene', 'model', 'robot'].includes(base.toLowerCase()) ? parent : base);\n}\n\nfunction sanitizeModelId(value: string): string {\n const sanitized = value.replace(/[^A-Za-z0-9_$]/g, '_').replace(/^[^A-Za-z_$]+/, '');\n return sanitized || 'model';\n}\n\nfunction mergeNames(target: Record<RegisterKey, Set<string>>, source: Record<RegisterKey, Set<string>>) {\n for (const key of REGISTER_KEYS) {\n for (const value of source[key]) target[key].add(value);\n }\n}\n\nfunction shouldRegenerate(file: string, watchedFiles: string[], models: readonly ModelEntry[], root: string): boolean {\n const absolute = path.resolve(file);\n if (watchedFiles.includes(absolute)) return true;\n if (!MODEL_EXTENSIONS.has(path.extname(absolute).toLowerCase())) return false;\n const modelDirs = models.map((model) => path.dirname(path.resolve(root, model.file)));\n return modelDirs.some((dir) => isPathInsideRoot(absolute, dir));\n}\n\nfunction isPathInsideRoot(filePath: string, root: string): boolean {\n const relative = path.relative(path.resolve(root), path.resolve(filePath));\n return relative === '' || (relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative));\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mujoco-react",
3
- "version": "9.3.0",
3
+ "version": "9.4.0",
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,350 @@
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ import type { ThreeElements } from '@react-three/fiber';
7
+ import { useEffect, useMemo, useState } from 'react';
8
+ import type { SplatCollisionProxyConfig } from '../types';
9
+
10
+ export type SplatCollisionProxyPreviewVector3 = [number, number, number];
11
+
12
+ export interface SplatCollisionProxyGeomPreview {
13
+ id: string;
14
+ type: 'box' | 'plane' | 'sphere' | 'capsule' | 'mesh';
15
+ position: SplatCollisionProxyPreviewVector3;
16
+ size: number[];
17
+ }
18
+
19
+ export interface SplatCollisionProxyPreviewProps
20
+ extends Omit<ThreeElements['group'], 'ref'> {
21
+ collisionProxy?: SplatCollisionProxyConfig | null;
22
+ xmlText?: string;
23
+ fetchXml?: (xmlPath: string) => Promise<string>;
24
+ color?: string;
25
+ opacity?: number;
26
+ planeColor?: string;
27
+ planeOpacity?: number;
28
+ }
29
+
30
+ export type SplatCollisionProxyPreviewStatus =
31
+ | 'idle'
32
+ | 'loading'
33
+ | 'ready'
34
+ | 'error';
35
+
36
+ export interface UseSplatCollisionProxyGeomsOptions {
37
+ collisionProxy?: SplatCollisionProxyConfig | null;
38
+ xmlText?: string;
39
+ fetchXml?: (xmlPath: string) => Promise<string>;
40
+ enabled?: boolean;
41
+ }
42
+
43
+ export interface SplatCollisionProxyGeomsState {
44
+ geoms: SplatCollisionProxyGeomPreview[];
45
+ status: SplatCollisionProxyPreviewStatus;
46
+ error: Error | null;
47
+ xmlPath?: string;
48
+ }
49
+
50
+ export function SplatCollisionProxyPreview({
51
+ collisionProxy,
52
+ xmlText,
53
+ fetchXml = fetchSplatCollisionProxyXml,
54
+ color = '#60a5fa',
55
+ opacity = 0.12,
56
+ planeColor = '#94a3b8',
57
+ planeOpacity = 0.08,
58
+ children,
59
+ ...groupProps
60
+ }: SplatCollisionProxyPreviewProps) {
61
+ const { geoms } = useSplatCollisionProxyGeoms({
62
+ collisionProxy,
63
+ xmlText,
64
+ fetchXml,
65
+ });
66
+
67
+ if (geoms.length === 0 && !children) return null;
68
+
69
+ return (
70
+ <group
71
+ {...groupProps}
72
+ userData={{
73
+ kind: 'splat-collision-proxy-preview',
74
+ ...groupProps.userData,
75
+ }}
76
+ >
77
+ {geoms.map((geom) => (
78
+ <SplatCollisionProxyGeom
79
+ key={geom.id}
80
+ geom={geom}
81
+ color={color}
82
+ opacity={opacity}
83
+ planeColor={planeColor}
84
+ planeOpacity={planeOpacity}
85
+ />
86
+ ))}
87
+ {children}
88
+ </group>
89
+ );
90
+ }
91
+
92
+ export function useSplatCollisionProxyGeoms({
93
+ collisionProxy,
94
+ xmlText,
95
+ fetchXml = fetchSplatCollisionProxyXml,
96
+ enabled = true,
97
+ }: UseSplatCollisionProxyGeomsOptions): SplatCollisionProxyGeomsState {
98
+ const [loadedXmlText, setLoadedXmlText] = useState<string | null>(null);
99
+ const [status, setStatus] =
100
+ useState<SplatCollisionProxyPreviewStatus>('idle');
101
+ const [error, setError] = useState<Error | null>(null);
102
+ const xmlPath = collisionProxy?.xmlPath;
103
+
104
+ useEffect(() => {
105
+ let cancelled = false;
106
+
107
+ if (!enabled) {
108
+ setLoadedXmlText(null);
109
+ setStatus('idle');
110
+ setError(null);
111
+ return undefined;
112
+ }
113
+
114
+ if (xmlText) {
115
+ setLoadedXmlText(xmlText);
116
+ setStatus('ready');
117
+ setError(null);
118
+ return undefined;
119
+ }
120
+
121
+ if (!xmlPath || !canFetchSplatCollisionProxyXml(xmlPath)) {
122
+ setLoadedXmlText(null);
123
+ setStatus('idle');
124
+ setError(null);
125
+ return undefined;
126
+ }
127
+ const fetchPath = xmlPath;
128
+
129
+ async function loadProxyXml() {
130
+ setStatus('loading');
131
+ setError(null);
132
+
133
+ try {
134
+ const nextXmlText = await fetchXml(fetchPath);
135
+ if (!cancelled) {
136
+ setLoadedXmlText(nextXmlText);
137
+ setStatus('ready');
138
+ }
139
+ } catch (nextError) {
140
+ if (!cancelled) {
141
+ setLoadedXmlText(null);
142
+ setStatus('error');
143
+ setError(
144
+ nextError instanceof Error
145
+ ? nextError
146
+ : new Error('Unable to load collision proxy XML.')
147
+ );
148
+ }
149
+ }
150
+ }
151
+
152
+ void loadProxyXml();
153
+
154
+ return () => {
155
+ cancelled = true;
156
+ };
157
+ }, [enabled, fetchXml, xmlPath, xmlText]);
158
+
159
+ const geoms = useMemo(
160
+ () => (loadedXmlText ? parseSplatCollisionProxyGeoms(loadedXmlText) : []),
161
+ [loadedXmlText]
162
+ );
163
+
164
+ return useMemo(
165
+ () => ({
166
+ geoms,
167
+ status,
168
+ error,
169
+ xmlPath,
170
+ }),
171
+ [error, geoms, status, xmlPath]
172
+ );
173
+ }
174
+
175
+ export async function fetchSplatCollisionProxyXml(xmlPath: string) {
176
+ const response = await fetch(xmlPath);
177
+ if (!response.ok) {
178
+ throw new Error(`Unable to load collision proxy XML (${response.status}).`);
179
+ }
180
+ return response.text();
181
+ }
182
+
183
+ export function canFetchSplatCollisionProxyXml(xmlPath: string) {
184
+ return (
185
+ xmlPath.startsWith('/') ||
186
+ xmlPath.startsWith('http://') ||
187
+ xmlPath.startsWith('https://')
188
+ );
189
+ }
190
+
191
+ export function parseSplatCollisionProxyGeoms(
192
+ xmlText: string
193
+ ): SplatCollisionProxyGeomPreview[] {
194
+ const parser = typeof DOMParser === 'undefined' ? null : new DOMParser();
195
+ if (!parser) return [];
196
+
197
+ const document = parser.parseFromString(xmlText, 'application/xml');
198
+ if (document.querySelector('parsererror')) return [];
199
+
200
+ const bodyPositions = new Map<Element, SplatCollisionProxyPreviewVector3>();
201
+
202
+ for (const body of Array.from(document.querySelectorAll('body'))) {
203
+ const parentBody = body.parentElement?.closest('body');
204
+ const parentPosition: SplatCollisionProxyPreviewVector3 = parentBody
205
+ ? bodyPositions.get(parentBody) ?? [0, 0, 0]
206
+ : [0, 0, 0];
207
+ bodyPositions.set(
208
+ body,
209
+ addProxyVectors(parentPosition, parseProxyVector(body.getAttribute('pos')))
210
+ );
211
+ }
212
+
213
+ return Array.from(document.querySelectorAll('geom'))
214
+ .map((geom, index): SplatCollisionProxyGeomPreview | null => {
215
+ const type = getCollisionProxyGeomType(geom);
216
+ if (!type) return null;
217
+ const parentBody = geom.closest('body');
218
+ const bodyPosition: SplatCollisionProxyPreviewVector3 = parentBody
219
+ ? bodyPositions.get(parentBody) ?? [0, 0, 0]
220
+ : [0, 0, 0];
221
+ const position = addProxyVectors(
222
+ bodyPosition,
223
+ parseProxyVector(geom.getAttribute('pos'))
224
+ );
225
+ const size = parseNumberList(geom.getAttribute('size'));
226
+ return {
227
+ id: geom.getAttribute('name') ?? `${type}-${index}`,
228
+ type,
229
+ position,
230
+ size,
231
+ };
232
+ })
233
+ .filter((geom): geom is SplatCollisionProxyGeomPreview => Boolean(geom));
234
+ }
235
+
236
+ function SplatCollisionProxyGeom({
237
+ geom,
238
+ color,
239
+ opacity,
240
+ planeColor,
241
+ planeOpacity,
242
+ }: {
243
+ geom: SplatCollisionProxyGeomPreview;
244
+ color: string;
245
+ opacity: number;
246
+ planeColor: string;
247
+ planeOpacity: number;
248
+ }) {
249
+ if (geom.type === 'sphere') {
250
+ return (
251
+ <mesh position={geom.position}>
252
+ <sphereGeometry args={[geom.size[0] ?? 0.1, 16, 8]} />
253
+ <SplatCollisionProxyMaterial color={color} opacity={opacity} />
254
+ </mesh>
255
+ );
256
+ }
257
+
258
+ if (geom.type === 'plane') {
259
+ const width = geom.size[0] && geom.size[0] > 0 ? geom.size[0] * 2 : 4;
260
+ const height = geom.size[1] && geom.size[1] > 0 ? geom.size[1] * 2 : 4;
261
+ return (
262
+ <mesh position={geom.position}>
263
+ <boxGeometry args={[width, height, 0.02]} />
264
+ <SplatCollisionProxyMaterial color={planeColor} opacity={planeOpacity} />
265
+ </mesh>
266
+ );
267
+ }
268
+
269
+ const size = getCollisionProxyBoxSize(geom);
270
+ return (
271
+ <mesh position={geom.position}>
272
+ <boxGeometry args={size} />
273
+ <SplatCollisionProxyMaterial color={color} opacity={opacity} />
274
+ </mesh>
275
+ );
276
+ }
277
+
278
+ function SplatCollisionProxyMaterial({
279
+ color,
280
+ opacity,
281
+ }: {
282
+ color: string;
283
+ opacity: number;
284
+ }) {
285
+ return (
286
+ <meshBasicMaterial
287
+ color={color}
288
+ transparent
289
+ opacity={opacity}
290
+ wireframe
291
+ />
292
+ );
293
+ }
294
+
295
+ function getCollisionProxyGeomType(
296
+ geom: Element
297
+ ): SplatCollisionProxyGeomPreview['type'] | null {
298
+ const type = geom.getAttribute('type') ?? 'sphere';
299
+ if (
300
+ type === 'box' ||
301
+ type === 'plane' ||
302
+ type === 'sphere' ||
303
+ type === 'capsule' ||
304
+ type === 'mesh'
305
+ ) {
306
+ return type;
307
+ }
308
+ return null;
309
+ }
310
+
311
+ function getCollisionProxyBoxSize(
312
+ geom: SplatCollisionProxyGeomPreview
313
+ ): SplatCollisionProxyPreviewVector3 {
314
+ if (geom.type === 'capsule') {
315
+ const radius = geom.size[0] ?? 0.05;
316
+ const halfLength = geom.size[1] ?? radius;
317
+ return [radius * 2, radius * 2, Math.max(radius * 2, halfLength * 2)];
318
+ }
319
+
320
+ if (geom.type === 'mesh') return [0.2, 0.2, 0.2];
321
+
322
+ return [
323
+ (geom.size[0] ?? 0.1) * 2,
324
+ (geom.size[1] ?? geom.size[0] ?? 0.1) * 2,
325
+ (geom.size[2] ?? geom.size[0] ?? 0.1) * 2,
326
+ ];
327
+ }
328
+
329
+ function parseProxyVector(
330
+ value: string | null
331
+ ): SplatCollisionProxyPreviewVector3 {
332
+ const values = parseNumberList(value);
333
+ return [values[0] ?? 0, values[1] ?? 0, values[2] ?? 0];
334
+ }
335
+
336
+ function parseNumberList(value: string | null) {
337
+ if (!value) return [];
338
+ return value
339
+ .trim()
340
+ .split(/\s+/)
341
+ .map((part) => Number(part))
342
+ .filter((part) => Number.isFinite(part));
343
+ }
344
+
345
+ function addProxyVectors(
346
+ a: SplatCollisionProxyPreviewVector3,
347
+ b: SplatCollisionProxyPreviewVector3
348
+ ): SplatCollisionProxyPreviewVector3 {
349
+ return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
350
+ }