diff --git a/Scripts/build_and_test.ps1 b/Scripts/build_and_test.ps1 index b986829..d2d139f 100644 --- a/Scripts/build_and_test.ps1 +++ b/Scripts/build_and_test.ps1 @@ -66,6 +66,23 @@ $cmd = Join-Path $Engine 'Engine\Binaries\Win64\UnrealEditor-Cmd.exe' if (-not (Test-Path $bat)) { Write-Error "Build.bat not found: $bat"; exit 3 } if (-not (Test-Path $cmd)) { Write-Error "UnrealEditor-Cmd not found: $cmd"; exit 3 } +# --- Codegen drift gate ---------------------------------------------------- +# Refuse to build if codegen output drifted from the committed Source/, or +# if any drift diagnostic (--strict) fires, or if the clang-AST introspect +# snapshot is missing (--require-introspect). Skipped silently when Python +# isn't on PATH — the gate is best-effort locally; CI enforces it strictly. +$pluginRoot = Split-Path -Parent $PSScriptRoot +$generator = Join-Path $pluginRoot 'Scripts/codegen/generate_ue_components.py' +$py = (Get-Command python -ErrorAction SilentlyContinue) +if ($py -and (Test-Path $generator)) { + Write-Host '>>> Codegen drift gate: python generate_ue_components.py --check --strict --require-introspect' + & $py.Source $generator --check --strict --require-introspect + if ($LASTEXITCODE -ne 0) { + Write-Error "Codegen drift detected (exit $LASTEXITCODE). Re-run 'python Scripts/codegen/generate_ue_components.py' to regenerate, then re-run this script." + exit 4 + } +} + # Truncate the test log up-front so a build failure (or any early exit # before UnrealEditor-Cmd writes to it) doesn't leave the SHA-256 in the # summary pointing at a previous run's file. diff --git a/Scripts/codegen/_codegen_checks.py b/Scripts/codegen/_codegen_checks.py new file mode 100644 index 0000000..9dbf13b --- /dev/null +++ b/Scripts/codegen/_codegen_checks.py @@ -0,0 +1,930 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""URLab codegen — drift checks. + +Every ``_check_*`` function that scans rules + snapshots for drift +lives here. The orchestrator imports the dispatcher functions +(``_emit_drift_diagnostics``, ``_check_*``) and wires them into +``_phase_diagnostics``. + +Dependencies are strictly downward: imports from ``_codegen_core`` +only. No emit logic, no .cpp injection — drift checks read the +rules + snapshots and route diagnostics through ``_diag_add``. +""" + +from __future__ import annotations + +import os +import re +from typing import Any, Dict, List, Optional, Sequence, Set, Tuple + +from _codegen_core import ( + _diag_add, + _UE_TYPE_INFO, _UE_TYPE_FAMILY, _ue_type_accepts_units_meta, _KNOWN_UE_UNITS, + _classify_c_type, _shapes_compatible, _VEC3_CONVERT_FMT, + schema_attrs, schema_subtype_attrs, + compute_canon_absorbed, + _resolve_mjs_field, _resolve_value_map, _value_map_pair, +) + + +# --------------------------------------------------------------------------- +# Hand-enum scrape (regex fallback when the libclang scrape didn't run) +# --------------------------------------------------------------------------- + +_HAND_ENUM_RE = re.compile( + r"enum\s+class\s+(EMj\w+)\s*:\s*uint8\s*\{([^}]*)\}", + re.DOTALL, +) +_HAND_ENUM_MEMBER_RE = re.compile(r"\A\s*(\w+)") + + +def _scan_hand_enums(public_root: str) -> Dict[str, List[str]]: + """Walk ``public_root`` for every ``.h`` file declaring + ``enum class EMj* : uint8 { ... }`` and return + ``{enum_name: [members]}``. Members are stripped of inline + initialisers, UMETA macros, and comments.""" + out: Dict[str, List[str]] = {} + for root, _dirs, files in os.walk(public_root): + for name in files: + if not name.endswith(".h"): + continue + with open(os.path.join(root, name), "r", encoding="utf-8") as f: + text = f.read() + for m in _HAND_ENUM_RE.finditer(text): + enum_name = m.group(1) + body = m.group(2) + body = re.sub(r"UMETA\([^)]*\)", "", body) + body = re.sub(r"//[^\n]*", "", body) + body = re.sub(r"/\*.*?\*/", "", body, flags=re.DOTALL) + members: List[str] = [] + for line in body.split(","): + mm = _HAND_ENUM_MEMBER_RE.match(line) + if mm: + members.append(mm.group(1)) + if members: + out[enum_name] = members + return out + + +def _hand_enums_from_snapshot(mjspec: Optional[Dict[str, Any]]) -> Dict[str, List[str]]: + """Pull URLab's hand-rolled ``EMj*`` enums out of the merged + introspect snapshot when present. Snapshot path produces real + ENUM_CONSTANT_DECL members from libclang. Regex fallback covers + the local-dev case where the snapshot wasn't regenerated.""" + if not mjspec: + return {} + introspect = mjspec.get("introspect", {}) or {} + hand_enums = introspect.get("hand_enums") or {} + out: Dict[str, List[str]] = {} + for name, entry in hand_enums.items(): + if not isinstance(entry, dict): + continue + members = entry.get("members", {}) + if isinstance(members, dict): + out[name] = list(members.keys()) + return out + + +# --------------------------------------------------------------------------- +# Drift checks +# --------------------------------------------------------------------------- + + +def _check_hand_enum_drift( + schema: Dict[str, Any], + rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], + public_root: str, +) -> None: + """Cross-check rule-declared UE enum members against the actual + hand enums AND against MuJoCo's mjt* enums.""" + hand_enums = _hand_enums_from_snapshot(mjspec) + if not hand_enums: + hand_enums = _scan_hand_enums(public_root) + if not hand_enums: + return + + for cat_name, cat_rules in rules.get("categories", {}).items(): + type_enum = cat_rules.get("type_enum_name") + if not type_enum or type_enum not in hand_enums: + continue + members = set(hand_enums[type_enum]) + for sub in cat_rules.get("subtypes", []): + ev = sub.get("enum_value") + if ev and ev not in members: + _diag_add( + f"[diagnostic] category '{cat_name}' subtype '{sub.get('key')}' " + f"references enum_value '{type_enum}::{ev}' that does not " + f"exist in {type_enum} members {sorted(members)}.", + source="hand_enum_drift", + ) + + element_rules = rules.get("element_rules", {}) + mjspec_enums = (mjspec or {}).get("enums", {}) + intentional_skips = rules.get("intentionally_unmapped_mj_enum_values", {}) + for elem, elem_rules in element_rules.items(): + for attr, enum_def in elem_rules.get("xml_enum_attrs", {}).items(): + ue_enum_type = enum_def.get("ue_enum_type") or enum_def.get("ue_enum") + value_map = enum_def.get("value_map", {}) + if not ue_enum_type or ue_enum_type not in hand_enums: + continue + members = set(hand_enums[ue_enum_type]) + for xml_val, mapping in value_map.items(): + pair = _value_map_pair(mapping) + if pair is None: + continue + ue_member, _ = pair + if ue_member not in members: + _diag_add( + f"[diagnostic] element '{elem}' xml_enum '{attr}' " + f"value_map entry '{xml_val}' maps to " + f"'{ue_enum_type}::{ue_member}' that does not exist " + f"in members {sorted(members)}.", + source="hand_enum_drift", + ) + from_mj_enum = enum_def.get("from_mj_enum") + if not from_mj_enum: + mjs_cast = enum_def.get("mjs_cast", "") + if mjs_cast.startswith("mjt"): + from_mj_enum = mjs_cast + if from_mj_enum and from_mj_enum in mjspec_enums: + mj_values = mjspec_enums[from_mj_enum] + covered_mj: set = set() + for mapping in value_map.values(): + pair = _value_map_pair(mapping) + if pair is not None: + covered_mj.add(pair[1]) + skips = set(intentional_skips.get(from_mj_enum, [])) + per_elem = intentional_skips.get("__per_element__", {}) + skips |= set(per_elem.get(f"{elem}.{attr}", [])) + for mj_const in mj_values: + if mj_const in covered_mj or mj_const in skips: + continue + _diag_add( + f"[diagnostic] {from_mj_enum}::{mj_const} (from " + f"mjspec snapshot) has no mapping in element " + f"'{elem}' xml_enum_attrs.{attr}.value_map; new " + f"MuJoCo enum values silently fall through to the " + f"default branch at runtime. Add a value_map entry " + f"or list under 'intentionally_unmapped_mj_enum_values" + f".{from_mj_enum}'.", + source="hand_enum_drift", + ) + + +def _check_type_shape_drift( + schema: Dict[str, Any], + rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], +) -> None: + """Cross-check ``type_mappings[attr]`` against the actual C-type + shape of the corresponding mjs struct field.""" + if not mjspec: + return + struct_table = (mjspec.get("introspect") or {}).get("structs", {}) + if not struct_table: + return + type_map = rules.get("type_mappings", {}) + unmodeled_mjs = rules.get("intentionally_unmodeled_mjs_fields", {}) + element_rules = rules.get("element_rules", {}) + for cat_name, cat_rules in rules.get("categories", {}).items(): + mjs_struct = cat_rules.get("mjs_struct") + if not mjs_struct or mjs_struct not in struct_table: + continue + fields = { + f["name"]: (f.get("c_type", ""), f.get("array_dim")) + for f in struct_table[mjs_struct].get("fields", []) + } + skip_fields = set(unmodeled_mjs.get(mjs_struct, [])) + skip_fields |= set(element_rules.get(cat_name, {}).get("exclude_attrs", [])) + for attr, ue_type in type_map.items(): + if attr not in fields or attr in skip_fields: + continue + ue_shape = _UE_TYPE_FAMILY.get(ue_type) + if not ue_shape: + continue + c_type, array_dim = fields[attr] + c_shape = _classify_c_type(c_type, array_dim) + if c_shape is None or c_shape[0] == "opaque": + continue + if not _shapes_compatible(ue_shape, c_shape): + _diag_add( + f"[diagnostic] type_mappings['{attr}'] = '{ue_type}' " + f"(category '{cat_name}') but {mjs_struct}.{attr} is " + f"'{c_type}' (shape={c_shape}); rule expects " + f"shape={ue_shape}. UE/C shape mismatch — emitted " + f"code may overflow, truncate, or fail to compile.", + source="type_shape_drift", + ) + + +def _check_new_attr_typing( + schema: Dict[str, Any], + rules: Dict[str, Any], +) -> None: + """Every schema attr that lands as a UPROPERTY but has no explicit + type_mappings entry silently inherits ``default_type`` ('float'). + Also surfaces type_mappings entries whose UE type does not resolve + to a known shape — the codegen would otherwise fall back to a + default emit and hide the typo (e.g. ``TArray``).""" + type_map = rules.get("type_mappings", {}) + default_type = rules.get("default_type", "float") + global_excl = set(rules.get("global_exclusions", [])) + intentional_float = set(rules.get("intentionally_default_typed_attrs", [])) + element_rules = rules.get("element_rules", {}) + canonicalizations = rules.get("canonicalizations", {}) + + def _ue_type_known(ue_type: str) -> bool: + if ue_type in _UE_TYPE_INFO: + return True + if ue_type.startswith("EMj"): + return True + if ue_type.startswith("TArray<") and ue_type.endswith(">"): + inner = ue_type[len("TArray<"):-1] + return inner in _UE_TYPE_INFO or inner.startswith("EMj") or inner.startswith("U") + return False + + bad_typed: set = set() + for attr, ue_type in type_map.items(): + if attr.startswith("_"): + continue + if not _ue_type_known(ue_type): + bad_typed.add(attr) + _diag_add( + f"[diagnostic] type_mappings['{attr}'] = '{ue_type}' is " + f"not a recognised UE type. The codegen will fall back " + f"to default_type ('{default_type}') for downstream " + f"emits, hiding the typo. Fix the type or add the entry " + f"to _UE_TYPE_INFO.", + source="new_attr_typing", + ) + + def _collect_attrs(cat_rules: Dict[str, Any]) -> set: + out: set = set(schema_attrs(schema, cat_rules.get("schema_common_block", ""))) + out |= set(cat_rules.get("schema_common_extra_attrs", [])) + sub_block = cat_rules.get("schema_subtypes_block") + if sub_block and sub_block in schema: + block = schema[sub_block] + if isinstance(block, dict): + for sub_attrs in block.values(): + if isinstance(sub_attrs, list): + out |= set(sub_attrs) + elif isinstance(sub_attrs, dict): + out |= set(sub_attrs.get("attrs", [])) + elif isinstance(block, list): + for entry in block: + if isinstance(entry, dict): + out |= set(entry.get("attrs", [])) + return out + + flagged: set = set() + for cat_name, cat_rules in rules.get("categories", {}).items(): + elem_rules = element_rules.get(cat_name, {}) + elem_excl = set(elem_rules.get("exclude_attrs", [])) + xml_enum_attrs = set(elem_rules.get("xml_enum_attrs", {}).keys()) + renames = set(elem_rules.get("property_renames", {}).keys()) + collations = set(elem_rules.get("target_collations", {}).keys()) + export_skip = set(elem_rules.get("export_skip_attrs", [])) + common_imports = set() + for entry in elem_rules.get("common_imports", []): + if isinstance(entry, str): + common_imports.add(entry) + elif isinstance(entry, dict): + common_imports.add(entry.get("attr")) + canon_absorbed: set = compute_canon_absorbed( + elem_rules.get("applies_canonicalizations", []), + canonicalizations, + ) + for attr in _collect_attrs(cat_rules): + if attr in global_excl or attr in elem_excl: + continue + if attr in xml_enum_attrs or attr in renames or attr in collations: + continue + if attr in canon_absorbed or attr in export_skip or attr in common_imports: + continue + if attr in type_map: + continue + if attr in flagged or attr in intentional_float: + continue + flagged.add(attr) + _diag_add( + f"[diagnostic] attr '{attr}' (used by {cat_name}) has no " + f"type_mappings entry and would fall back to default_type " + f"('{default_type}'). Pin its UE type in type_mappings, or " + f"list it under 'intentionally_default_typed_attrs' to " + f"acknowledge the fallback.", + source="new_attr_typing", + ) + + +_ATTR_NAME_RE = re.compile(r"^[a-z_][a-z0-9_]*$") + + +def _all_schema_attrs(schema: Dict[str, Any], rules: Dict[str, Any]) -> set: + """Union of every schema attr observed anywhere in the snapshot.""" + out: set = set() + + def _walk(node: Any) -> None: + if isinstance(node, list): + for item in node: + if isinstance(item, str) and _ATTR_NAME_RE.match(item): + out.add(item) + else: + _walk(item) + elif isinstance(node, dict): + for k, v in node.items(): + if k in ("obj_attr", "ref_attr") and isinstance(v, str): + if _ATTR_NAME_RE.match(v): + out.add(v) + _walk(v) + + _walk(schema) + for cat_rules in rules.get("categories", {}).values(): + out |= set(cat_rules.get("schema_common_extra_attrs", [])) + return out + + +def _check_orphan_rule_entries( + schema: Dict[str, Any], + rules: Dict[str, Any], +) -> None: + """Diagnose rule entries that reference attrs no schema element + uses. Catches stale rules left over from MuJoCo renaming/removing + an attr.""" + known_attrs = _all_schema_attrs(schema, rules) + if not known_attrs: + return + type_map = rules.get("type_mappings", {}) + for attr in type_map.keys(): + if attr not in known_attrs: + _diag_add( + f"[diagnostic] type_mappings['{attr}'] is set but no " + f"schema element exposes an attr by that name. Dead rule " + f"entry — remove, or check whether MuJoCo renamed/removed " + f"the attr.", + source="orphan_rule", + ) + PER_ELEM_KEYS = ( + "exclude_attrs", + "vec3_convert", + "property_renames", + "property_meta", + "property_defaults", + "export_skip_attrs", + "mjs_data_packed_attrs", + ) + for elem, elem_rules in rules.get("element_rules", {}).items(): + for key in PER_ELEM_KEYS: + block = elem_rules.get(key, {}) + if isinstance(block, dict): + rule_attrs = list(block.keys()) + elif isinstance(block, list): + rule_attrs = [ + a if isinstance(a, str) else a.get("attr") + for a in block + ] + else: + continue + for attr in rule_attrs: + if not attr or attr in known_attrs: + continue + _diag_add( + f"[diagnostic] element_rules['{elem}']['{key}'] " + f"references attr '{attr}', which is not present in " + f"ANY schema element. Stale rule.", + source="orphan_rule", + ) + + +def _check_mjxmacro_block_coverage( + rules: Dict[str, Any], + mjxmacro: Dict[str, Any], +) -> None: + """Bi-directional check between mjxmacro snapshot blocks and + ``synthetic_categories`` entries. Forward catches new blocks + upstream URLab doesn't model; reverse catches rule entries + pointing at vanished blocks.""" + blocks = mjxmacro.get("struct_fields", {}) + synthetic = rules.get("synthetic_categories", {}) + if not blocks and not synthetic: + return + block_to_rule: Dict[str, str] = {} + for key, entry in synthetic.items(): + if not isinstance(entry, dict): + continue + mb = entry.get("mjxmacro_block") + if mb: + block_to_rule[mb] = key + for block in blocks: + if block not in block_to_rule: + _diag_add( + f"[diagnostic] mjxmacro struct_fields block '{block}' has " + f"no synthetic_categories rule entry; the {len(blocks[block])} " + f"field(s) it declares will not be emitted as a UE struct.", + source="mjxmacro_block_coverage", + ) + for block, rule_key in block_to_rule.items(): + if block not in blocks: + _diag_add( + f"[diagnostic] synthetic_categories '{rule_key}' references " + f"mjxmacro_block '{block}' that does not exist in the current " + f"mjxmacro snapshot — block renamed or removed upstream.", + source="mjxmacro_block_coverage", + ) + + +# Apply-mode values _emit_synth_apply_methods_cpp understands. Anything +# else lands as a silent passthrough to vec3_y_flip / unconditional — +# the diagnostic surfaces typos so a rule author's intent is real. +_VALID_APPLY_MODES = ( + {"unconditional", "guarded", "pos"} + | set(_VEC3_CONVERT_FMT.keys()) + | {f"guarded_{k}" for k in _VEC3_CONVERT_FMT.keys()} + | {"guarded_pos"} +) + + +def _check_apply_mode_validity(rules: Dict[str, Any]) -> None: + """Diagnose ``field_apply_to_spec_mode`` values the codegen would + silently fall back on.""" + synth = rules.get("synthetic_categories", {}) + for cat_name, def_ in synth.items(): + if cat_name.startswith("_") or not isinstance(def_, dict): + continue + modes = def_.get("field_apply_to_spec_mode", {}) + if not isinstance(modes, dict): + continue + for field, mode in modes.items(): + if mode not in _VALID_APPLY_MODES: + _diag_add( + f"[diagnostic] synthetic_categories['{cat_name}']" + f".field_apply_to_spec_mode['{field}'] = '{mode}' " + f"is not a recognised apply mode. Expected one of " + f"{sorted(_VALID_APPLY_MODES)}.", + source="apply_mode", + ) + + +def _check_embedded_cpp_references( + rules: Dict[str, Any], mjspec: Optional[Dict[str, Any]], +) -> None: + """Diagnose rule entries that name a MuJoCo C symbol the mjspec + snapshot doesn't carry.""" + if not mjspec or "enums" not in mjspec: + return + known_consts: Set[str] = set() + for members in mjspec["enums"].values(): + if isinstance(members, dict): + known_consts.update(members.keys()) + if not known_consts: + return + for elem, elem_rules in rules.get("element_rules", {}).items(): + for attr, enum_def in elem_rules.get("xml_enum_attrs", {}).items(): + for xml_val, mapping in enum_def.get("value_map", {}).items(): + pair = _value_map_pair(mapping) + if pair is None: + continue + mj_const = pair[1] + if not isinstance(mj_const, str): + continue + if not mj_const.startswith("mj"): + continue + if mj_const not in known_consts: + _diag_add( + f"[diagnostic] element_rules['{elem}']" + f".xml_enum_attrs['{attr}'].value_map['{xml_val}'][1]" + f" = '{mj_const}' is not present in any mjspec enum. " + f"Likely typo — UE compile would fail with " + f"'undeclared identifier'.", + source="embedded_cpp_refs", + ) + for cat_name, cat_rules in rules.get("categories", {}).items(): + final = cat_rules.get("geom_final_type") + if not final: + continue + fallback = final.get("default_fallback") + if isinstance(fallback, str) and fallback.startswith("mj") and fallback not in known_consts: + _diag_add( + f"[diagnostic] categories['{cat_name}'].geom_final_type" + f".default_fallback = '{fallback}' is not present in any " + f"mjspec enum.", + source="embedded_cpp_refs", + ) + + +def _collect_every_schema_attr(schema: Dict[str, Any]) -> Set[str]: + """Walk the entire schema tree returning every attr name found. + Used by ``_check_allowlist_staleness``.""" + out: Set[str] = set() + + def walk(node: Any) -> None: + if isinstance(node, dict): + for v in node.values(): + if isinstance(v, list) and all(isinstance(s, str) for s in v): + out.update(v) + else: + walk(v) + elif isinstance(node, list): + for entry in node: + walk(entry) + + walk(schema) + return out + + +def _check_allowlist_staleness( + schema: Dict[str, Any], rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], +) -> None: + """Surface allowlist entries the codebase no longer needs. Covers + 4 of the 5 ``intentionally_*`` allowlists; the fifth + (intentionally_unmodeled_compiler_attrs) is policed indirectly via + _check_compiler_attrs_coverage.""" + unmodeled_elems: Dict[str, str] = rules.get("intentionally_unmodeled_elements", {}) + schema_keys = set(schema.keys()) + for key in unmodeled_elems: + if key not in schema_keys: + _diag_add( + f"[diagnostic] intentionally_unmodeled_elements lists '{key}' " + f"but the schema no longer carries that top-level element. " + f"Drop the entry.", + source="allowlist_staleness", + ) + + unmodeled_fields: Dict[str, List[str]] = rules.get("intentionally_unmodeled_mjs_fields", {}) + structs = (mjspec or {}).get("structs", {}) if mjspec else {} + if structs: + for struct, fields in unmodeled_fields.items(): + if struct not in structs: + _diag_add( + f"[diagnostic] intentionally_unmodeled_mjs_fields names " + f"struct '{struct}' that is missing from the current " + f"mjspec snapshot. Drop the entry.", + source="allowlist_staleness", + ) + continue + struct_field_set = set(structs[struct]) + for field in fields or []: + if field not in struct_field_set: + _diag_add( + f"[diagnostic] intentionally_unmodeled_mjs_fields" + f"['{struct}'] lists '{field}' but the field no " + f"longer exists on the mjs struct. Drop the entry.", + source="allowlist_staleness", + ) + + default_typed: List[str] = rules.get("intentionally_default_typed_attrs", []) + every_attr: Set[str] = _collect_every_schema_attr(schema) + for attr in default_typed: + if attr not in every_attr: + _diag_add( + f"[diagnostic] intentionally_default_typed_attrs lists " + f"'{attr}' but no schema element carries that attr. " + f"Drop the entry.", + source="allowlist_staleness", + ) + + unmapped: Dict[str, Any] = rules.get("intentionally_unmapped_mj_enum_values", {}) + mj_enums = (mjspec or {}).get("enums", {}) if mjspec else {} + if mj_enums: + for key in unmapped: + if key.startswith("_") or key == "__per_element__": + continue + if key not in mj_enums: + _diag_add( + f"[diagnostic] intentionally_unmapped_mj_enum_values " + f"names mjt enum '{key}' that is missing from the " + f"current mjspec snapshot. Drop the entry.", + source="allowlist_staleness", + ) + + +def _check_property_units_validity( + rules: Dict[str, Any], +) -> None: + """Diagnose property_units entries that use an unrecognised UE + display unit, or target a UE type that UHT rejects Units meta on.""" + for elem, elem_rules in rules.get("element_rules", {}).items(): + units = elem_rules.get("property_units", {}) + if not isinstance(units, dict): + continue + for attr, unit in units.items(): + if unit not in _KNOWN_UE_UNITS: + _diag_add( + f"[diagnostic] element_rules['{elem}'].property_units" + f"['{attr}'] = '{unit}' is not a UE-recognised display " + f"unit. Use one of {sorted(_KNOWN_UE_UNITS)} or extend " + f"_KNOWN_UE_UNITS in _codegen_core.", + source="property_units", + ) + + +def _check_compiler_attrs_coverage( + schema: Dict[str, Any], + rules: Dict[str, Any], +) -> None: + """Diagnose any attribute the MJCF schema lists that + URLab neither models in FMjCompilerSettings nor explicitly skips.""" + compiler_attrs = schema.get("compiler", {}).get("attrs", []) + if not compiler_attrs: + return + mapped = set(rules.get("compiler_attr_field_map", {}).keys()) + skipped = set(rules.get("intentionally_unmodeled_compiler_attrs", [])) + for attr in compiler_attrs: + if attr in mapped or attr in skipped: + continue + _diag_add( + f"[diagnostic] is in the MJCF schema " + f"but URLab does not handle it. Either add a field to " + f"FMjCompilerSettings + an entry in 'compiler_attr_field_map', " + f"or add to 'intentionally_unmodeled_compiler_attrs' if the " + f"flag has no UE-side effect.", + source="compiler_coverage", + ) + + +def _check_value_map_stale_mj_consts( + rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], +) -> None: + """Every value_map[*][1] is a literal mj* C constant emitted into + the generated .cpp; the snapshot cross-check surfaces removed/ + renamed constants before they break the C++ compile.""" + if not mjspec: + return + enums = mjspec.get("enums", {}) + if not enums: + return + known: set = set() + for members in enums.values(): + if isinstance(members, dict): + known.update(members.keys()) + if not known: + return + for elem, elem_rules in rules.get("element_rules", {}).items(): + for attr, enum_def in elem_rules.get("xml_enum_attrs", {}).items(): + value_map = enum_def.get("value_map", {}) + for xml_val, mapping in value_map.items(): + pair = _value_map_pair(mapping) + if pair is None: + continue + mj_const = pair[1] + if not isinstance(mj_const, str) or not mj_const.startswith("mj"): + continue + if mj_const not in known: + _diag_add( + f"[diagnostic] element '{elem}' xml_enum '{attr}' " + f"value_map entry '{xml_val}' references " + f"'{mj_const}', which is NOT in the mjspec " + f"snapshot's enum members. The generated .cpp " + f"will fail to compile when the MuJoCo headers " + f"update.", + source="value_map_stale", + ) + + +def _check_top_level_elements_coverage( + schema: Dict[str, Any], rules: Dict[str, Any], +) -> None: + """Flag top-level schema elements with no category in rules.""" + categories = rules.get("categories", {}) + known_blocks = {c.get("schema_common_block", "").split(".", 1)[0] + for c in categories.values()} + known_blocks.discard("") + container_keys = { + "_meta", "actuator_common", "actuator_types", "sensor_common", + "sensor_types", "sensor_per_type", "sensor_extras", + "tendon", "equality", "contact", + "asset", "compiler", "option", "keyframe", "default", + } + unmodeled: Dict[str, str] = rules.get("intentionally_unmodeled_elements", {}) + for key in schema: + if key.startswith("_") or key in container_keys or key in known_blocks: + continue + if key in unmodeled: + continue + _diag_add( + f"[diagnostic] schema has top-level element '{key}' but no " + f"category in codegen_rules.json (rules['categories']). " + f"Either add a category entry, list '{key}' in " + f"container_keys, or add an " + f"'intentionally_unmodeled_elements' entry explaining why " + f"it's skipped.", + source="top_level_coverage", + ) + + +def _check_actuator_subtypes_coverage( + schema: Dict[str, Any], rules: Dict[str, Any], +) -> None: + act_cat = rules.get("categories", {}).get("actuator", {}) + known_act_subs = {s.get("key") for s in act_cat.get("subtypes", [])} + for name in schema.get("actuator_types", {}): + if name not in known_act_subs: + _diag_add( + f"[diagnostic] schema actuator subtype '{name}' has no " + f"entry in categories.actuator.subtypes. Add a subtype " + f"+ subtype_setto rule pair so codegen emits the UMj" + f"{name.title()}Actuator class.", + source="actuator_subtypes_coverage", + ) + + +def _check_sensor_subtypes_coverage( + schema: Dict[str, Any], rules: Dict[str, Any], +) -> None: + sens_cat = rules.get("categories", {}).get("sensor", {}) + known_sens_subs = {s.get("key") for s in sens_cat.get("subtypes", [])} + for name in schema.get("sensor_types", []): + if name not in known_sens_subs: + _diag_add( + f"[diagnostic] schema sensor type '{name}' has no entry " + f"in categories.sensor.subtypes. Add it so the per-sensor " + f"UMjXSensor subclass is emitted.", + source="sensor_subtypes_coverage", + ) + + +def _check_setto_param_coverage( + schema: Dict[str, Any], rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], +) -> None: + """Flag mjs_setTo* parameters with no UE-side mapping AND no + explicit sentinel default.""" + if not mjspec or "setto_functions" not in mjspec: + return + categories = rules.get("categories", {}) + setto_defaults = rules.get("setto_param_defaults", {}) + for cat_name, cat_rules in categories.items(): + setto_block = cat_rules.get("subtype_setto") or {} + common_attrs = set(schema_attrs( + schema, cat_rules.get("schema_common_block", ""))) + for sub_key, setto_def in setto_block.items(): + if not isinstance(setto_def, dict): + continue + fn_name = setto_def.get("call") + if not fn_name or fn_name not in mjspec["setto_functions"]: + continue + sig = mjspec["setto_functions"][fn_name] + renames = setto_def.get("param_renames", {}) + fn_defaults = set(setto_defaults.get(fn_name, {}).keys()) + sub_attrs = set(schema_subtype_attrs(schema, cat_name, sub_key)) + schema_attr_set = common_attrs | sub_attrs + for p in sig.get("params", []): + pname = p["name"] + ue_prop = renames.get(pname, pname) + if ue_prop in schema_attr_set or pname in fn_defaults: + continue + _diag_add( + f"[diagnostic] {fn_name} param '{pname}' is not " + f"in the {cat_name}.{sub_key} schema attrs and " + f"has no param_renames or setto_param_defaults " + f"entry. Codegen passes the generic sentinel for " + f"it. If MuJoCo added this param, decide whether " + f"to expose it as a UE UPROPERTY (schema attr + " + f"type_mapping) or pin its sentinel.", + source="setto_param_coverage", + ) + + +def _check_mjs_struct_field_drift( + schema: Dict[str, Any], rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], +) -> None: + """Flag mjs struct fields with no schema-attr coverage or rule + binding.""" + if not mjspec or "structs" not in mjspec: + return + categories = rules.get("categories", {}) + unmodeled_by_struct: Dict[str, set] = { + struct: set(fields) for struct, fields in + rules.get("intentionally_unmodeled_mjs_fields", {}).items() + } + for cat_name, cat_rules in categories.items(): + mjs_struct = cat_rules.get("mjs_struct") + if not mjs_struct or mjs_struct not in mjspec["structs"]: + continue + block = cat_rules.get("schema_common_block", "") + schema_attrs_set = set(schema_attrs(schema, block)) + for sub in cat_rules.get("subtypes", []): + schema_attrs_set.update( + schema_subtype_attrs(schema, cat_name, sub.get("key", "")) + ) + mjs_field_set = set(mjspec["structs"][mjs_struct]) + elem_rules = rules.get("element_rules", {}).get(cat_name, {}) + attr_to_mjs = elem_rules.get("attr_to_mjs_field", {}) + mapped_fields = set(attr_to_mjs.values()) + for coll_def in elem_rules.get("target_collations", {}).values(): + if isinstance(coll_def, dict) and coll_def.get("mjs_field"): + mapped_fields.add(coll_def["mjs_field"]) + for enum_def in elem_rules.get("xml_enum_attrs", {}).values(): + if isinstance(enum_def, dict) and enum_def.get("mjs_field"): + mapped_fields.add(enum_def["mjs_field"]) + for packed in elem_rules.get("mjs_data_packed_attrs", {}).values(): + if isinstance(packed, dict): + mapped_fields.add(packed.get("target") or "data") + for da in elem_rules.get("mjs_double_vec_attrs", []): + mapped_fields.add(da) + if cat_rules.get("type_enum_name"): + mapped_fields.add("type") + mapped_fields.add("objtype") + for conv_list in elem_rules.get("unit_conversion", {}).values(): + for entry in conv_list if isinstance(conv_list, list) else []: + if isinstance(entry, dict) and entry.get("mjs_field"): + mapped_fields.add(entry["mjs_field"]) + # Canonicalisation name -> set of mjs struct fields its export + # block writes. Lets the drift check treat canon-owned fields as + # covered. Inlined here because this is the only consumer; kept + # in lock-step with the inline canon emitters in + # generate_ue_components (_canon_export_*). + canon_mjs_fields = { + "body_sleep_policy": {"sleep"}, + "actuator_transmission": {"target", "trntype", "slidersite", "refsite"}, + "fromto_decompose": set(), + "orientation": {"quat"}, + "spatial_pose": {"pos"}, + } + for canon in elem_rules.get("applies_canonicalizations", []): + mapped_fields |= canon_mjs_fields.get(canon, set()) + structural = { + "element", "info", "userdata", "user", "name", "classname", + "parent", "frame", "explicitinertial", + } + structural |= unmodeled_by_struct.get(mjs_struct, set()) + structural |= mapped_fields + normalised_schema = {a.replace("_", "").lower() + for a in schema_attrs_set} + for mjs_field in mjs_field_set: + if mjs_field in structural: + continue + candidate = mjs_field.replace("_", "").lower() + if candidate in normalised_schema: + continue + stripped = candidate.replace("name", "") + if stripped in normalised_schema: + continue + if candidate.startswith("act") and ("actuator" + candidate[3:]) in normalised_schema: + continue + _diag_add( + f"[diagnostic] {mjs_struct}.{mjs_field} (in mjspec_snapshot) " + f"has no corresponding schema attr in '{cat_name}'. Either " + f"add a schema canonicalisation, list it under " + f"intentionally_unmodeled_mjs_fields, or accept that codegen " + f"silently skips it.", + source="mjs_field_drift", + ) + + +def _check_generated_enum_coverage( + rules: Dict[str, Any], mjspec: Optional[Dict[str, Any]], +) -> None: + """Flag generated_enums entries that map fewer mj enum members + than the snapshot carries.""" + if not mjspec or "enums" not in mjspec: + return + for gen_name, gen_def in rules.get("generated_enums", {}).items(): + if gen_name.startswith("_") or not isinstance(gen_def, dict): + continue + if gen_def.get("disabled"): + continue + for entry in gen_def.get("enums", []): + if entry.get("disabled"): + continue + mj_enum_name = entry.get("from_mj_enum") + ue_member_from_mj = entry.get("ue_member_from_mj", {}) + exclude = set(entry.get("exclude_mj_members", [])) + if not mj_enum_name: + continue + c_enum = mjspec["enums"].get(mj_enum_name, {}) + if not c_enum: + _diag_add( + f"[diagnostic] generated_enums['{gen_name}'].{entry.get('ue_name')}: " + f"from_mj_enum '{mj_enum_name}' not found in the projected mjspec. " + f"Rebuild the introspect snapshot, or correct the enum name.", + source="enum_drift", + ) + continue + mapped = set(ue_member_from_mj) | exclude + missing = [m for m in c_enum if m not in mapped] + if missing: + _diag_add( + f"[diagnostic] generated_enums['{gen_name}'].{entry.get('ue_name')}: " + f"C enum '{mj_enum_name}' has {len(missing)} member(s) with no UE " + f"mapping: {missing[:5]}{'...' if len(missing) > 5 else ''}. Add to " + f"ue_member_from_mj or exclude_mj_members.", + source="enum_drift", + ) + + +def _emit_drift_diagnostics(schema: Dict[str, Any], rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]]) -> None: + """Run every drift-coverage check. Each helper surfaces one class + of drift. All diagnostics route through the module-level + ``_DIAGS_BUFFER.pending`` collector and flush once at the end of + ``collect_all_writes``.""" + _check_top_level_elements_coverage(schema, rules) + _check_actuator_subtypes_coverage(schema, rules) + _check_sensor_subtypes_coverage(schema, rules) + _check_setto_param_coverage(schema, rules, mjspec) + _check_mjs_struct_field_drift(schema, rules, mjspec) + _check_generated_enum_coverage(rules, mjspec) diff --git a/Scripts/codegen/_codegen_core.py b/Scripts/codegen/_codegen_core.py new file mode 100644 index 0000000..817331b --- /dev/null +++ b/Scripts/codegen/_codegen_core.py @@ -0,0 +1,487 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""URLab codegen — core shared data + helpers. + +Dependency root. Owns: + +- ``DiagBuffer`` — the diagnostics buffer the orchestrator + checks + share. +- ``_UE_TYPE_INFO`` — single source of truth for every UE type + codegen can emit; ``_UE_TYPE_FAMILY`` and + ``_UE_TYPES_ACCEPTING_UNITS_META`` are derived views. +- Naming helpers, schema readers, canon-iteration helpers. +- The 5-strategy ``_resolve_mjs_field`` chain — the bridge between + MJCF attr names and the C struct field names MuJoCo picks. +- ``_resolve_value_map`` — the xml_enum value-map reader. +- ``FileWrite`` — the data class every emitter produces. + +Read-only against rules / schema / snapshot. No file writes, no +UPROPERTY emission, no .cpp injection. ``generate_ue_components`` +and ``_codegen_checks`` both import from here. +""" + +from __future__ import annotations + +import re +import sys +from dataclasses import dataclass +from typing import Any, Dict, Iterable, Iterator, List, Optional, Sequence, Set, Tuple + + +# --------------------------------------------------------------------------- +# Diagnostics +# --------------------------------------------------------------------------- + +@dataclass +class Diagnostic: + """A non-fatal codegen warning. Collected by ``_diag_add`` during a + run and flushed once at the end via ``_diag_flush``.""" + message: str + source: str = "" # short tag for grouping (e.g. "schema_drift") + + +class DiagBuffer: + """Collects codegen diagnostics during a run. ``pending`` is the + queue of unflushed entries; ``fired_count`` survives the flush so + ``main()`` can check whether ``--strict`` should exit non-zero.""" + + def __init__(self) -> None: + self.pending: List[Diagnostic] = [] + self.fired_count: int = 0 + + def add(self, message: str, *, source: str = "") -> None: + self.pending.append(Diagnostic(message=message, source=source)) + + def flush(self) -> None: + """Print collected diagnostics to stderr, advance ``fired_count`` + by the number flushed, and clear the pending list.""" + if not self.pending: + return + print(f"\n--- codegen diagnostics ({len(self.pending)}) ---", + file=sys.stderr) + for d in self.pending: + print(d.message, file=sys.stderr) + print( + "(diagnostics are non-fatal; the codegen has emitted what it " + "can — fix the rules to silence them.)", + file=sys.stderr, + ) + self.fired_count += len(self.pending) + self.pending.clear() + + def reset(self) -> None: + self.pending.clear() + self.fired_count = 0 + + +_DIAGS_BUFFER = DiagBuffer() + + +def _diag_add(message: str, *, source: str = "") -> None: + _DIAGS_BUFFER.add(message, source=source) + + +def _diag_flush() -> None: + _DIAGS_BUFFER.flush() + + +def _reset_diags() -> None: + """Reset the diag buffer between runs so back-to-back invocations + in the same Python process (test runners, integration shells) + don't carry stale state.""" + _DIAGS_BUFFER.reset() + + +# --------------------------------------------------------------------------- +# UE type registry +# --------------------------------------------------------------------------- + +@dataclass(frozen=True) +class _UEType: + """Single source of truth for a UE type codegen can emit. Every per- + type dispatch (default initializer, drift-check shape, UHT Units-meta + gate) reads this row instead of redeclaring the type universe.""" + default_init: str # C++ initializer (e.g. ``"0.0f"``) + shape: Tuple[str, Any] # drift-check shape (see _classify_c_type) + accepts_units_meta: bool # UHT allows Units="..." on this type + + +# Every UE type codegen can target. ``_attr_default_value``, +# ``_UE_TYPE_FAMILY``, and ``_UE_TYPES_ACCEPTING_UNITS_META`` below are +# thin views over this dict. +_UE_TYPE_INFO: Dict[str, _UEType] = { + "float": _UEType("0.0f", ("scalar", "num"), True), + "double": _UEType("0.0", ("scalar", "num"), True), + "int32": _UEType("0", ("scalar", "int"), True), + "uint8": _UEType("0", ("scalar", "int"), True), # synth-mirror only + "bool": _UEType("false", ("scalar", "bool"), False), + "FString": _UEType('TEXT("")', ("scalar", "string"), False), + "FVector": _UEType("FVector::ZeroVector", ("vec", 3), True), + "FQuat": _UEType("FQuat::Identity", ("vec", 4), False), + "FLinearColor": _UEType("FLinearColor::White", ("vec", 4), False), + "TArray": _UEType("{}", ("array", None), False), + "TArray": _UEType("{}", ("array", None), False), +} + + +def _attr_default_value(ue_type: str) -> str: + info = _UE_TYPE_INFO.get(ue_type) + if info is not None: + return info.default_init + # Unknown types fall through to the default-construct literal — same + # for novel TArray<...> entries (e.g. TArray) the registry + # doesn't enumerate. + return "{}" + + +# UE type → shape for ``_check_type_shape_drift``. Derived from +# ``_UE_TYPE_INFO`` so the type universe is declared once. +_UE_TYPE_FAMILY = {k: v.shape for k, v in _UE_TYPE_INFO.items()} + + +_UE_TYPES_ACCEPTING_UNITS_META = { + k for k, v in _UE_TYPE_INFO.items() if v.accepts_units_meta +} + + +def _ue_type_accepts_units_meta(ue_type: str) -> bool: + """UHT enforces 'Units' meta only on numeric scalars + numeric + structs. Returns False for TArray<...>, FString, FLinearColor, + FQuat — codegen silently drops the Units meta for those types so + the build succeeds.""" + info = _UE_TYPE_INFO.get(ue_type) + return bool(info and info.accepts_units_meta) + + +_DYNAMIC_VEC_TYPES = { + "mjFloatVec", "mjDoubleVec", "mjIntVec", "mjStringVec", + "mjFloatVecVec", "mjDoubleVecVec", "mjIntVecVec", +} + + +_KNOWN_UE_UNITS = { + # UE5 numeric units the editor knows how to render + (optionally) + # convert via Display Units preferences. + "m", "cm", "mm", "km", + "rad", "deg", +} + + +@dataclass +class FileWrite: + """One file write the codegen would perform. Collected during the + phase walk; ``apply_writes`` either flushes them to disk, prints + diffs, or returns the count under ``--check``.""" + path: str + content: str + + +def override_toggle_name(prop_name: str) -> str: + """``bOverride_`` is the codegen-emitted toggle field that + gates whether the corresponding UPROPERTY's value gets written + back to the mjs struct.""" + return f"bOverride_{prop_name}" + + +# --------------------------------------------------------------------------- +# Rule-iteration helpers +# --------------------------------------------------------------------------- + + +def iter_canon_absorbed(elem_canons: Iterable[str], + canonicalizations: Dict[str, Any]) -> Iterator[str]: + """Yield every attr absorbed by any canonicalisation in + ``elem_canons``. Skips unknown canon keys silently — diagnostics + for those live in the rule-validity drift checks.""" + if not canonicalizations: + return + for c in elem_canons: + cd = canonicalizations.get(c) + if cd: + yield from cd.get("absorbs_attrs", ()) + + +def compute_canon_absorbed(elem_canons: Iterable[str], + canonicalizations: Dict[str, Any]) -> Set[str]: + return set(iter_canon_absorbed(elem_canons, canonicalizations)) + + +def iter_category_attrs(attrs: Iterable[str], *, + global_excl: Set[str], + elem_excl: Set[str], + canon_absorbed: Set[str], + extra_excl: Optional[Set[str]] = None) -> Iterator[str]: + """Yield attrs that pass the standard codegen exclusion gates plus + any site-specific ``extra_excl`` set the caller assembles + (xml_enum_attrs, target-collation-absorbed, etc — these vary per + emission stage).""" + for attr in attrs: + if attr in global_excl or attr in elem_excl or attr in canon_absorbed: + continue + if extra_excl is not None and attr in extra_excl: + continue + yield attr + + +# --------------------------------------------------------------------------- +# Schema readers +# --------------------------------------------------------------------------- + + +def schema_attrs(schema: Dict[str, Any], path: str) -> List[str]: + """Read an attribute list at a dotted path, e.g. + ``actuator_common.attrs``. Returns [] if missing.""" + cur: Any = schema + for piece in path.split("."): + if isinstance(cur, dict) and piece in cur: + cur = cur[piece] + else: + return [] + if isinstance(cur, list): + if cur and isinstance(cur[0], str): + return list(cur) + attrs: List[str] = [] + for entry in cur: + if isinstance(entry, dict): + if "attrs" in entry and isinstance(entry["attrs"], list): + attrs.extend([str(x) for x in entry["attrs"]]) + else: + for v in entry.values(): + if isinstance(v, list): + attrs.extend([str(x) for x in v]) + seen = set() + out = [] + for a in attrs: + if a not in seen: + seen.add(a) + out.append(a) + return out + if isinstance(cur, dict): + attrs2: List[str] = [] + for v in cur.values(): + if isinstance(v, list): + attrs2.extend([str(x) for x in v if isinstance(x, str)]) + return attrs2 + return [] + + +def schema_subtype_attrs(schema: Dict[str, Any], category: str, + subtype_key: str) -> List[str]: + """Look up per-subtype attrs from schema['actuator_types'][key] / + schema['sensor_types'] (list-of-dict). Returns [] if not found.""" + if category == "actuator": + block = schema.get("actuator_types", {}) + if isinstance(block, dict): + entry = block.get(subtype_key) + if isinstance(entry, list): + return [str(x) for x in entry] + if isinstance(entry, dict) and "attrs" in entry: + return [str(x) for x in entry["attrs"]] + return [] + if category == "sensor": + block = schema.get("sensor_types", []) + if isinstance(block, list): + for entry in block: + if isinstance(entry, dict) and entry.get("name") == subtype_key: + attrs = entry.get("attrs", []) + return [str(x) for x in attrs] if isinstance(attrs, list) else [] + if isinstance(entry, str) and entry == subtype_key: + return [] + return [] + return [] + + +# --------------------------------------------------------------------------- +# C-type classifier (drift-check inputs) +# --------------------------------------------------------------------------- + + +def _classify_c_type(c_type: str, array_dim) -> Optional[tuple]: + """Reduce an introspect c_type + array_dim down to a comparable + (shape, dim_or_family) tuple. Shapes: + ``("scalar", fam)`` — single value, fam ∈ {num,int,bool,string} + ``("vec", N)`` — fixed-size C array of length N + ``("array", None)`` — dynamic-length C vec (mjFloatVec, etc.) + ``("opaque", _)`` — mjsElement* and other spec-internal + pointers URLab never exposes; returning a + distinct tag lets the check skip them + without silently accepting "scalar" + matches. + Returns None for genuinely unknown bases so the check stays quiet + on novel types instead of producing noise. + """ + ct = c_type.strip() + base_no_arr = re.sub(r"\s*\[[^\]]*\]\s*", "", ct).strip() + base_no_ptr = base_no_arr.rstrip(" *").strip() + if base_no_ptr in _DYNAMIC_VEC_TYPES: + return ("array", None) + if base_no_ptr.startswith("mjsElement") or base_no_ptr.endswith("Element"): + return ("opaque", None) + if "*" in ct or "mjString" in ct or "std::string" in ct: + return ("scalar", "string") + is_array = array_dim is not None and array_dim != 1 + base = base_no_arr + fam: Optional[str] = None + if base in ("mjtNum", "float", "double"): + fam = "num" + elif base in ("int", "mjtByte", "unsigned char", "uint8_t", "uchar"): + fam = "int" + elif base in ("bool", "_Bool"): + fam = "bool" + else: + return None + if is_array: + if array_dim in (3, 4): + return ("vec", array_dim) + return ("array", None) + return ("scalar", fam) + + +def _shapes_compatible(ue_shape: tuple, c_shape: tuple) -> bool: + """True when ``ue_shape`` can legitimately back ``c_shape``. + + A ``TArray`` (array) is shape-compatible with a fixed-size C + array (vec) because the codegen writes ``prop.Num()`` elements + into the C array. + Vec-to-vec requires the dim to match exactly. + Scalar↔array always mismatches. Opaque C shapes are skipped.""" + if c_shape[0] == "opaque": + return True + if ue_shape[0] == c_shape[0]: + if ue_shape[0] == "vec": + return ue_shape[1] == c_shape[1] + return True + if ue_shape[0] == "array" and c_shape[0] == "vec": + return True + return False + + +# --------------------------------------------------------------------------- +# Vec3 convert format table +# --------------------------------------------------------------------------- +# +# Maps the per-field ``apply_to_spec_mode`` rule values for FVector +# UPROPERTYs to the per-element write template the synth-struct emitter +# uses. Each entry is a Python format string with two slots: ``{c}`` +# (the destination C-array expression) and ``{ue}`` (the source UE +# FVector expression). + +_VEC3_CONVERT_FMT = { + "pos": "{c}[0] = {ue}.X / 100.0; {c}[1] = -{ue}.Y / 100.0; {c}[2] = {ue}.Z / 100.0;", + "vec3_cm": "{c}[0] = {ue}.X / 100.0; {c}[1] = -{ue}.Y / 100.0; {c}[2] = {ue}.Z / 100.0;", + "vec3_y_flip": "{c}[0] = {ue}.X; {c}[1] = -{ue}.Y; {c}[2] = {ue}.Z;", + "passthrough": "{c}[0] = {ue}.X; {c}[1] = {ue}.Y; {c}[2] = {ue}.Z;", +} + + +# --------------------------------------------------------------------------- +# mjs-field resolver chain (the 5-strategy bridge) +# --------------------------------------------------------------------------- + + +def _resolve_direct(attr: str, mjs_fields: Set[str]) -> Optional[str]: + """``attr`` matches a struct field verbatim (condim -> condim).""" + return attr if attr in mjs_fields else None + + +def _resolve_name_suffix(attr: str, mjs_fields: Set[str]) -> Optional[str]: + """``attr + "name"`` matches (mesh -> meshname). MuJoCo's name- + ref fields uniformly append ``name`` to the schema attr.""" + cand = attr + "name" + return cand if cand in mjs_fields else None + + +def _resolve_root_name_digits(attr: str, mjs_fields: Set[str]) -> Optional[str]: + """```` -> ``name`` (body1 -> + bodyname1).""" + m = re.match(r"^(.*?)(\d+)$", attr) + if not m: + return None + root, digits = m.group(1), m.group(2) + for candidate in (f"{root}name{digits}", f"{root}_name{digits}"): + if candidate in mjs_fields: + return candidate + return None + + +def _resolve_underscore_norm(attr: str, mjs_fields: Set[str]) -> Optional[str]: + """Strip all underscores and look for matching letters + (solreflimit -> solref_limit). Lossy — only used when nothing + cleaner fits.""" + norm = attr.replace("_", "") + for f in mjs_fields: + if f.replace("_", "") == norm: + return f + return None + + +def _resolve_actuator_prefix(attr: str, mjs_fields: Set[str]) -> Optional[str]: + """Schema ``actuator*`` -> mjs ``act*`` (actuatorfrclimited -> + actfrclimited). MuJoCo abbreviates the prefix on its struct + fields even though the XML attr spells it out.""" + if not attr.startswith("actuator"): + return None + cand = "act" + attr[len("actuator"):] + if cand in mjs_fields: + return cand + cand_norm = cand.replace("_", "") + for f in mjs_fields: + if f.replace("_", "") == cand_norm: + return f + return None + + +_MJS_FIELD_RESOLVERS = ( + _resolve_direct, + _resolve_name_suffix, + _resolve_root_name_digits, + _resolve_underscore_norm, + _resolve_actuator_prefix, +) + + +def _resolve_mjs_field(attr: str, mjs_fields: set, + attr_to_mjs_field: Optional[Dict[str, str]] = None) -> str: + """Pick the correct C field name on a category's mjs struct for a + given schema attribute. Per-element ``attr_to_mjs_field`` + overrides apply first; otherwise the ``_MJS_FIELD_RESOLVERS`` + chain captures MuJoCo's own naming conventions in priority order. + Falls back to ``attr`` if nothing matches — the build then + surfaces the mismatch loudly when the export line tries to access + ``Element->attr``.""" + if attr_to_mjs_field and attr in attr_to_mjs_field: + return attr_to_mjs_field[attr] + if not mjs_fields: + return attr + for resolver in _MJS_FIELD_RESOLVERS: + hit = resolver(attr, mjs_fields) + if hit is not None: + return hit + return attr + + +# --------------------------------------------------------------------------- +# xml_enum value-map resolver +# --------------------------------------------------------------------------- + + +def _resolve_value_map(attr: str, enum_def: Dict[str, Any]) -> Dict[str, Sequence[str]]: + """Return the ``{xml_val -> [UE_enum_member, mj_const]}`` table for + an xml_enum attr. The rule must carry an explicit ``value_map``.""" + if "value_map" in enum_def: + return enum_def["value_map"] + raise RuntimeError(f"xml_enum {attr}: rule is missing value_map") + + +def _value_map_pair(mapping: Any) -> Optional[Tuple[str, str]]: + """Unpack a ``value_map`` entry into ``(ue_member, mj_const)`` or + return None when the shape is malformed. The 4 check sites that + used to inline ``isinstance(mapping, (list, tuple)) and len(mapping) + >= 2`` route through here so one shape contract covers all of + them. The corresponding emit-side path raises (see + ``_emit_xml_enum_export``) — the rule shape contract test + (test_rule_shape_contract.py::test_xml_enum_attr_value_maps_have_ + correct_shape) is the canonical gate; this helper is the + runtime fallback for the drift checks.""" + if not isinstance(mapping, (list, tuple)) or len(mapping) < 2: + return None + return mapping[0], mapping[1] diff --git a/Scripts/codegen/_codegen_inject.py b/Scripts/codegen/_codegen_inject.py new file mode 100644 index 0000000..f11d70d --- /dev/null +++ b/Scripts/codegen/_codegen_inject.py @@ -0,0 +1,196 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""URLab codegen — text-injection machinery. + +Pure text operations: locate ``// --- CODEGEN__START/END ---`` +marker pairs in a source file, splice a body between them, and emit +diagnostics when the body has unbalanced braces or the markers are +missing. + +The brace-aware helpers (``_find_matching_brace``, +``_strip_cpp_braces_in_strings``, ``_check_brace_balance``) live +here too because the banner-overwrite audit + the brace-balance +gate both consume them.""" + +from __future__ import annotations + +import os +import re +from typing import Dict, List, Optional, Sequence, Tuple + +from _codegen_core import _diag_add, FileWrite + + +def _make_tag_pair(tag: str) -> Tuple[str, str]: + return (f"// --- CODEGEN_{tag}_START ---", f"// --- CODEGEN_{tag}_END ---") + + +def _strip_cpp_braces_in_strings(text: str) -> str: + """Remove characters that look like braces but live inside a + string/char literal or comment. Used by ``_check_brace_balance`` + so a diagnostic message containing ``"{"`` doesn't trip the + balance gate.""" + text = re.sub(r"//[^\n]*", "", text) + text = re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL) + text = re.sub(r'"(?:\\.|[^"\\])*"', '""', text) + text = re.sub(r"'(?:\\.|[^'\\])*'", "''", text) + return text + + +def _find_matching_brace(text: str, open_idx: int) -> Optional[int]: + """Return the index of the ``}`` matching the ``{`` at + ``open_idx``. Tracks brace depth across string/char literals and + line/block comments so a nested ``{`` inside a TEXT(...) literal + doesn't shift the balance. Returns None on EOF / unmatched.""" + if open_idx < 0 or open_idx >= len(text) or text[open_idx] != "{": + return None + depth = 1 + i = open_idx + 1 + in_str: Optional[str] = None + while i < len(text) and depth > 0: + ch = text[i] + if in_str is not None: + if ch == "\\" and i + 1 < len(text): + i += 2 + continue + if ch == in_str: + in_str = None + i += 1 + continue + if ch == "/" and i + 1 < len(text) and text[i + 1] == "/": + nl = text.find("\n", i) + i = nl if nl != -1 else len(text) + continue + if ch == "/" and i + 1 < len(text) and text[i + 1] == "*": + end = text.find("*/", i + 2) + i = end + 2 if end != -1 else len(text) + continue + if ch in ('"', "'"): + in_str = ch + elif ch == "{": + depth += 1 + elif ch == "}": + depth -= 1 + if depth == 0: + return i + i += 1 + return None + + +def _check_brace_balance(body: str, tag: str, source: str) -> None: + """Emit a diagnostic when an injected block has an obvious brace + imbalance.""" + stripped = _strip_cpp_braces_in_strings(body) + opens = stripped.count("{") + closes = stripped.count("}") + if opens != closes: + _diag_add( + f"[diagnostic] {source}: injected block for tag " + f"CODEGEN_{tag} has unbalanced braces (open={opens}, " + f"close={closes}). The generated .cpp will not compile.", + source=source, + ) + + +_TAG_PATTERN_CACHE: Dict[str, "re.Pattern[str]"] = {} + + +def _tag_pattern(tag: str) -> "re.Pattern[str]": + pat = _TAG_PATTERN_CACHE.get(tag) + if pat is None: + start, end = _make_tag_pair(tag) + pat = re.compile( + r"([ \t]*)(" + re.escape(start) + r")(.*?)([ \t]*)(" + re.escape(end) + r")", + re.DOTALL, + ) + _TAG_PATTERN_CACHE[tag] = pat + return pat + + +def inject_between_tags(file_text: str, tag: str, new_inner: str, + *, balance_source: Optional[str] = None) -> Tuple[str, bool]: + """Replace the content between ``// --- CODEGEN__START ---`` + and ``// --- CODEGEN__END ---`` with ``new_inner``. Returns + (new_text, was_found). + + The END marker's leading whitespace is rewritten to match the + START marker's indent. When ``new_inner`` is empty or + whitespace-only the block collapses so START + END sit on + adjacent lines with no stray blank line between them. + + When ``balance_source`` is set, emit a diagnostic if the injected + block has unbalanced braces.""" + pattern = _tag_pattern(tag) + matched = [False] + + def repl(m: re.Match) -> str: + matched[0] = True + start_indent = m.group(1) + trimmed = new_inner.rstrip() + if trimmed: + body = "\n" + trimmed + "\n" + start_indent + else: + # Empty body: collapse to one newline so START + END sit + # adjacent (no stray blank line between them). + body = "\n" + start_indent + return m.group(1) + m.group(2) + body + m.group(5) + + new_text = pattern.sub(repl, file_text) + if matched[0] and balance_source: + _check_brace_balance(new_inner, tag, balance_source) + return new_text, matched[0] + + +def _inject_tags_into_cpp( + cpp_path: str, + tagged_bodies: Sequence[Tuple[str, str]], + writes: List[FileWrite], + *, + diag_source: str, +) -> None: + """Open ``cpp_path`` once, inject every (tag, body) pair, surface + a diagnostic for each missing marker pair, append (or update) a + single FileWrite if any tag actually changed the text. + + Phase ordering: earlier phases (e.g. ``_phase_categories``) may have + queued a FileWrite for the same path. Reading from disk in that case + would be stale — the later phase would inject into the PRE-cleanup + text and the post-cleanup IMPORT/EXPORT block would be lost on + apply. Use the pending write's content when present, and replace + it in-place so duplicate FileWrites for the same path don't show + up in ``apply_writes``.""" + pending_idx: Optional[int] = None + for i in range(len(writes) - 1, -1, -1): + if writes[i].path == cpp_path: + pending_idx = i + break + + if pending_idx is not None: + text = writes[pending_idx].content + elif os.path.exists(cpp_path): + with open(cpp_path, "r", encoding="utf-8") as f: + text = f.read() + else: + _diag_add( + f"[diagnostic] {diag_source}: host .cpp '{cpp_path}' does " + f"not exist; no blocks injected.", + source=diag_source, + ) + return + + new_text = text + for tag, body in tagged_bodies: + new_text, ok = inject_between_tags( + new_text, tag, body, balance_source=diag_source, + ) + if not ok: + _diag_add( + f"[diagnostic] {diag_source}: '{cpp_path}' is missing " + f"the CODEGEN_{tag}_START/END marker pair.", + source=diag_source, + ) + if new_text == text: + return + if pending_idx is not None: + writes[pending_idx] = FileWrite(path=cpp_path, content=new_text) + else: + writes.append(FileWrite(path=cpp_path, content=new_text)) diff --git a/Scripts/codegen/_vendored/_VENDORED_FROM.md b/Scripts/codegen/_vendored/_VENDORED_FROM.md new file mode 100644 index 0000000..e24f132 --- /dev/null +++ b/Scripts/codegen/_vendored/_VENDORED_FROM.md @@ -0,0 +1,17 @@ +# Vendored sources + +`sync_vendored.py` reads this manifest and rewrites it deterministically +on every run (stable column order, sorted by `local_dest`). Re-running on +the same upstream SHA produces zero diff — keeps the manifest out of +merge-conflict territory. + +To bump a vendored file, edit its `upstream_sha` (or replace with `main` +for an unpinned re-fetch), then run: + +``` +python Scripts/codegen/sync_vendored.py +``` + +| file | upstream_url | upstream_sha | retrieved_date | license | local_dest | +| ---- | ------------ | ------------ | -------------- | ------- | ---------- | +| mjspecmacro.h | https://raw.githubusercontent.com/google-deepmind/mujoco/{sha}/include/mujoco/mjspecmacro.h | main | 2026-05-29 | Apache-2.0 | Scripts/codegen/_vendored/mjspecmacro.h | diff --git a/Scripts/codegen/_vendored/__init__.py b/Scripts/codegen/_vendored/__init__.py new file mode 100644 index 0000000..388c395 --- /dev/null +++ b/Scripts/codegen/_vendored/__init__.py @@ -0,0 +1,12 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Vendored third-party source files needed by URLab codegen. + +Files here are auto-fetched by ``Scripts/codegen/sync_vendored.py`` from +the URLs listed in ``_VENDORED_FROM.md``. Edit those source URLs / SHAs +in the manifest; the script downloads + writes them verbatim. + +DO NOT edit the .h / .cc files in this directory by hand — they get +clobbered on the next ``sync_vendored.py`` run. URLab-side changes go +in the codegen modules that consume them. +""" diff --git a/Scripts/codegen/_vendored/ast_nodes.py b/Scripts/codegen/_vendored/ast_nodes.py new file mode 100644 index 0000000..f85cc9a --- /dev/null +++ b/Scripts/codegen/_vendored/ast_nodes.py @@ -0,0 +1,154 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Lightweight AST-node dataclasses used by ``build_introspect_snapshot.py`` +to project clang.cindex AST cursors into a serialisable shape. + +URLab-side rather than pulled from upstream because (a) the upstream +``clang.cindex`` types don't pickle cleanly across libclang versions and +(b) the snapshot only needs a small subset of node info. Keeping the +projection in one place means the schema is auditable from JSON, and +test fixtures can be hand-built without needing a real libclang install. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field, asdict +from typing import Any, Dict, List, Optional + + +@dataclass +class CFunctionParam: + name: str + c_type: str + array_dim: Optional[int] = None # None for scalar / pointer + + def to_dict(self) -> Dict[str, Any]: + return asdict(self) + + +@dataclass +class CFunction: + name: str + return_type: str + params: List[CFunctionParam] = field(default_factory=list) + doc: str = "" + file: str = "" # source path + line: int = 0 + + def to_dict(self) -> Dict[str, Any]: + return { + "name": self.name, + "return_type": self.return_type, + "params": [p.to_dict() for p in self.params], + "doc": self.doc, + "file": self.file, + "line": self.line, + } + + +@dataclass +class CEnumMember: + name: str + value: int + doc: str = "" + + +@dataclass +class CEnum: + name: str + members: List[CEnumMember] = field(default_factory=list) + underlying_type: Optional[str] = None + doc: str = "" + file: str = "" + line: int = 0 + + def to_dict(self) -> Dict[str, Any]: + return { + "name": self.name, + "members": {m.name: m.value for m in self.members}, + "member_docs": {m.name: m.doc for m in self.members if m.doc}, + "underlying_type": self.underlying_type, + "doc": self.doc, + "file": self.file, + "line": self.line, + } + + +@dataclass +class CStructField: + name: str + c_type: str + array_dim: Optional[int] = None + is_pointer: bool = False + doc: str = "" + + +@dataclass +class CStruct: + name: str + fields: List[CStructField] = field(default_factory=list) + doc: str = "" + file: str = "" + line: int = 0 + + def to_dict(self) -> Dict[str, Any]: + return { + "name": self.name, + "fields": [ + { + "name": f.name, + "c_type": f.c_type, + "array_dim": f.array_dim, + "is_pointer": f.is_pointer, + "doc": f.doc, + } + for f in self.fields + ], + "doc": self.doc, + "file": self.file, + "line": self.line, + } + + +@dataclass +class CDefine: + name: str + value: str + doc: str = "" + file: str = "" + line: int = 0 + + +@dataclass +class IntrospectSnapshot: + """Top-level container for the clang-AST scrape output. Serialised + to ``Scripts/introspect_snapshot.json``. snapshot_version bumps on + schema-incompatible changes. + + ``hand_enums`` mirrors ``enums`` but covers URLab's hand-rolled + ``EMj*`` enums under ``Source/URLab/Public``. They live in a + separate field so the MuJoCo mjt* lookup (value_map.mj_const drift + checks) doesn't accidentally collide with a future EMj* name.""" + snapshot_version: int = 1 + header_hash: str = "" + functions: Dict[str, CFunction] = field(default_factory=dict) + enums: Dict[str, CEnum] = field(default_factory=dict) + structs: Dict[str, CStruct] = field(default_factory=dict) + defines: Dict[str, CDefine] = field(default_factory=dict) + hand_enums: Dict[str, CEnum] = field(default_factory=dict) + + def to_dict(self) -> Dict[str, Any]: + return { + "_meta": { + "snapshot_version": self.snapshot_version, + "header_hash": self.header_hash, + }, + "functions": {n: f.to_dict() for n, f in self.functions.items()}, + "enums": {n: e.to_dict() for n, e in self.enums.items()}, + "structs": {n: s.to_dict() for n, s in self.structs.items()}, + "defines": { + n: {"value": d.value, "doc": d.doc, "file": d.file, "line": d.line} + for n, d in self.defines.items() + }, + "hand_enums": {n: e.to_dict() for n, e in self.hand_enums.items()}, + } diff --git a/Scripts/codegen/_vendored/mjspecmacro.h b/Scripts/codegen/_vendored/mjspecmacro.h new file mode 100644 index 0000000..81e861e --- /dev/null +++ b/Scripts/codegen/_vendored/mjspecmacro.h @@ -0,0 +1,603 @@ +// Copyright 2026 DeepMind Technologies Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef MUJOCO_MJSPECMACRO_H_ +#define MUJOCO_MJSPECMACRO_H_ + + +//-------------------------------- mjsElement ------------------------------------------------------ + +#define MJSELEMENT_FIELDS \ + X( mjtObj, elemtype, 1 ) \ + X( uint64_t, signature, 1 ) + + +//-------------------------------- mjsCompiler ----------------------------------------------------- + +#define MJSCOMPILER_FIELDS \ + X ( mjtByte, autolimits, 1 ) \ + X ( double, boundmass, 1 ) \ + X ( double, boundinertia, 1 ) \ + X ( double, settotalmass, 1 ) \ + X ( mjtByte, balanceinertia, 1 ) \ + X ( mjtByte, fitaabb, 1 ) \ + X ( mjtByte, degree, 1 ) \ + XVEC( char, eulerseq, 3 ) \ + X ( mjtByte, discardvisual, 1 ) \ + X ( mjtByte, usethread, 1 ) \ + X ( mjtByte, fusestatic, 1 ) \ + X ( int, inertiafromgeom, 1 ) \ + XVEC( int, inertiagrouprange, 2 ) \ + X ( mjtByte, saveinertial, 1 ) \ + X ( int, alignfree, 1 ) \ + X ( mjLROpt, LRopt, 1 ) \ + X ( mjString*, meshdir, 1 ) \ + X ( mjString*, texturedir, 1 ) + + +//-------------------------------- mjSpec ---------------------------------------------------------- + +#define MJSPEC_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjString*, modelname, 1 ) \ + X( mjsCompiler, compiler, 1 ) \ + X( mjtByte, strippath, 1 ) \ + X( mjOption, option, 1 ) \ + X( mjVisual, visual, 1 ) \ + X( mjStatistic, stat, 1 ) \ + X( mjtSize, memory, 1 ) \ + X( int, nemax, 1 ) \ + X( int, nuserdata, 1 ) \ + X( int, nuser_body, 1 ) \ + X( int, nuser_jnt, 1 ) \ + X( int, nuser_geom, 1 ) \ + X( int, nuser_site, 1 ) \ + X( int, nuser_cam, 1 ) \ + X( int, nuser_tendon, 1 ) \ + X( int, nuser_actuator, 1 ) \ + X( int, nuser_sensor, 1 ) \ + X( int, nkey, 1 ) \ + X( int, njmax, 1 ) \ + X( int, nconmax, 1 ) \ + X( mjtSize, nstack, 1 ) \ + X( mjString*, comment, 1 ) \ + X( mjString*, modelfiledir, 1 ) \ + X( mjtByte, hasImplicitPluginElem, 1 ) + + +//-------------------------------- mjsOrientation -------------------------------------------------- + +#define MJSORIENTATION_FIELDS \ + X ( mjtOrientation, type, 1 ) \ + XVEC( double, axisangle, 4 ) \ + XVEC( double, xyaxes, 6 ) \ + XVEC( double, zaxis, 3 ) \ + XVEC( double, euler, 3 ) + + +//-------------------------------- mjsPlugin ------------------------------------------------------- + +#define MJSPLUGIN_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjString*, name, 1 ) \ + X( mjString*, plugin_name, 1 ) \ + X( mjtByte, active, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsBody --------------------------------------------------------- + +#define MJSBODY_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjString*, childclass, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, quat, 4 ) \ + X ( mjsOrientation, alt, 1 ) \ + X ( double, mass, 1 ) \ + XVEC( double, ipos, 3 ) \ + XVEC( double, iquat, 4 ) \ + XVEC( double, inertia, 3 ) \ + X ( mjsOrientation, ialt, 1 ) \ + XVEC( double, fullinertia, 6 ) \ + X ( mjtByte, mocap, 1 ) \ + X ( double, gravcomp, 1 ) \ + X ( mjtSleepPolicy, sleep, 1 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjtByte, explicitinertial, 1 ) \ + X ( mjsPlugin, plugin, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsFrame -------------------------------------------------------- + +#define MJSFRAME_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjString*, childclass, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, quat, 4 ) \ + X ( mjsOrientation, alt, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsJoint -------------------------------------------------------- + +#define MJSJOINT_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjtJoint, type, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, axis, 3 ) \ + X ( double, ref, 1 ) \ + X ( int, align, 1 ) \ + XVEC( double, stiffness, mjNPOLY+1 ) \ + X ( double, springref, 1 ) \ + XVEC( double, springdamper, 2 ) \ + X ( int, limited, 1 ) \ + XVEC( double, range, 2 ) \ + X ( double, margin, 1 ) \ + XVEC( mjtNum, solref_limit, mjNREF ) \ + XVEC( mjtNum, solimp_limit, mjNIMP ) \ + X ( int, actfrclimited, 1 ) \ + XVEC( double, actfrcrange, 2 ) \ + X ( double, armature, 1 ) \ + XVEC( double, damping, mjNPOLY+1 ) \ + X ( double, frictionloss, 1 ) \ + XVEC( mjtNum, solref_friction, mjNREF ) \ + XVEC( mjtNum, solimp_friction, mjNIMP ) \ + X ( int, group, 1 ) \ + X ( mjtByte, actgravcomp, 1 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsGeom --------------------------------------------------------- + +#define MJSGEOM_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjtGeom, type, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, quat, 4 ) \ + X ( mjsOrientation, alt, 1 ) \ + XVEC( double, fromto, 6 ) \ + XVEC( double, size, 3 ) \ + X ( int, contype, 1 ) \ + X ( int, conaffinity, 1 ) \ + X ( int, condim, 1 ) \ + X ( int, priority, 1 ) \ + XVEC( double, friction, 3 ) \ + X ( double, solmix, 1 ) \ + XVEC( mjtNum, solref, mjNREF ) \ + XVEC( mjtNum, solimp, mjNIMP ) \ + X ( double, margin, 1 ) \ + X ( double, gap, 1 ) \ + X ( double, mass, 1 ) \ + X ( double, density, 1 ) \ + X ( mjtGeomInertia, typeinertia, 1 ) \ + X ( mjtNum, fluid_ellipsoid, 1 ) \ + XVEC( mjtNum, fluid_coefs, 5 ) \ + X ( mjString*, material, 1 ) \ + XVEC( float, rgba, 4 ) \ + X ( int, group, 1 ) \ + X ( mjString*, hfieldname, 1 ) \ + X ( mjString*, meshname, 1 ) \ + X ( double, fitscale, 1 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjsPlugin, plugin, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsSite --------------------------------------------------------- + +#define MJSSITE_FIELDS \ + X ( mjsElement*, element, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, quat, 4 ) \ + X ( mjsOrientation, alt, 1 ) \ + XVEC( double, fromto, 6 ) \ + XVEC( double, size, 3 ) \ + X ( mjtGeom, type, 1 ) \ + X ( mjString*, material, 1 ) \ + X ( int, group, 1 ) \ + XVEC( float, rgba, 4 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsCamera ------------------------------------------------------- + +#define MJSCAMERA_FIELDS \ + X ( mjsElement*, element, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, quat, 4 ) \ + X ( mjsOrientation, alt, 1 ) \ + X ( mjtCamLight, mode, 1 ) \ + X ( mjString*, targetbody, 1 ) \ + X ( mjtProjection, proj, 1 ) \ + XVEC( int, resolution, 2 ) \ + X ( int, output, 1 ) \ + X ( double, fovy, 1 ) \ + X ( double, ipd, 1 ) \ + XVEC( float, intrinsic, 4 ) \ + XVEC( float, sensor_size, 2 ) \ + XVEC( float, focal_length, 2 ) \ + XVEC( float, focal_pixel, 2 ) \ + XVEC( float, principal_length, 2 ) \ + XVEC( float, principal_pixel, 2 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsLight -------------------------------------------------------- + +#define MJSLIGHT_FIELDS \ + X ( mjsElement*, element, 1 ) \ + XVEC( double, pos, 3 ) \ + XVEC( double, dir, 3 ) \ + X ( mjtCamLight, mode, 1 ) \ + X ( mjString*, targetbody, 1 ) \ + X ( mjtByte, active, 1 ) \ + X ( mjtLightType, type, 1 ) \ + X ( mjString*, texture, 1 ) \ + X ( mjtByte, castshadow, 1 ) \ + X ( float, bulbradius, 1 ) \ + X ( float, intensity, 1 ) \ + X ( float, range, 1 ) \ + XVEC( float, attenuation, 3 ) \ + X ( float, cutoff, 1 ) \ + X ( float, exponent, 1 ) \ + XVEC( float, ambient, 3 ) \ + XVEC( float, diffuse, 3 ) \ + XVEC( float, specular, 3 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsFlex --------------------------------------------------------- + +#define MJSFLEX_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( int, contype, 1 ) \ + X ( int, conaffinity, 1 ) \ + X ( int, condim, 1 ) \ + X ( int, priority, 1 ) \ + XVEC( double, friction, 3 ) \ + X ( double, solmix, 1 ) \ + XVEC( mjtNum, solref, mjNREF ) \ + XVEC( mjtNum, solimp, mjNIMP ) \ + X ( double, margin, 1 ) \ + X ( double, gap, 1 ) \ + X ( int, dim, 1 ) \ + X ( double, radius, 1 ) \ + XVEC( double, size, 3 ) \ + X ( mjtByte, internal, 1 ) \ + X ( mjtByte, flatskin, 1 ) \ + X ( int, selfcollide, 1 ) \ + X ( int, passive, 1 ) \ + X ( int, activelayers, 1 ) \ + X ( int, group, 1 ) \ + X ( double, edgestiffness, 1 ) \ + X ( double, edgedamping, 1 ) \ + XVEC( float, rgba, 4 ) \ + X ( mjString*, material, 1 ) \ + X ( double, young, 1 ) \ + X ( double, poisson, 1 ) \ + X ( double, damping, 1 ) \ + X ( double, thickness, 1 ) \ + X ( int, elastic2d, 1 ) \ + XVEC( int, cellcount, 3 ) \ + X ( int, order, 1 ) \ + X ( mjStringVec*, nodebody, 1 ) \ + X ( mjStringVec*, vertbody, 1 ) \ + X ( mjDoubleVec*, node, 1 ) \ + X ( mjDoubleVec*, vert, 1 ) \ + X ( mjIntVec*, elem, 1 ) \ + X ( mjFloatVec*, texcoord, 1 ) \ + X ( mjIntVec*, elemtexcoord, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsMesh --------------------------------------------------------- + +#define MJSMESH_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjString*, content_type, 1 ) \ + X ( mjString*, file, 1 ) \ + XVEC( double, refpos, 3 ) \ + XVEC( double, refquat, 4 ) \ + XVEC( double, scale, 3 ) \ + X ( mjtMeshInertia, inertia, 1 ) \ + X ( mjtByte, smoothnormal, 1 ) \ + X ( mjtByte, needsdf, 1 ) \ + X ( int, maxhullvert, 1 ) \ + X ( mjFloatVec*, uservert, 1 ) \ + X ( mjFloatVec*, usernormal, 1 ) \ + X ( mjFloatVec*, usertexcoord, 1 ) \ + X ( mjIntVec*, userface, 1 ) \ + X ( mjIntVec*, userfacenormal, 1 ) \ + X ( mjIntVec*, userfacetexcoord, 1 ) \ + X ( mjsPlugin, plugin, 1 ) \ + X ( mjString*, material, 1 ) \ + X ( int, octree_maxdepth, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsHField ------------------------------------------------------- + +#define MJSHFIELD_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjString*, content_type, 1 ) \ + X ( mjString*, file, 1 ) \ + XVEC( double, size, 4 ) \ + X ( int, nrow, 1 ) \ + X ( int, ncol, 1 ) \ + X ( mjFloatVec*, userdata, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsSkin --------------------------------------------------------- + +#define MJSSKIN_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjString*, file, 1 ) \ + X ( mjString*, material, 1 ) \ + XVEC( float, rgba, 4 ) \ + X ( float, inflate, 1 ) \ + X ( int, group, 1 ) \ + X ( mjFloatVec*, vert, 1 ) \ + X ( mjFloatVec*, texcoord, 1 ) \ + X ( mjIntVec*, face, 1 ) \ + X ( mjStringVec*, bodyname, 1 ) \ + X ( mjFloatVec*, bindpos, 1 ) \ + X ( mjFloatVec*, bindquat, 1 ) \ + X ( mjIntVecVec*, vertid, 1 ) \ + X ( mjFloatVecVec*, vertweight, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsTexture ------------------------------------------------------ + +#define MJSTEXTURE_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjtTexture, type, 1 ) \ + X ( mjtColorSpace, colorspace, 1 ) \ + X ( int, builtin, 1 ) \ + X ( int, mark, 1 ) \ + XVEC( double, rgb1, 3 ) \ + XVEC( double, rgb2, 3 ) \ + XVEC( double, markrgb, 3 ) \ + X ( double, random, 1 ) \ + X ( int, height, 1 ) \ + X ( int, width, 1 ) \ + X ( int, nchannel, 1 ) \ + X ( mjString*, content_type, 1 ) \ + X ( mjString*, file, 1 ) \ + XVEC( int, gridsize, 2 ) \ + XVEC( char, gridlayout, 12 ) \ + X ( mjStringVec*, cubefiles, 1 ) \ + X ( mjByteVec*, data, 1 ) \ + X ( mjtByte, hflip, 1 ) \ + X ( mjtByte, vflip, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsMaterial ----------------------------------------------------- + +#define MJSMATERIAL_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjStringVec*, textures, 1 ) \ + X ( mjtByte, texuniform, 1 ) \ + XVEC( float, texrepeat, 2 ) \ + X ( float, emission, 1 ) \ + X ( float, specular, 1 ) \ + X ( float, shininess, 1 ) \ + X ( float, reflectance, 1 ) \ + X ( float, metallic, 1 ) \ + X ( float, roughness, 1 ) \ + XVEC( float, rgba, 4 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsPair --------------------------------------------------------- + +#define MJSPAIR_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjString*, geomname1, 1 ) \ + X ( mjString*, geomname2, 1 ) \ + X ( int, condim, 1 ) \ + XVEC( mjtNum, solref, mjNREF ) \ + XVEC( mjtNum, solreffriction, mjNREF ) \ + XVEC( mjtNum, solimp, mjNIMP ) \ + X ( double, margin, 1 ) \ + X ( double, gap, 1 ) \ + XVEC( double, friction, 5 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsExclude ------------------------------------------------------ + +#define MJSEXCLUDE_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjString*, bodyname1, 1 ) \ + X( mjString*, bodyname2, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsEquality ----------------------------------------------------- + +#define MJSEQUALITY_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjtEq, type, 1 ) \ + XVEC( double, data, mjNEQDATA ) \ + X ( mjtByte, active, 1 ) \ + X ( mjString*, name1, 1 ) \ + X ( mjString*, name2, 1 ) \ + X ( mjtObj, objtype, 1 ) \ + XVEC( mjtNum, solref, mjNREF ) \ + XVEC( mjtNum, solimp, mjNIMP ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsTendon ------------------------------------------------------- + +#define MJSTENDON_FIELDS \ + X ( mjsElement*, element, 1 ) \ + XVEC( double, stiffness, mjNPOLY+1 ) \ + XVEC( double, springlength, 2 ) \ + XVEC( double, damping, mjNPOLY+1 ) \ + X ( double, frictionloss, 1 ) \ + XVEC( mjtNum, solref_friction, mjNREF ) \ + XVEC( mjtNum, solimp_friction, mjNIMP ) \ + X ( double, armature, 1 ) \ + X ( int, limited, 1 ) \ + X ( int, actfrclimited, 1 ) \ + XVEC( double, range, 2 ) \ + XVEC( double, actfrcrange, 2 ) \ + X ( double, margin, 1 ) \ + XVEC( mjtNum, solref_limit, mjNREF ) \ + XVEC( mjtNum, solimp_limit, mjNIMP ) \ + X ( mjString*, material, 1 ) \ + X ( double, width, 1 ) \ + XVEC( float, rgba, 4 ) \ + X ( int, group, 1 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsWrap --------------------------------------------------------- + +#define MJSWRAP_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjtWrap, type, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsActuator ----------------------------------------------------- + +#define MJSACTUATOR_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjtGain, gaintype, 1 ) \ + XVEC( double, gainprm, mjNGAIN ) \ + X ( mjtBias, biastype, 1 ) \ + XVEC( double, biasprm, mjNGAIN ) \ + X ( mjtDyn, dyntype, 1 ) \ + XVEC( double, dynprm, mjNDYN ) \ + X ( int, actdim, 1 ) \ + X ( mjtByte, actearly, 1 ) \ + X ( mjtTrn, trntype, 1 ) \ + XVEC( double, gear, 6 ) \ + X ( mjString*, target, 1 ) \ + X ( mjString*, refsite, 1 ) \ + X ( mjString*, slidersite, 1 ) \ + X ( double, cranklength, 1 ) \ + XVEC( double, lengthrange, 2 ) \ + X ( double, inheritrange, 1 ) \ + XVEC( double, damping, mjNPOLY+1 ) \ + X ( double, armature, 1 ) \ + X ( int, ctrllimited, 1 ) \ + XVEC( double, ctrlrange, 2 ) \ + X ( int, forcelimited, 1 ) \ + XVEC( double, forcerange, 2 ) \ + X ( int, actlimited, 1 ) \ + XVEC( double, actrange, 2 ) \ + X ( int, group, 1 ) \ + X ( int, nsample, 1 ) \ + X ( int, interp, 1 ) \ + X ( double, delay, 1 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjsPlugin, plugin, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsSensor ------------------------------------------------------- + +#define MJSSENSOR_FIELDS \ + X ( mjsElement*, element, 1 ) \ + X ( mjtSensor, type, 1 ) \ + X ( mjtObj, objtype, 1 ) \ + X ( mjString*, objname, 1 ) \ + X ( mjtObj, reftype, 1 ) \ + X ( mjString*, refname, 1 ) \ + XVEC( int, intprm, mjNSENS ) \ + X ( mjtDataType, datatype, 1 ) \ + X ( mjtStage, needstage, 1 ) \ + X ( int, dim, 1 ) \ + X ( double, cutoff, 1 ) \ + X ( double, noise, 1 ) \ + X ( int, nsample, 1 ) \ + X ( int, interp, 1 ) \ + X ( double, delay, 1 ) \ + XVEC( double, interval, 2 ) \ + X ( mjDoubleVec*, userdata, 1 ) \ + X ( mjsPlugin, plugin, 1 ) \ + X ( mjString*, info, 1 ) + + +//-------------------------------- mjsNumeric ------------------------------------------------------ + +#define MJSNUMERIC_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjDoubleVec*, data, 1 ) \ + X( int, size, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsText --------------------------------------------------------- + +#define MJSTEXT_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjString*, data, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsTuple -------------------------------------------------------- + +#define MJSTUPLE_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjIntVec*, objtype, 1 ) \ + X( mjStringVec*, objname, 1 ) \ + X( mjDoubleVec*, objprm, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsKey ---------------------------------------------------------- + +#define MJSKEY_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( double, time, 1 ) \ + X( mjDoubleVec*, qpos, 1 ) \ + X( mjDoubleVec*, qvel, 1 ) \ + X( mjDoubleVec*, act, 1 ) \ + X( mjDoubleVec*, mpos, 1 ) \ + X( mjDoubleVec*, mquat, 1 ) \ + X( mjDoubleVec*, ctrl, 1 ) \ + X( mjString*, info, 1 ) + + +//-------------------------------- mjsDefault ------------------------------------------------------ + +#define MJSDEFAULT_FIELDS \ + X( mjsElement*, element, 1 ) \ + X( mjsJoint*, joint, 1 ) \ + X( mjsGeom*, geom, 1 ) \ + X( mjsSite*, site, 1 ) \ + X( mjsCamera*, camera, 1 ) \ + X( mjsLight*, light, 1 ) \ + X( mjsFlex*, flex, 1 ) \ + X( mjsMesh*, mesh, 1 ) \ + X( mjsMaterial*, material, 1 ) \ + X( mjsPair*, pair, 1 ) \ + X( mjsEquality*, equality, 1 ) \ + X( mjsTendon*, tendon, 1 ) \ + X( mjsActuator*, actuator, 1 ) + + +#endif // MUJOCO_MJSPECMACRO_H_ diff --git a/Scripts/codegen/build_introspect_snapshot.py b/Scripts/codegen/build_introspect_snapshot.py new file mode 100644 index 0000000..1098b81 --- /dev/null +++ b/Scripts/codegen/build_introspect_snapshot.py @@ -0,0 +1,487 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +clang.cindex-based scrape of MuJoCo headers (mjspec.h + mjmodel.h + +optionally the vendored mjspecmacro.h) into +``Scripts/codegen/snapshots/introspect_snapshot.json``. The codegen +consumes this snapshot as its single source of truth for the MuJoCo C +API surface. + +Captures: +- function signatures (every MJAPI-tagged declaration in the headers) +- enum decls with values + per-member doc comments +- struct decls with fields + per-field doc comments + array dims +- ``#define`` constants (after preprocessor evaluation when literal) + +Usage: + python Scripts/codegen/build_introspect_snapshot.py + [--mujoco-include /path/to/mujoco/include] + [--output Scripts/codegen/snapshots/introspect_snapshot.json] + [--libclang /path/to/libclang.dll] (only if not auto-found) + +libclang resolution: respects ``$LIBCLANG_LIBRARY_FILE`` env var; falls +back to clang.cindex's default search. Set ``--libclang`` to override. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +import re +import sys +from typing import Dict, List + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_PLUGIN_ROOT = os.path.normpath(os.path.join(_HERE, "..", "..")) + +# Use the local vendored ast_nodes copy. +sys.path.insert(0, os.path.join(_HERE, "_vendored")) +from ast_nodes import ( # noqa: E402 + CFunction, + CFunctionParam, + CEnum, + CEnumMember, + CStruct, + CStructField, + CDefine, + IntrospectSnapshot, +) + + +def _header_hash(paths: List[str]) -> str: + """SHA-256 of the concatenated header content. Lets callers skip + re-running the snapshot when nothing upstream changed.""" + h = hashlib.sha256() + for p in sorted(paths): + if not os.path.exists(p): + continue + with open(p, "rb") as f: + h.update(f.read()) + return h.hexdigest() + + +def _strip_doc(raw: str) -> str: + """Collapse a libclang raw doc comment into one line, stripping + leading ``//`` / ``/*`` decoration.""" + if not raw: + return "" + out_lines: List[str] = [] + for line in raw.splitlines(): + s = line.strip() + for prefix in ("///", "//!", "//", "/**", "*/", "*", "/*"): + if s.startswith(prefix): + s = s[len(prefix):].strip() + break + if s.endswith("*/"): + s = s[:-2].strip() + if s: + out_lines.append(s) + return " ".join(out_lines) + + +def _walk(tu, mujoco_include: str, snapshot: IntrospectSnapshot) -> None: + """Visit every cursor in the translation unit. ``mujoco_include`` is + the include root; we only capture decls whose file lives under it + (so libc / Windows SDK / TinyXML noise is filtered out).""" + import clang.cindex as cx # noqa: E402, local-only + + plugin_root_norm = os.path.normcase(os.path.abspath(_PLUGIN_ROOT)) + + def _normalised_path(loc) -> str: + """Return the location's file as a forward-slash path relative to + the plugin root, so the snapshot is byte-identical across + developers (no absolute ``c:\\users\\...`` strings).""" + if not loc or not loc.file: + return "" + abs_path = os.path.normcase(os.path.abspath(loc.file.name)) + if abs_path.startswith(plugin_root_norm): + rel = os.path.relpath(abs_path, plugin_root_norm) + return rel.replace("\\", "/") + return abs_path.replace("\\", "/") + + # Filter root mirrors _normalised_path: relative-to-plugin-root with + # forward slashes. + mujoco_abs = os.path.normcase(os.path.abspath(mujoco_include)) + if mujoco_abs.startswith(plugin_root_norm): + norm_root = os.path.relpath(mujoco_abs, plugin_root_norm).replace("\\", "/") + else: + norm_root = mujoco_abs.replace("\\", "/") + + for cursor in tu.cursor.get_children(): + fp = _normalised_path(cursor.location) + if not fp.startswith(norm_root): + continue + + kind = cursor.kind + + if kind == cx.CursorKind.FUNCTION_DECL: + params: List[CFunctionParam] = [] + for arg in cursor.get_arguments(): + t = arg.type.spelling + dim = None + if "[" in t and "]" in t: + # e.g. "double [4]" -> dim=4 + try: + dim_str = t[t.index("[") + 1:t.index("]")] + if dim_str.strip().isdigit(): + dim = int(dim_str) + except ValueError: + pass + params.append(CFunctionParam( + name=arg.spelling, c_type=t, array_dim=dim, + )) + fn = CFunction( + name=cursor.spelling, + return_type=cursor.result_type.spelling, + params=params, + doc=_strip_doc(cursor.raw_comment or ""), + file=fp, + line=cursor.location.line if cursor.location else 0, + ) + snapshot.functions[fn.name] = fn + + elif kind == cx.CursorKind.ENUM_DECL: + # Anonymous enums get spelling = "" — skip; we only want + # named typedef enums. The C tag name is ``mjtJoint_`` but + # callers reference the typedef ``mjtJoint``; normalise here. + name = cursor.spelling or cursor.type.spelling + if not name or name.startswith("(anonymous"): + continue + if name.endswith("_"): + name = name[:-1] + members: List[CEnumMember] = [] + for child in cursor.get_children(): + if child.kind == cx.CursorKind.ENUM_CONSTANT_DECL: + members.append(CEnumMember( + name=child.spelling, + value=child.enum_value, + doc=_strip_doc(child.raw_comment or ""), + )) + underlying = cursor.enum_type.spelling if cursor.enum_type else None + snapshot.enums[name] = CEnum( + name=name, members=members, + underlying_type=underlying, + doc=_strip_doc(cursor.raw_comment or ""), + file=fp, + line=cursor.location.line if cursor.location else 0, + ) + + elif kind == cx.CursorKind.STRUCT_DECL: + name = cursor.spelling or cursor.type.spelling + if not name: + continue + # Strip trailing underscore from C tag names ("mjsBody_" -> "mjsBody"). + if name.endswith("_"): + name = name[:-1] + fields: List[CStructField] = [] + for child in cursor.get_children(): + if child.kind != cx.CursorKind.FIELD_DECL: + continue + t = child.type.spelling + dim = None + is_ptr = "*" in t + if "[" in t and "]" in t: + try: + dim_str = t[t.index("[") + 1:t.index("]")] + if dim_str.strip().isdigit(): + dim = int(dim_str) + except ValueError: + pass + fields.append(CStructField( + name=child.spelling, + c_type=t, + array_dim=dim, + is_pointer=is_ptr, + doc=_strip_doc(child.raw_comment or ""), + )) + snapshot.structs[name] = CStruct( + name=name, fields=fields, + doc=_strip_doc(cursor.raw_comment or ""), + file=fp, + line=cursor.location.line if cursor.location else 0, + ) + + elif kind == cx.CursorKind.MACRO_DEFINITION: + name = cursor.spelling + # Skip function-like macros; libclang doesn't expand them. + # Skip header guards. + if name.endswith("_H_") or name.startswith("__"): + continue + # Extract tokens between the cursor's extent to get the value. + tokens = list(tu.get_tokens(extent=cursor.extent)) + if len(tokens) < 2: + continue + value = " ".join(t.spelling for t in tokens[1:]) + snapshot.defines[name] = CDefine( + name=name, value=value, + doc=_strip_doc(cursor.raw_comment or ""), + file=fp, + line=cursor.location.line if cursor.location else 0, + ) + + +# --------------------------------------------------------------------------- +# URLab hand-enum scrape +# +# UE hand-rolled ``enum class EMj* : uint8 { ... }`` declarations live in +# C++ headers that #include CoreMinimal.h + lots of UE machinery libclang +# can't parse standalone. Extract each enum block via regex (the +# delimiters are stable), strip the UE-macro surface (UMETA/UENUM/UMETA), +# and hand the cleaned single-enum source to libclang for AST-level +# member extraction. That gives us libclang's accuracy on member values +# without the UE-include hell, and is byte-comparable to the regex +# scraper that used to live in generate_ue_components.py. +# --------------------------------------------------------------------------- + +_HAND_ENUM_BLOCK_RE = re.compile( + r"(enum\s+class\s+EMj\w+\s*:\s*uint8\s*\{[^}]*\}\s*;)", + re.DOTALL, +) +_HAND_ENUM_NAME_RE = re.compile(r"enum\s+class\s+(EMj\w+)") + + +_UE_FN_MACRO_RE = re.compile(r"\b(UMETA|UENUM)\s*\(") + + +def _strip_balanced_call(text: str, start: int) -> int: + """Return the index just past the matching ``)`` for a function-call + opener at ``start``. Handles nested parens — naive ``[^)]*`` would + bail on ``UMETA(DisplayName = "Track (Centre of Mass)")``.""" + depth = 1 + i = start + 1 + in_str = None + while i < len(text) and depth > 0: + ch = text[i] + if in_str: + if ch == "\\" and i + 1 < len(text): + i += 2 + continue + if ch == in_str: + in_str = None + elif ch in ('"', "'"): + in_str = ch + elif ch == "(": + depth += 1 + elif ch == ")": + depth -= 1 + i += 1 + return i + + +def _strip_ue_macros_from_enum_block(text: str) -> str: + """Erase ``UMETA(...)`` and ``UENUM(...)`` function-like macros so a + plain libclang pass can compile the enum block. Each macro turns + into the empty string; the surrounding member identifiers + comma + separators stay intact. Handles nested parens inside the macro + argument — ``UMETA(DisplayName = "Track (Centre of Mass)")`` etc.""" + out: List[str] = [] + i = 0 + while i < len(text): + m = _UE_FN_MACRO_RE.search(text, i) + if not m: + out.append(text[i:]) + break + out.append(text[i:m.start()]) + i = _strip_balanced_call(text, m.end() - 1) + stripped = "".join(out) + stripped = re.sub(r"//[^\n]*", "", stripped) + stripped = re.sub(r"/\*.*?\*/", "", stripped, flags=re.DOTALL) + return stripped + + +def _scrape_hand_enums_via_libclang( + urlab_source_root: str, +) -> Dict[str, CEnum]: + """Walk every .h under ``urlab_source_root`` looking for ``enum class + EMj* : uint8`` blocks; hand each cleaned block to libclang for + member + value extraction. + + Returns ``{enum_name: CEnum}``. The plugin_root-relative path is + stamped on each entry so the snapshot stays byte-identical across + developer machines (no absolute ``c:\\users\\...`` strings).""" + import clang.cindex as cx # noqa: E402, local-only + + plugin_root_norm = os.path.normcase(os.path.abspath(_PLUGIN_ROOT)) + out: Dict[str, CEnum] = {} + idx = cx.Index.create() + + for root, _dirs, files in os.walk(urlab_source_root): + for name in files: + if not name.endswith(".h"): + continue + path = os.path.join(root, name) + try: + with open(path, "r", encoding="utf-8") as f: + text = f.read() + except OSError: + continue + rel = os.path.relpath( + os.path.normcase(os.path.abspath(path)), + plugin_root_norm, + ).replace("\\", "/") + for block_match in _HAND_ENUM_BLOCK_RE.finditer(text): + block = block_match.group(1) + name_m = _HAND_ENUM_NAME_RE.search(block) + if not name_m: + continue + enum_name = name_m.group(1) + cleaned = _strip_ue_macros_from_enum_block(block) + # Compute 1-based source line of the enum's opening + # ``enum`` keyword (the block_match is anchored on the + # whole declaration, so its start offset is also the + # enum's start). + start_line = text[:block_match.start()].count("\n") + 1 + # UE typedefs uint8 to unsigned char; provide our own + # typedef so libclang doesn't need any system headers + # (which on Windows pull in MSVC STL that triggers a + # "Unexpected compiler version" static_assert). + tu = idx.parse( + path=".cpp", + args=["-x", "c++", "-std=c++17", "-nostdinc", + "-nostdinc++", "-ferror-limit=0"], + unsaved_files=[( + ".cpp", + "typedef unsigned char uint8;\n" + cleaned + "\n", + )], + options=cx.TranslationUnit.PARSE_SKIP_FUNCTION_BODIES, + ) + # Don't bail on diagnostics — even with errors libclang + # produces usable ENUM_DECL cursors. The downstream + # match-by-name + member iteration covers correctness. + for cursor in tu.cursor.walk_preorder(): + if cursor.kind != cx.CursorKind.ENUM_DECL: + continue + if cursor.spelling != enum_name: + continue + members: List[CEnumMember] = [] + for child in cursor.get_children(): + if child.kind == cx.CursorKind.ENUM_CONSTANT_DECL: + members.append(CEnumMember( + name=child.spelling, + value=child.enum_value, + doc="", + )) + if not members: + continue + out[enum_name] = CEnum( + name=enum_name, + members=members, + underlying_type="uint8", + doc="", + file=rel, + line=start_line, + ) + break + return out + + +def main(argv: List[str] | None = None) -> int: + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--mujoco-include", default=os.path.join( + _PLUGIN_ROOT, "third_party", "install", "MuJoCo", "include", + )) + ap.add_argument("--output", default=os.path.join( + _PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "introspect_snapshot.json", + )) + ap.add_argument("--libclang", default=None, + help="path to libclang.dll/.so/.dylib; overrides auto-detect") + ap.add_argument("--urlab-source-root", default=os.path.join( + _PLUGIN_ROOT, "Source", "URLab", "Public", + ), help="root for the EMj* hand-enum libclang scrape; skipped if empty") + args = ap.parse_args(argv) + + try: + import clang.cindex as cx + except ImportError: + print("ERROR: clang.cindex not installed. Run " + "`uv run --with libclang python build_introspect_snapshot.py` " + "or `pip install libclang`.", file=sys.stderr) + return 1 + + if args.libclang: + cx.Config.set_library_file(args.libclang) + elif os.environ.get("LIBCLANG_LIBRARY_FILE"): + cx.Config.set_library_file(os.environ["LIBCLANG_LIBRARY_FILE"]) + + mujoco_include = args.mujoco_include + if not os.path.exists(mujoco_include): + print(f"ERROR: --mujoco-include not found: {mujoco_include}", file=sys.stderr) + return 2 + + mjspec_h = os.path.join(mujoco_include, "mujoco", "mjspec.h") + mjmodel_h = os.path.join(mujoco_include, "mujoco", "mjmodel.h") + mjxmacro_h = os.path.join(mujoco_include, "mujoco", "mjxmacro.h") + + # Vendored mjspecmacro.h (only used if non-stub; sync_vendored.py + # fills it from upstream). + vendored_mjspecmacro = os.path.join(_HERE, "_vendored", "mjspecmacro.h") + + # Synthesize a small dispatch source that #includes the headers we + # care about. Letting clang chew on a real .c lets it resolve types + # without us threading -include flags. + dispatch_c = "\n".join([ + "#include ", + "#include ", + "#include ", + "#include ", + ]) + args_clang = [ + "-x", "c", + "-std=c11", + f"-I{mujoco_include}", + "-DMJ_STATIC", # avoid MJAPI dllimport/export linkage attrs + ] + + try: + idx = cx.Index.create() + except cx.LibclangError as exc: + print(f"ERROR: libclang failed to load: {exc}", file=sys.stderr) + return 3 + + tu = idx.parse( + path=".c", + args=args_clang, + unsaved_files=[(".c", dispatch_c)], + options=(cx.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD + | cx.TranslationUnit.PARSE_SKIP_FUNCTION_BODIES), + ) + fatal_diags = [d for d in tu.diagnostics if d.severity >= cx.Diagnostic.Error] + if fatal_diags: + print(f"libclang errors:", file=sys.stderr) + for d in fatal_diags[:5]: + print(f" {d.spelling} ({d.location})", file=sys.stderr) + return 4 + + snapshot = IntrospectSnapshot( + snapshot_version=1, + header_hash=_header_hash([mjspec_h, mjmodel_h, mjxmacro_h, + vendored_mjspecmacro]), + ) + _walk(tu, mujoco_include, snapshot) + + if args.urlab_source_root and os.path.isdir(args.urlab_source_root): + try: + snapshot.hand_enums = _scrape_hand_enums_via_libclang( + args.urlab_source_root, + ) + except cx.LibclangError as exc: + print(f"warning: hand-enum libclang scrape skipped: {exc}", + file=sys.stderr) + + out_dict = snapshot.to_dict() + os.makedirs(os.path.dirname(args.output), exist_ok=True) + with open(args.output, "w", encoding="utf-8") as f: + json.dump(out_dict, f, indent=2) + print(f"wrote {args.output}: " + f"{len(snapshot.functions)} functions, " + f"{len(snapshot.enums)} enums, " + f"{len(snapshot.structs)} structs, " + f"{len(snapshot.defines)} defines, " + f"{len(snapshot.hand_enums)} hand_enums, " + f"header_hash={snapshot.header_hash[:12]}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Scripts/codegen/build_mjcf_schema_snapshot.py b/Scripts/codegen/build_mjcf_schema_snapshot.py index 53f4327..634d448 100644 --- a/Scripts/codegen/build_mjcf_schema_snapshot.py +++ b/Scripts/codegen/build_mjcf_schema_snapshot.py @@ -175,7 +175,209 @@ def _find_child(parent: SchemaNode, name: str) -> Optional[SchemaNode]: ] -def _build_snapshot(root: SchemaNode, mujoco_version: str) -> Dict: +# ---------------------------------------------------------------------------- +# Per-sensor objtype/reftype extraction +# ---------------------------------------------------------------------------- +# +# The static MJCF[nMJCF] schema only carries attr lists — not the per-sensor +# mapping between the XML element name and the mjsSensor objtype/reftype the +# compiler expects. That logic lives in xml_native_reader.cc's `Sensor()` +# method (a giant if/else cascade, one branch per sensor type). The codegen +# scrapes those branches here so rules don't have to hand-list them. + +# Inside Sensor(), each "regular" branch follows: +# if (type == "") { +# sensor->type = mjSENS_X; +# sensor->objtype = mjOBJ_Y; // OPTIONAL: literal default +# ReadAttrTxt(elem, "", objname, true); // OPTIONAL: name source +# sensor->reftype = mjOBJ_Z; // OPTIONAL +# ReadAttrTxt(elem, "", refname, true); // OPTIONAL: ref name source +# } +# +# "Computed" branches (rangefinder, distance/normal/fromto, contact, user, +# plugin) derive objtype/reftype from attribute presence at parse time; +# those get marked computed=True so codegen rules keep their explicit +# overrides for them. +# Matches the open of a sensor branch, capturing the parenthesised condition +# string. We post-process the condition to pull out every ``type == "NAME"`` +# clause so ``else if (type == "distance" || type == "normal" || type == +# "fromto") { ... }`` produces three entries that share the branch body. +_SENSOR_BRANCH_RE = re.compile( + r'(?:if|else if)\s*\((?P[^{]*?type\s*==\s*"[^"]+"[^{]*)\)\s*\{', + re.DOTALL, +) +_SENSOR_NAMES_IN_COND_RE = re.compile(r'type\s*==\s*"([^"]+)"') +_TYPE_LITERAL_RE = re.compile(r'sensor->type\s*=\s*(mjSENS_\w+)\s*;') +_OBJTYPE_LITERAL_RE = re.compile(r'sensor->objtype\s*=\s*(mjOBJ_\w+)\s*;') +_REFTYPE_LITERAL_RE = re.compile(r'sensor->reftype\s*=\s*(mjOBJ_\w+)\s*;') +_OBJTYPE_FROM_XML_RE = re.compile( + r'ReadAttrTxt\s*\(\s*elem\s*,\s*"objtype"\s*,\s*text' +) +_NAME_READ_RE = re.compile( + r'ReadAttrTxt\s*\(\s*elem\s*,\s*"([^"]+)"\s*,\s*(objname|refname)\b' +) + + +def _slice_balanced_braces(src: str, open_idx: int) -> str: + """Given an index pointing AT '{', return the substring up to the + matching close (exclusive of both braces). Tracks string literals and + line/block comments so braces inside ``"..."``, ``//`` or ``/* */`` are + ignored. Returns "" if no matching close found.""" + assert src[open_idx] == "{" + n = len(src) + depth = 0 + i = open_idx + in_str = False + str_q = "" + in_line_comment = False + in_block_comment = False + while i < n: + c = src[i] + c2 = src[i:i+2] + if in_line_comment: + if c == "\n": + in_line_comment = False + i += 1 + continue + if in_block_comment: + if c2 == "*/": + in_block_comment = False + i += 2 + continue + i += 1 + continue + if in_str: + if c == "\\": + i += 2 + continue + if c == str_q: + in_str = False + i += 1 + continue + if c2 == "//": + in_line_comment = True + i += 2 + continue + if c2 == "/*": + in_block_comment = True + i += 2 + continue + if c in ('"', "'"): + in_str = True + str_q = c + i += 1 + continue + if c == "{": + depth += 1 + elif c == "}": + depth -= 1 + if depth == 0: + return src[open_idx+1:i] + i += 1 + return "" + + +# Branches where objtype/reftype are derived from attribute presence at +# parse time (multiple ReadAttrTxt + sensor->objtype = X ? mjOBJ_A : mjOBJ_B +# pattern). Codegen rules keep explicit overrides for these; the extractor +# marks them computed=True so the generated codegen doesn't pretend to know. +_COMPUTED_OBJTYPE_SENSORS = { + "rangefinder", "distance", "normal", "fromto", "contact", + "user", "plugin", +} + + +def _extract_sensor_per_type(src_text: str) -> Dict[str, Dict[str, object]]: + """Scrape ``Sensor()``'s per-type if/else cascade. Returns a dict + keyed by XML element name; each entry has: + + objtype: "mjOBJ_X" | "from_xml" | "computed" | None + reftype: "mjOBJ_Y" | "computed" | None + obj_attr: "site"/"joint"/.../None (XML attr name carrying objname) + ref_attr: "camera"/"site"/.../None (XML attr name carrying refname) + computed: True iff objtype/reftype are derived from attr presence + """ + # Slice out the Sensor() method body so we don't pick up branches from + # other methods that happen to share regex shapes. + sig_re = re.compile(r"void\s+mjXReader::Sensor\s*\(") + m = sig_re.search(src_text) + if not m: + return {} + open_idx = src_text.find("{", m.end()) + if open_idx < 0: + return {} + body = _slice_balanced_braces(src_text, open_idx) + if not body: + return {} + + result: Dict[str, Dict[str, object]] = {} + # Some outer branches (distance/normal/fromto, contact, plugin) contain + # an inner ``if (type == "X")`` that toggles ->type. Those inner matches + # would otherwise overwrite the outer-branch entry with a stripped-down + # body. Track the [start, end) of each outer-branch body and skip + # matches whose '{' falls inside. + consumed_ranges: List[tuple] = [] + for bm in _SENSOR_BRANCH_RE.finditer(body): + names = _SENSOR_NAMES_IN_COND_RE.findall(bm.group("cond")) + if not names: + continue + brace_idx = bm.end() - 1 + if brace_idx < 0 or body[brace_idx] != "{": + continue + if any(s < brace_idx < e for s, e in consumed_ranges): + continue + branch = _slice_balanced_braces(body, brace_idx) + consumed_ranges.append((brace_idx, brace_idx + 1 + len(branch))) + + obj_literal = _OBJTYPE_LITERAL_RE.search(branch) + ref_literal = _REFTYPE_LITERAL_RE.search(branch) + obj_from_xml = bool(_OBJTYPE_FROM_XML_RE.search(branch)) and not obj_literal + + obj_attr: Optional[str] = None + ref_attr: Optional[str] = None + for nm in _NAME_READ_RE.finditer(branch): + attr, target = nm.group(1), nm.group(2) + if attr == "objtype": + continue # the literal "objtype" attr selector, not a name source + if target == "objname" and obj_attr is None: + obj_attr = attr + elif target == "refname" and ref_attr is None: + ref_attr = attr + + # Capture the mjSENS_X assigned in this branch. Multi-name branches + # (distance/normal/fromto) carry an inner positional switch with + # one ->type per name. Single-name branches (touch, framepos, ...) + # have exactly one mjSENS_X. + mj_types = [m.group(1) for m in _TYPE_LITERAL_RE.finditer(branch)] + if len(mj_types) == len(names): + name_to_mj_type = dict(zip(names, mj_types)) + elif mj_types: + # Single-type branch — every name shares it. + name_to_mj_type = {n: mj_types[0] for n in names} + else: + name_to_mj_type = {n: None for n in names} + + # Multi-name branches (distance/normal/fromto share one block, + # routed inside by `if (type == ...)` to set ->type). All share + # the same objtype/reftype derivation, so emit one entry per name. + for name in names: + computed = name in _COMPUTED_OBJTYPE_SENSORS + result[name] = { + "mj_type": name_to_mj_type.get(name), + "objtype": ("computed" if computed + else ("from_xml" if obj_from_xml + else (obj_literal.group(1) if obj_literal else None))), + "reftype": ("computed" if computed + else (ref_literal.group(1) if ref_literal else None)), + "obj_attr": obj_attr, + "ref_attr": ref_attr, + "computed": computed, + } + return result + + +def _build_snapshot(root: SchemaNode, mujoco_version: str, *, + src_text: str = "") -> Dict: """Walk the parsed MJCF tree and project it onto URLab's curated shape.""" out: Dict = { "_meta": { @@ -237,11 +439,22 @@ def _build_snapshot(root: SchemaNode, mujoco_version: str) -> Dict: # Sensor section: per-type attr declarations. URLab tracks: # sensor_types = list of names # sensor_common = shared attrs (_SENSOR_COMMON_ATTRS, URLab convention) + # sensor_per_type = per-sensor objtype/reftype/attr defaults scraped + # from xml_native_reader.cc's Sensor() method body sensor = _find_child(mujoco, "sensor") if sensor is not None: sensor_attrs = {c.name: list(c.attrs) for c in sensor.children} out["sensor_types"] = list(sensor_attrs.keys()) out["sensor_common"] = {"attrs": list(_SENSOR_COMMON_ATTRS)} + if src_text: + per_type = _extract_sensor_per_type(src_text) + # Only emit per-type rows for sensors that exist in the static + # MJCF schema — keeps the snapshot in sync if MuJoCo adds a + # parser branch but not a schema entry (or vice versa). + out["sensor_per_type"] = { + name: per_type[name] for name in sensor_attrs + if name in per_type + } # Tendon section: spatial vs fixed, plus wrap types. tendon = _find_child(mujoco, "tendon") @@ -348,7 +561,7 @@ def main(argv: Optional[List[str]] = None) -> int: plugin_root, "third_party", "MuJoCo", "src", "src", "xml", "xml_native_reader.cc", ) - default_output = os.path.join(plugin_root, "Scripts", "mjcf_schema_snapshot.json") + default_output = os.path.join(plugin_root, "Scripts", "codegen", "snapshots", "mjcf_schema_snapshot.json") ap = argparse.ArgumentParser() ap.add_argument("--src", default=default_src, @@ -367,7 +580,7 @@ def main(argv: Optional[List[str]] = None) -> int: blocks = _tokenise_blocks(body) root = _parse_tree(blocks) version = _detect_mujoco_version(args.src) - snapshot = _build_snapshot(root, mujoco_version=version) + snapshot = _build_snapshot(root, mujoco_version=version, src_text=src_text) os.makedirs(os.path.dirname(args.output), exist_ok=True) with open(args.output, "w", encoding="utf-8") as f: diff --git a/Scripts/codegen/build_mjspec_snapshot.py b/Scripts/codegen/build_mjspec_snapshot.py deleted file mode 100644 index 706d7ac..0000000 --- a/Scripts/codegen/build_mjspec_snapshot.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. -"""Parse mjspec.h and emit a JSON snapshot of each `mjs` struct's -fields so codegen can look up the real C field name (e.g. mjsExclude -holds `bodyname1`, not the schema attr `body1`). - -Output: ``Scripts/mjspec_snapshot.json`` with shape - { - "structs": { - "mjsBody": ["element", "name", "childclass", ...], - "mjsPair": ["element", "geomname1", "geomname2", "condim", ...], - ... - } - } - -Usage: - python build_mjspec_snapshot.py - [--mjspec PATH] (default: third_party/install/MuJoCo/include/mujoco/mjspec.h) - [--output PATH] (default: Scripts/mjspec_snapshot.json) -""" - -from __future__ import annotations - -import argparse -import json -import os -import re -import sys - -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -PLUGIN_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..")) - -DEFAULT_MJSPEC = os.path.join( - PLUGIN_ROOT, "third_party", "install", "MuJoCo", "include", "mujoco", "mjspec.h" -) -DEFAULT_MUJOCO_H = os.path.join( - PLUGIN_ROOT, "third_party", "install", "MuJoCo", "include", "mujoco", "mujoco.h" -) -DEFAULT_OUTPUT = os.path.join(PLUGIN_ROOT, "Scripts", "mjspec_snapshot.json") - -# Matches `typedef struct mjsName_ { ... } mjsName;` blocks. -_STRUCT_RE = re.compile( - r"typedef\s+struct\s+(mjs\w+)_\s*\{(.*?)\}\s*\1\s*;", - re.DOTALL, -) - -# Inside a struct body, a field line looks like: -# ` ;` -> e.g. `int condim;` -# ` [];` -> e.g. `mjtNum solref[mjNREF];` -# `* ;` -> e.g. `mjString* name;` -# ` [d1][d2];` -> e.g. `double data[mjNEQDATA];` -# Comments after the `;` are stripped before matching. -_FIELD_RE = re.compile( - r"^\s*" - r"(?:struct\s+)?" # optional `struct` keyword - r"(?P[\w:]+\s*\**)\s+" # type, possibly with `*` - r"(?P\w+)" # field name - r"(?:\s*\[[^\]]*\])*" # optional [dim] suffix(es) - r"\s*;", - re.MULTILINE, -) - - -def parse_structs(text: str) -> dict[str, list[str]]: - structs: dict[str, list[str]] = {} - for m in _STRUCT_RE.finditer(text): - name = m.group(1) - body = m.group(2) - # Strip line-end comments. - body_clean = re.sub(r"//[^\n]*", "", body) - body_clean = re.sub(r"/\*.*?\*/", "", body_clean, flags=re.DOTALL) - fields: list[str] = [] - for fm in _FIELD_RE.finditer(body_clean): - fname = fm.group("name") - # Skip C-keyword-only matches; the regex shouldn't, but be safe. - if fname in ("struct", "const", "typedef", "if", "else"): - continue - fields.append(fname) - structs[name] = fields - return structs - - -# Matches `MJAPI const char* mjs_setToX(mjsActuator* actuator, ... params ...);`. -# DOTALL so the param list can span lines. `?:` non-capturing to keep groups -# minimal; we re-parse the param string with `_PARAM_RE` below. -_SETTO_RE = re.compile( - r"MJAPI\s+const\s+char\s*\*\s*" - r"(?Pmjs_setTo\w+)\s*" - r"\(\s*mjsActuator\s*\*\s*\w+\s*(?:,\s*(?P[^)]*))?\s*\)", - re.DOTALL, -) - -# Inside the param list, each param looks like ` []?`, -# separated by commas. Handles `double kv[1]`, `double timeconst`, `int input_mode`. -_PARAM_RE = re.compile( - r"^\s*(?P[\w]+)\s+" - r"(?P\w+)" - r"(?:\s*\[\s*(?P\d+)\s*\])?\s*$" -) - - -def parse_setto_functions(text: str) -> dict[str, dict]: - """Scrape ``mjs_setTo*`` function declarations from mujoco.h. Skips the - first ``mjsActuator* actuator`` parameter; returns the remaining - parameter list with C type and (if present) fixed array dimension.""" - out: dict[str, dict] = {} - for m in _SETTO_RE.finditer(text): - name = m.group("name") - params_text = (m.group("params") or "").strip() - params: list[dict] = [] - if params_text: - for raw in params_text.split(","): - raw_clean = re.sub(r"//[^\n]*", "", raw).strip() - if not raw_clean: - continue - pm = _PARAM_RE.match(raw_clean) - if not pm: - raise RuntimeError( - f"unparsed mjs_setTo* param: {raw_clean!r} in {name}" - ) - params.append({ - "name": pm.group("name"), - "c_type": pm.group("c_type"), - "array_dim": int(pm.group("dim")) if pm.group("dim") else None, - }) - out[name] = {"params": params} - return out - - -def main() -> int: - ap = argparse.ArgumentParser(description=__doc__) - ap.add_argument("--mjspec", default=DEFAULT_MJSPEC) - ap.add_argument("--mujoco-h", default=DEFAULT_MUJOCO_H) - ap.add_argument("--output", default=DEFAULT_OUTPUT) - args = ap.parse_args() - - if not os.path.exists(args.mjspec): - print(f"ERROR: mjspec.h not found at {args.mjspec}", file=sys.stderr) - return 1 - - with open(args.mjspec, "r", encoding="utf-8") as f: - text = f.read() - - structs = parse_structs(text) - out = {"structs": structs} - - # Also scrape mjs_setTo* signatures from mujoco.h so codegen can emit - # the actuator preset calls from introspection instead of hand-written - # C++ literals in codegen_rules.json. - if os.path.exists(args.mujoco_h): - with open(args.mujoco_h, "r", encoding="utf-8") as f: - mj_text = f.read() - out["setto_functions"] = parse_setto_functions(mj_text) - else: - print(f"WARN: mujoco.h not found at {args.mujoco_h} — skipping setto functions", file=sys.stderr) - out["setto_functions"] = {} - - os.makedirs(os.path.dirname(args.output), exist_ok=True) - with open(args.output, "w", encoding="utf-8") as f: - json.dump(out, f, indent=2) - - total_fields = sum(len(v) for v in structs.values()) - print(f"wrote {args.output}: {len(structs)} structs, {total_fields} fields, " - f"{len(out['setto_functions'])} setto functions") - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/Scripts/codegen/build_mjxmacro_snapshot.py b/Scripts/codegen/build_mjxmacro_snapshot.py index f60706f..d2053cc 100644 --- a/Scripts/codegen/build_mjxmacro_snapshot.py +++ b/Scripts/codegen/build_mjxmacro_snapshot.py @@ -30,7 +30,7 @@ DEFAULT_MJXMACRO = os.path.join( PLUGIN_ROOT, "third_party", "install", "MuJoCo", "include", "mujoco", "mjxmacro.h" ) -DEFAULT_OUTPUT = os.path.join(PLUGIN_ROOT, "Scripts", "mjxmacro_snapshot.json") +DEFAULT_OUTPUT = os.path.join(PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "mjxmacro_snapshot.json") # Block names we care about. Categorized so the consumer knows the # kind of data (per-element pointer table vs flat struct fields). @@ -76,9 +76,12 @@ "MJDATA_ARENA_POINTERS_DUAL", "MJDATA_ARENA_POINTERS_ISLAND", "MJDATA_ARENA_POINTERS_SOLVER", + "MJDATA_ARENA_POINTERS_CONTACT", ] # Flat struct field blocks (no outer dimension — just type + name + size). +# Lives across both mjxmacro.h (the mjmodel-side struct fields) and +# mjspecmacro.h (the mjspec-side struct fields). STRUCT_FIELD_BLOCKS = [ "MJOPTION_FIELDS", "MJSTATISTIC_FIELDS", @@ -88,13 +91,26 @@ "MJVISUAL_MAP_FIELDS", "MJVISUAL_SCALE_FIELDS", "MJVISUAL_RGBA_FIELDS", + "MJSCOMPILER_FIELDS", + "MJSPEC_FIELDS", ] +DEFAULT_MJSPECMACRO = os.path.join( + SCRIPT_DIR, "_vendored", "mjspecmacro.h", +) + # Regexes _BLOCK_START_RE = re.compile(r"^\s*#define\s+(\w+)\s*(?:\(\s*\w+\s*\))?\s*\\?\s*$") +# Single source of truth for the X-macro tag set. Accepts X / XVEC / XNV. +# XNV ("X No Vec") is structurally identical to X (same 4-tuple shape); +# MuJoCo uses the tag so its own codegen knows to skip the vectorised +# emission path. URLab doesn't care about that distinction — we just want +# the entry shape. Add new tags here whenever MuJoCo introduces one; +# duplicating the list in a sibling regex is the bug class that bit XNV. +_X_TAG_RE = r"X(?:VEC|NV)?" # X-macro entry. Tolerates 4 or 3-tuple forms (pointer vs flat field). # Captures parenthesised contents; field split below trims/normalizes. -_X_ENTRY_RE = re.compile(r"^\s*X(?:VEC)?\s*\(\s*(.*?)\s*\)\s*\\?\s*$") +_X_ENTRY_RE = re.compile(rf"^\s*{_X_TAG_RE}\s*\(\s*(.*?)\s*\)\s*\\?\s*$") def _strip_comments(text: str) -> str: @@ -104,13 +120,7 @@ def _strip_comments(text: str) -> str: return text -def _join_continued_lines(text: str) -> str: - # mjxmacro spreads multi-line macros via backslash continuation; preserve - # individual entries on their own lines for downstream parsing. - return text - - -_BODY_ENTRY_RE = re.compile(r"^\s*(X|XVEC)\s*\(") +_BODY_ENTRY_RE = re.compile(rf"^\s*{_X_TAG_RE}\s*\(") def _parse_block_body(lines: List[str], start_idx: int) -> List[str]: @@ -170,12 +180,16 @@ def _parse_pointer_entry(raw: str) -> Optional[Dict[str, Any]]: def _parse_struct_field_entry(raw: str) -> Optional[Dict[str, Any]]: - """Parse `X(type, name, count)` or `X(name, count)` or `XVEC(...)`. + """Parse `X(type, name, count)` or `X(name, count)` or `X(name)` or `XVEC(...)`. mjxmacro flat-struct blocks have a few shapes: - `X(type, name, count)` (mjOption) - `X(name, count)` (mjStatistic — no type, defaults to mjtNum) - `X(type, name)` (mjVisual fields — no explicit count, treated as scalar) + - `X(name)` (mjVisualQuality/Map/Scale/Rgba — bare field name; type is + whatever the corresponding ``struct mjVisualX`` member is. URLab + defaults to mjtNum since these structs are float/int in practice and + consumers can override via ``field_types``.) - `XVEC(type, name, count)` (vec3 / vec5 / etc.) """ m = _X_ENTRY_RE.match(raw) @@ -193,6 +207,9 @@ def _parse_struct_field_entry(raw: str) -> Optional[Dict[str, Any]]: ctype, name, count = fields[0], fields[1], "1" else: ctype, name, count = "mjtNum", fields[0], fields[1] + elif len(fields) == 1: + # Bare field name — type defaults to mjtNum, scalar. + ctype, name, count = "mjtNum", fields[0], "1" else: return None return { @@ -203,6 +220,24 @@ def _parse_struct_field_entry(raw: str) -> Optional[Dict[str, Any]]: } +# Block names from MuJoCo's X-macro headers that we KNOWINGLY do not +# consume — additions are still flagged at parse time so a new block +# can't disappear silently, but listed names produce no warning. +KNOWN_UNCONSUMED_BLOCKS = { + # Sentinels / size constants — defined as #define X foo without a body. + "MJMODEL_POINTERS_PREAMBLE", + "MJMODEL_POINTERS", # meta-aggregator (re-includes all POINTERS_* blocks) + "MJMODEL_SIZES", # int field counts + "MJMODEL_INTS", + "MJMODEL_INTS_PREAMBLE", + "MJMODEL_INTS_NUMERIC", + "MJMODEL_FLOATS", + "MJDATA_VECTOR", + "MJDATA_SCALAR", + "MJDATA_SCALAR_PREAMBLE", +} + + def parse_mjxmacro(path: str) -> Dict[str, Any]: with open(path, "r", encoding="utf-8") as f: raw_text = f.read() @@ -219,6 +254,12 @@ def parse_mjxmacro(path: str) -> Dict[str, Any]: "struct_fields": {}, } + expected = ( + set(POINTER_BLOCKS_MJMODEL) | set(POINTER_BLOCKS_MJDATA) + | set(STRUCT_FIELD_BLOCKS) | KNOWN_UNCONSUMED_BLOCKS + ) + seen_blocks: set = set() + i = 0 while i < len(lines): line = lines[i] @@ -227,8 +268,27 @@ def parse_mjxmacro(path: str) -> Dict[str, Any]: i += 1 continue block_name = m.group(1) + seen_blocks.add(block_name) # Collect block body — entries on subsequent lines. entries = _parse_block_body(lines, i + 1) + # Defensive sentinel: a non-entry, non-empty line ended body + # collection inside an EXPECTED block. The XNV regression was + # exactly this — surface it so the next new X-tag bumps cause a + # loud warning rather than silently truncating the snapshot. + end_idx = i + 1 + len(entries) + if (block_name in expected and end_idx < len(lines) + and lines[end_idx].strip() + and not _BODY_ENTRY_RE.match(lines[end_idx].strip())): + # If the very next line was also an entry-shaped token we + # missed (i.e. it has parens), warn loudly. + tail = lines[end_idx].strip() + if "(" in tail and tail.endswith(")") or tail.endswith(") \\"): + print( + f"warning: body collector stopped INSIDE block " + f"{block_name} at line {end_idx + 1}: '{tail[:80]}' — " + f"new X-macro tag? Update _X_TAG_RE in this script.", + file=sys.stderr, + ) if block_name in POINTER_BLOCKS_MJMODEL: parsed = [e for e in (_parse_pointer_entry(r) for r in entries) if e] out["mjmodel_pointers"][block_name] = parsed @@ -239,6 +299,29 @@ def parse_mjxmacro(path: str) -> Dict[str, Any]: parsed = [e for e in (_parse_struct_field_entry(r) for r in entries) if e] out["struct_fields"][block_name] = parsed i += 1 + + # New-block tripwire: surface any #define block whose name we have + # never seen before. Catches scenarios like a new + # MJMODEL_POINTERS_PLUGIN_SUB landing upstream — without this, the + # snapshot silently drops the block. + unexpected = { + b for b in seen_blocks + if b not in expected and (b.startswith("MJMODEL_") or + b.startswith("MJDATA_") or + b.startswith("MJOPTION_") or + b.startswith("MJSTATISTIC_") or + b.startswith("MJVISUAL_") or + b.startswith("MJSCOMPILER_") or + b.startswith("MJSPEC_")) + } + if unexpected: + print( + f"warning: parsed {len(unexpected)} unrecognised X-macro " + f"block(s) — add to POINTER_BLOCKS_MJMODEL/MJDATA, " + f"STRUCT_FIELD_BLOCKS, or KNOWN_UNCONSUMED_BLOCKS in this " + f"script: {sorted(unexpected)}", + file=sys.stderr, + ) return out @@ -249,6 +332,32 @@ def main() -> int: print(f"error: mjxmacro.h not found at {src}", file=sys.stderr) return 1 snapshot = parse_mjxmacro(src) + # Track which source each struct-field block came from so a snapshot + # reader can tell mjmodel-side (mjxmacro.h) blocks apart from mjspec-side + # (mjspecmacro.h) blocks without re-parsing the headers. + block_sources: Dict[str, str] = {} + for block_name in snapshot["struct_fields"]: + block_sources[block_name] = snapshot["_meta"]["source"] + # Also fold in the vendored mjspecmacro.h (MJSCOMPILER_FIELDS + + # MJSPEC_FIELDS) — both live in the same ``struct_fields`` dict so + # synthetic_categories rules can reference either by block name. + if os.path.isfile(DEFAULT_MJSPECMACRO): + spec_snapshot = parse_mjxmacro(DEFAULT_MJSPECMACRO) + spec_rel = os.path.relpath(DEFAULT_MJSPECMACRO, PLUGIN_ROOT) + for block_name, entries in spec_snapshot["struct_fields"].items(): + snapshot["struct_fields"][block_name] = entries + block_sources[block_name] = spec_rel + else: + # Loud rather than silent — MJSCOMPILER_FIELDS / MJSPEC_FIELDS + # blocks WILL be missing if the vendored header was removed, and + # that surfaces only as a downstream KeyError much later in + # generate_ue_components.py. + print( + f"warning: vendored mjspecmacro.h not found at {DEFAULT_MJSPECMACRO}; " + f"MJSCOMPILER_FIELDS + MJSPEC_FIELDS will be absent from the snapshot.", + file=sys.stderr, + ) + snapshot["_meta"]["struct_field_sources"] = block_sources # Stats for sanity. total_model = sum(len(v) for v in snapshot["mjmodel_pointers"].values()) total_data = sum(len(v) for v in snapshot["mjdata_pointers"].values()) diff --git a/Scripts/codegen/codegen_rules.json b/Scripts/codegen/codegen_rules.json index c29fa76..12e9909 100644 --- a/Scripts/codegen/codegen_rules.json +++ b/Scripts/codegen/codegen_rules.json @@ -4,22 +4,27 @@ "version": "5.0" }, + "_doc_transform_widget_policy": "Categories whose Pos/Quat are authored via the UE Transform widget (geom/site/camera/frame/inertial) hide the canon Pos/Quat UPROPERTYs from the Details panel. The UPROPERTYs still exist for the import seed + BP read access, but EditConditionHides keeps them out of the user-facing surface so authoring stays in one place. Per-element _note_hidden entries point at this policy instead of restating it.", + "global_exclusions": [ - "user", "name", "class", "type" + "user", "name", "class", "type", "objtype", "reftype" ], "default_type": "float", "_note_property_renames": "Schema attr -> UPROPERTY identifier. Used when the UE-side identifier must differ from the verbatim schema attr (typically to avoid C++ keyword collisions or to keep PascalCase for legacy consumers). qpos/qvel/etc are PascalCase on UMjKeyframe because BP graphs / runtime accessors reference them that way.", "property_renames": { - "qpos": "Qpos", - "qvel": "Qvel", - "act": "Act", - "ctrl": "Ctrl", - "mpos": "Mpos", - "mquat": "Mquat", - "time": "Time" + "qpos": "Qpos", + "qvel": "Qvel", + "act": "Act", + "ctrl": "Ctrl", + "mpos": "Mpos", + "mquat": "Mquat", + "time": "Time", + "actuatorfrclimited": "ActFrcLimited", + "actuatorfrcrange": "ActFrcRange", + "axis": "Axis" }, - "_note_setto_param_defaults": "MuJoCo's mjs_setTo* API treats specific scalar defaults as sentinels. These values are how URLab signals 'not overridden, use MuJoCo's default'. Most use -1.0; a few use 0.0 or 0.01 — encoded here as data, NOT as C++ string literals.", + "_note_setto_param_defaults": "MuJoCo's mjs_setTo* API treats specific scalar defaults as sentinels. These values are how URLab signals 'not overridden, use MuJoCo's default'. Most use -1.0; a few use 0.0 or 0.01. Values are stored as strings because the codegen drops them verbatim into the generated C++ call — typing them as JSON numbers would force a format choice (1 vs 1.0 vs 1.0f) and lose round-trip fidelity.", "setto_param_defaults": { "mjs_setToPosition": {"inheritrange": "0.0"}, "_note_mjs_setToIntVelocity": "intvelocity's mjs_setTo signature accepts a timeconst array param but MuJoCo's XML schema doesn't expose `timeconst` as an MJCF attr on (unlike //). Pin it to the -1.0 sentinel so the setto leaves the type-derived default alone.", @@ -38,6 +43,91 @@ "skin": "Children of . URLab handles skinning via UE skeletal meshes; in MJCF would need a dedicated asset pipeline." }, + "_note_hand_vs_generated_enums": "URLab keeps every EMj*Type enum hand-rolled. Subtype-driving enums (EMjJointType, EMjGeomType, etc.) must stay hand-rolled because each member drives a UClass subclass — adding one is a product decision, not mechanical. Pure-mapping enums (EMjGainType, EMjBiasType, ...) are mechanically codegenable but live next to their parent UClass; moving them to Generated/ would require include reordering for no functional gain. The hand_enum_drift phase in generate_ue_components.py provides the equivalent forward-maintainability guarantee: any new mjt* value upstream surfaces as a diagnostic instead of a silent runtime fallthrough.", + + "_note_compiler_attr_field_map": "MJCF XML attrs URLab honours, mapped to their FMjCompilerSettings field name. The field is hand-rolled in MuJoCo/Utils/MjOrientationUtils.h; the drift check uses this map purely as an allowlist. New MuJoCo compiler flags surface as a diagnostic until added here or to intentionally_unmodeled_compiler_attrs.", + "compiler_attr_field_map": { + "angle": "bAngleInDegrees", + "eulerseq": "EulerSeq", + "meshdir": "MeshDir", + "assetdir": "AssetDir", + "autolimits": "bAutoLimits" + }, + + "_note_intentionally_unmodeled_compiler_attrs": " XML attrs that don't affect URLab's UE-side parsing — physics tuning knobs, compiler-only optimisations, paths URLab supersedes with UE asset routing. Listed explicitly so the compiler-coverage diagnostic stays clean while remaining loud on additions.", + "intentionally_unmodeled_compiler_attrs": [ + "boundmass", "boundinertia", "settotalmass", "balanceinertia", + "strippath", "coordinate", "fitaabb", "discardvisual", + "usethread", "fusestatic", "inertiafromgeom", "inertiagrouprange", + "saveinertial", "texturedir", "alignfree" + ], + + "_note_intentionally_default_typed_attrs": "Attrs that legitimately want default_type ('float') — single scalar floats whose UE shape happens to match the rule fallback. Listed explicitly so the new_attr_typing diagnostic stays clean. Any new MuJoCo XML attr added in a future version that ISN'T a scalar float will surface as a diagnostic.", + "intentionally_default_typed_attrs": [ + "active", "actuatorgravcomp", "area", "armature", "bias", + "cranklength", "cutoff", "dampratio", "density", "diameter", + "force", "fovy", "fpmax", "frictionloss", "fvmax", + "gain", "gap", "gravcomp", "inheritrange", "ipd", + "kp", "kv", "lmax", "lmin", "margin", + "mass", "noise", "output", "radius", "ref", + "resistance", "solmix", "springref", "tausmooth", "torquescale", + "vmax", "width" + ], + + "_note_intentionally_unmapped_mj_enum_values": "MuJoCo enum constants the codegen knowingly does NOT expose as URLab enum members. Silences the hand_enum_drift diagnostic. Two scopes: top-level keys are mjt* enum names whose entries apply to EVERY element using that enum (visualizer-only types, sentinel counts, alternative-class subsumption); '__per_element__' carries per-(element, attr) overrides for cases where the same mjt* enum admits a different subset depending on the host (e.g. rejects mjGEOM_PLANE/HFIELD/MESH but accepts them).", + "intentionally_unmapped_mj_enum_values": { + "mjtGain": ["mjGAIN_DCMOTOR"], + "mjtBias": ["mjBIAS_DCMOTOR"], + "mjtDyn": ["mjDYN_DCMOTOR"], + "mjtGeom": [ + "mjNGEOMTYPES", + "mjGEOM_ARROW", "mjGEOM_ARROW1", "mjGEOM_ARROW2", + "mjGEOM_LINE", "mjGEOM_LINEBOX", "mjGEOM_LABEL", "mjGEOM_TRIANGLE", + "mjGEOM_FLEX", "mjGEOM_SKIN", "mjGEOM_SDF", "mjGEOM_NONE" + ], + "__per_element__": { + "_note_site_type": "Site exposes Mesh + Hfield. Plane stays omitted because a site is a point/extent surface, not an infinite plane; SDF stays omitted because it carries heavy resource data the spawn-surface UX doesn't need.", + "site.type": ["mjGEOM_PLANE"] + } + }, + + "_note_intentionally_unmodeled_mjs_fields": "Per-mjsX-struct list of fields URLab knows about but doesn't model via codegen. Silences the mjsX-field-drift diagnostic. Add entries for fields handled by a different UE component, by canon, or that we deliberately skip.", + "intentionally_unmodeled_mjs_fields": { + "mjsBody": [ + "inertia", "ipos", "ialt", "mass", "iquat", "fullinertia", "alt", + "plugin" + ], + "mjsFrame": [ + "pos", "quat", "childclass", "alt" + ], + "mjsFlex": [ + "solimp", "solmix", "contype", "activelayers", "edgedamping", "elem", + "size", "passive", "condim", "order", "nodebody", + "vertbody", "elemtexcoord", "selfcollide", "poisson", "vert", "margin", + "conaffinity", "damping", "priority", "edgestiffness", "node", + "solref", "gap", "elastic2d", "young", "friction", "thickness", "internal" + ], + "mjsCamera": [ + "intrinsic", "alt" + ], + "mjsGeom": [ + "alt", "plugin" + ], + "mjsSite": [ + "alt" + ], + "mjsActuator": [ + "plugin" + ], + "mjsJoint": [ + "align" + ], + "mjsSensor": [ + "datatype", "dim", "intprm", "needstage", "objname", "plugin", + "refname", "reftype" + ] + }, + "type_mappings": { "axis": "FVector", "dir": "FVector", @@ -59,9 +149,7 @@ "origin": "TArray", "dim": "int32", "rgba": "FLinearColor", - "rgba2": "FLinearColor", "range": "TArray", - "actfrcrange": "TArray", "actuatorfrcrange": "TArray", "ctrlrange": "TArray", "forcerange": "TArray", @@ -80,9 +168,7 @@ "thermal": "TArray", "lugre": "TArray", "stiffness": "TArray", - "stiffnesspoly": "TArray", "damping": "TArray", - "dampingpoly": "TArray", "friction": "TArray", "fullinertia": "TArray", "diaginertia": "TArray", @@ -99,24 +185,18 @@ "biasprm": "TArray", "dynprm": "TArray", "polycoef": "TArray", - "intprm": "TArray", "limited": "bool", "mocap": "bool", "actlimited": "bool", "ctrllimited": "bool", "forcelimited": "bool", "actuatorfrclimited":"bool", - "actgravcomp": "bool", "actearly": "bool", "shellinertia": "bool", - "fitscale": "bool", + "fitscale": "double", "fitaabb": "bool", "discardvisual": "bool", - "needstage": "FString", - "datatype": "FString", - "objtype": "FString", "objname": "FString", - "reftype": "FString", "refname": "FString", "gaintype": "FString", "biastype": "FString", @@ -146,7 +226,6 @@ "file": "FString", "target": "FString", "mode": "FString", - "side": "FString", "anchor": "TArray", "relpose": "TArray", "ctrl": "TArray", @@ -183,18 +262,14 @@ "export_helper": "MjUtils::UEToMjRotation" }, "actuator_transmission": { - "_note": "MJCF actuators encode their transmission via one of {joint, tendon, site, body, jointinparent} (the target name) plus optional {slidersite, refsite}. URLab collapses this to a single EMjActuatorTrnType enum + TargetName/SliderSite/RefSite strings. Codegen emits the parse+write blocks; the UPROPERTY declarations stay hand-side on UMjActuator.", + "_note": "MJCF actuators encode their transmission via one of {joint, tendon, site, body, jointinparent} (the target name) plus optional {slidersite, refsite}. URLab collapses this to a single EMjActuatorTrnType enum + TargetName/SliderSite/RefSite strings. Codegen emits the parse+write blocks inline (no rule-side helper); the UPROPERTY declarations stay hand-side on UMjActuator.", "absorbs_attrs": ["joint", "tendon", "site", "body", "jointinparent", "slidersite", "refsite"], - "emits_property": null, - "import_helper": "(inline)", - "export_helper": "(inline)" + "emits_property": null }, "body_sleep_policy": { - "_note": "MJCF body.sleep is one of {'never','allowed','init'} or absent; mjsBody.sleep is the mjtSleepPolicy enum. URLab exposes EMjBodySleepPolicy SleepPolicy (with a Default entry that means 'let the global option decide'). Codegen emits the string<->enum mapping on both sides; the SleepPolicy UPROPERTY itself stays declared hand-side on UMjBody.", + "_note": "MJCF body.sleep is one of {'never','allowed','init'} or absent; mjsBody.sleep is the mjtSleepPolicy enum. URLab exposes EMjBodySleepPolicy SleepPolicy (with a Default entry that means 'let the global option decide'). Codegen emits the string<->enum mapping on both sides inline (no rule-side helper); the SleepPolicy UPROPERTY itself stays declared hand-side on UMjBody.", "absorbs_attrs": ["sleep"], - "emits_property": null, - "import_helper": "(inline)", - "export_helper": "(inline)" + "emits_property": null }, "fromto_decompose": { "_note": "MJCF's `fromto` is an alternative form for capsule/cylinder/box/ellipsoid (an XY-XY segment). Decompose at import into Pos/Quat plus a half-length scalar written into size[1] (Y slot, e.g. capsule half-length) or size[2] (Z slot, e.g. box half-height) depending on shape Type. The codegen-owned size TArray is grown as needed.", @@ -215,7 +290,7 @@ "element_rules": { "actuator": { "_note_enums": "gaintype/biastype/dyntype are mjtGain/mjtBias/mjtDyn enums on mjsActuator. URLab declares EMjGainType/EMjBiasType/EMjDynType hand-side on UMjActuator; codegen owns the XML<->enum map via xml_enum_attrs. dcmotor 'input' is per-subtype (only on UMjDcMotorActuator) — emitter gates on attr-in-subtype-schema for that case.", - "exclude_attrs": [], + "common_imports": ["class"], "applies_canonicalizations": ["actuator_transmission"], "xml_enum_attrs": { "gaintype": { @@ -223,6 +298,8 @@ "ue_enum_type": "EMjGainType", "mjs_field": "gaintype", "mjs_cast": "mjtGain", + "emit_property_decl": true, + "property_default": "Fixed", "value_map": { "fixed": ["Fixed", "mjGAIN_FIXED"], "affine": ["Affine", "mjGAIN_AFFINE"], @@ -235,6 +312,8 @@ "ue_enum_type": "EMjBiasType", "mjs_field": "biastype", "mjs_cast": "mjtBias", + "emit_property_decl": true, + "property_default": "None", "value_map": { "none": ["None", "mjBIAS_NONE"], "affine": ["Affine", "mjBIAS_AFFINE"], @@ -247,6 +326,8 @@ "ue_enum_type": "EMjDynType", "mjs_field": "dyntype", "mjs_cast": "mjtDyn", + "emit_property_decl": true, + "property_default": "None", "value_map": { "none": ["None", "mjDYN_NONE"], "integrator": ["Integrator", "mjDYN_INTEGRATOR"], @@ -269,13 +350,81 @@ } }, "sensor": { - "exclude_attrs": [] + "_note": "Sensor reads its target name from one of several xor attrs depending on subtype (site for touch/accel/gyro, joint for jointpos, etc.). target_collations collapses them into UE FString TargetName. ReferenceName is direct from 'refname'. ObjType / RefType are EMjObjType enums with their own string<->enum mapping (xml_enum_attrs).", + "common_imports": ["class"], + "target_collations": { + "TargetName": { + "mjs_field": "objname", + "absorbs_attrs": ["site", "joint", "tendon", "actuator", "body", "geom", "objname", "camera", "mesh"] + }, + "ReferenceName": { + "mjs_field": "refname", + "absorbs_attrs": ["refname"] + } + }, + "xml_enum_attrs": { + "objtype": { + "ue_property": "ObjType", + "ue_enum_type": "EMjObjType", + "has_override_toggle": false, + "value_map": { + "body": ["Body", "mjOBJ_BODY"], + "xbody": ["XBody", "mjOBJ_XBODY"], + "joint": ["Joint", "mjOBJ_JOINT"], + "dof": ["DoF", "mjOBJ_DOF"], + "geom": ["Geom", "mjOBJ_GEOM"], + "site": ["Site", "mjOBJ_SITE"], + "camera": ["Camera", "mjOBJ_CAMERA"], + "light": ["Light", "mjOBJ_LIGHT"], + "mesh": ["Mesh", "mjOBJ_MESH"], + "hfield": ["HField", "mjOBJ_HFIELD"], + "texture": ["Texture", "mjOBJ_TEXTURE"], + "material": ["Material", "mjOBJ_MATERIAL"], + "pair": ["Pair", "mjOBJ_PAIR"], + "exclude": ["Exclude", "mjOBJ_EXCLUDE"], + "equality": ["Equality", "mjOBJ_EQUALITY"], + "tendon": ["Tendon", "mjOBJ_TENDON"], + "actuator": ["Actuator", "mjOBJ_ACTUATOR"] + } + }, + "reftype": { + "ue_property": "RefType", + "ue_enum_type": "EMjObjType", + "has_override_toggle": false, + "value_map": { + "body": ["Body", "mjOBJ_BODY"], + "xbody": ["XBody", "mjOBJ_XBODY"], + "joint": ["Joint", "mjOBJ_JOINT"], + "geom": ["Geom", "mjOBJ_GEOM"], + "site": ["Site", "mjOBJ_SITE"], + "camera": ["Camera", "mjOBJ_CAMERA"] + } + } + } }, "joint": { - "exclude_attrs": ["pos", "axis"], - "extra_property_inits": { - "Pos": "FVector::ZeroVector", - "Axis": "FVector(0.0f, 0.0f, 1.0f)" + "_note_axis_pos": "axis: MuJoCo direction vector with opposite Y handedness vs UE; vec3_convert.axis = y_negate flips on import + export. pos: spatial_pose canon emits the Pos UPROPERTY pair + drives SetRelativeLocation on import.", + "common_imports": ["class"], + "applies_canonicalizations": ["spatial_pose"], + "vec3_convert": {"axis": "y_negate"}, + "property_defaults": {"axis": "FVector(0.0f, 0.0f, 1.0f)"}, + "_note_hidden": "Pos is the joint anchor offset — derived from the UE component's RelativeLocation. Axis stays visible as a direction (not a position) and is the user-authored joint hinge direction.", + "hidden_canon_properties": ["spatial_pose"], + "_note_property_meta": "Joint fields whose unit semantics shift with the joint Type get a tooltip that spells out the per-type interpretation, so a user reading the Details panel knows whether the number is metres or degrees. UE's Units meta is intentionally NOT used here — a static label would be wrong for the other Type.", + "property_meta": { + "axis": "ToolTip=\"Joint axis in the parent body's local frame. Hinge: rotation axis. Slide: translation direction. Ignored for Ball and Free.\"", + "range": "ToolTip=\"Joint position bounds [min, max]. Hinge/Ball: degrees. Slide: centimetres. Ignored when 'limited' is false.\"", + "ref": "ToolTip=\"Reference (zero) position. Hinge/Ball: degrees. Slide: centimetres.\"", + "springref": "ToolTip=\"Equilibrium position for the joint spring. Hinge/Ball: degrees. Slide: centimetres.\"", + "stiffness": "ToolTip=\"Per-axis spring stiffness. Hinge/Ball: N·m/rad. Slide: N/m.\"", + "damping": "ToolTip=\"Per-axis damping. Hinge/Ball: N·m·s/rad. Slide: N·s/m.\"", + "springdamper": "ToolTip=\"Compact spring spec [stiffness, damping]; populated when MJCF used . Overrides stiffness + damping when set.\"", + "armature": "ToolTip=\"Added rotor inertia for hinges (kg·m²) or added mass for slides (kg). Models reflected inertia of the actuator.\"", + "frictionloss": "ToolTip=\"Dry-friction loss. Hinge/Ball: N·m. Slide: N.\"", + "actuatorgravcomp": "ToolTip=\"Gravity compensation factor passed to actuators on this joint. 0 = no compensation, 1 = full gravity cancelled.\"", + "actuatorfrcrange": "ToolTip=\"Actuator force bounds [min, max] when 'ActFrcLimited' is true. Hinge/Ball: N·m. Slide: N.\"", + "margin": "ToolTip=\"Contact-detection margin (m). Joints inherit this when computing limit constraints.\"", + "group": "ToolTip=\"Visualisation group 0–5. MuJoCo viewer uses this to toggle visibility.\"" }, "xml_enum_attrs": { "type": { @@ -315,12 +464,20 @@ }, "geom": { "_note": "size is codegen-owned TArray; fromto-decomposed half-length is written into size[1]/[2] by the canon. material is codegen-owned for IMPORT (FString -> UE material lookup) but SKIPPED on export because URLab handles materials as UE assets and does not register them in the mjsSpec (mjs_setString on Element->material would reference a non-existent spec entry and fail mj_compile). Orientation cluster absorbed by `orientation`; fromto absorbed by `fromto_decompose`. type is an URLab enum (EMjGeomType); codegen owns the XML<->enum string map via xml_enum_attrs.", - "exclude_attrs": [], + "common_imports": ["class"], "_note_hfield": "hfield references URLab's own hfield actor system, not a mjsHField spec entry. Codegen still imports the string for editor visibility but skips the spec write to avoid 'hfield not found' on compile.", "export_skip_attrs": ["material", "hfield"], "applies_canonicalizations": ["spatial_pose", "orientation", "fromto_decompose"], "_note_sentinel": "fromto-only XML inputs leave the radius slot unset; the canon writes -1.0f as the sentinel and the per-attr size export skips those slots so the parent default's radius is preserved.", "sentinel_skip_export": {"size": "-1.0f"}, + "_note_property_units": "Scalar lengths exposed in mjsGeom carry meta=(Units=\"m\") so the editor shows a 'm' suffix or auto-converts to cm/mm when 'Display Units' is enabled. Storage stays raw MJ metres; export path unaffected. size is hidden (Scale3D is canonical) — see hidden_attrs.", + "property_units": { + "margin": "m", + "gap": "m" + }, + "_note_hidden": "See _doc_transform_widget_policy. size is hidden too — Scale3D is canonical.", + "hidden_canon_properties": ["spatial_pose", "orientation"], + "hidden_attrs": ["size"], "_note_attr_to_mjs_field": "MuJoCo renames fluidcoef -> fluid_coefs on the mjsGeom struct. shellinertia and fluidshape are handled by xml_enum_attrs below (they need string<->enum + field-rename together).", "attr_to_mjs_field": { "fluidcoef": "fluid_coefs" @@ -369,10 +526,12 @@ }, "site": { "_note": "Same as geom: size codegen-owned TArray; material codegen-owned for IMPORT but export-skipped (UE-side materials); orientation + fromto canonicalized. mjsSite.type uses mjtGeom (sites are visual 'geoms'). Site has no bOverride_Type — Type always carries a value (default Sphere).", - "exclude_attrs": [], "export_skip_attrs": ["material"], "applies_canonicalizations": ["spatial_pose", "orientation", "fromto_decompose"], "sentinel_skip_export": {"size": "-1.0f"}, + "_note_hidden": "See _doc_transform_widget_policy. size hidden too — Scale3D is canonical.", + "hidden_canon_properties": ["spatial_pose", "orientation"], + "hidden_attrs": ["size"], "xml_enum_attrs": { "type": { "ue_property": "Type", @@ -385,15 +544,21 @@ "capsule": ["Capsule", "mjGEOM_CAPSULE"], "ellipsoid": ["Ellipsoid", "mjGEOM_ELLIPSOID"], "cylinder": ["Cylinder", "mjGEOM_CYLINDER"], - "box": ["Box", "mjGEOM_BOX"] + "box": ["Box", "mjGEOM_BOX"], + "mesh": ["Mesh", "mjGEOM_MESH"], + "hfield": ["Hfield", "mjGEOM_HFIELD"] } } } }, "tendon": { + "common_imports": ["class"], "_note_material": "material codegen-owned for IMPORT but export-skipped — URLab handles materials as UE assets, not mjsMaterial spec entries.", - "exclude_attrs": [], - "export_skip_attrs": ["material"] + "export_skip_attrs": ["material"], + "_note_property_units": "springlength is unambiguously a length in metres. range is intentionally NOT tagged — it can be a length (slide-mode tendon) or an angle (rare hinge-coupled tendon) and labelling it with one unit would be wrong as often as right.", + "property_units": { + "springlength": "m" + } }, "equality": { "_note_target_collation": "MJCF equality elements address one or two of {body, site, joint, tendon, flex} per the equality kind. URLab collapses to FString Obj1/Obj2 (hand-declared UPROPERTYs with dynamic GetOptions based on EqualityType). Excluded from codegen so they don't appear as separate UPROPERTYs; target_collations rule emits the import collation + mjs_setString export. site1/site2 stay as their own UPROPERTYs (codegen-owned) so the objtype switch in ExportTo can detect site-mode connects/welds and pick mjOBJ_SITE.", @@ -416,6 +581,10 @@ "import_op": "m_to_cm"} ] }, + "_note_property_units": "anchor is stored in UE centimetres (post unit_conversion). Tagging the field with Units=\"cm\" so the editor shows the suffix that matches the actual stored value — no auto-conversion needed.", + "property_units": { + "anchor": "cm" + }, "mjs_data_packed_attrs": { "anchor": { "slot_range": [0, 3], @@ -439,14 +608,25 @@ }, "camera": { "_note": "MJCF camera.mode is a tracking mode (mjtCamLight subset). URLab declares EMjCameraTrackingMode hand-side; codegen owns the XML<->enum map. NOT to be confused with URLab's EMjCameraMode which is a UE-side render-mode selector (RGB/Depth/Segmentation).", - "exclude_attrs": [], + "_note_common_imports": "Camera also reads name; the hand-written ImportFromXml has a fallback `if MjName empty -> 'Camera'` that runs AFTER this read.", + "common_imports": ["name"], "applies_canonicalizations": ["spatial_pose", "orientation"], + "_note_hidden": "See _doc_transform_widget_policy. Intrinsics (fovy, ipd, focal, etc.) stay visible.", + "hidden_canon_properties": ["spatial_pose", "orientation"], "_note_attr_to_mjs_field": "MuJoCo renames a handful of camera attrs between the XML schema and the mjsCamera struct: target -> targetbody (mjString*), projection -> proj (mjtProjection enum), focal -> focal_length, principal -> principal_length. sensorsize auto-resolves to sensor_size via the underscore-normalise heuristic. Without this map the auto-resolver in _resolve_mjs_field can't bridge target/focal/principal and they were silently dropped on export.", "attr_to_mjs_field": { "target": "targetbody", "focal": "focal_length", "principal": "principal_length" }, + "_note_property_units": "Camera lengths (ipd, focal, principal, sensorsize) stay in raw MJ metres on the UE side; tagging them with Units=\"m\" gives the editor a suffix and lets Display Units convert to mm/cm. fovy is degrees per the MJCF spec. focalpixel / principalpixel are pixel counts (not lengths) and are intentionally untagged.", + "property_units": { + "ipd": "m", + "focal": "m", + "principal": "m", + "sensorsize": "m", + "fovy": "deg" + }, "xml_enum_attrs": { "mode": { "ue_property": "TrackingMode", @@ -474,32 +654,39 @@ } }, "body": { - "exclude_attrs": [], + "common_imports": ["name"], "applies_canonicalizations": ["spatial_pose", "orientation", "body_sleep_policy"], "_note_canon_export_skip": "Body's pos/quat are written by MjSpecWrapper::CreateBody from the UE component transform (the source of truth for body placement). The codegen-emitted spatial_pose/orientation export would overwrite those with the Pos/Quat UPROPERTYs, which are stale for any body not freshly imported from XML. Skip the export side for these two canons.", "canon_export_skip": ["spatial_pose", "orientation"], + "_note_hidden": "See _doc_transform_widget_policy. canon_export_skip routes the write through the UE transform.", + "hidden_canon_properties": ["spatial_pose", "orientation"], "property_meta": { "mocap": "DisplayName=\"Driven By Unreal\"", "childclass": "GetOptions=\"GetChildClassOptions\"" } }, "inertial": { - "exclude_attrs": [], - "applies_canonicalizations": ["spatial_pose", "orientation"] + "applies_canonicalizations": ["spatial_pose", "orientation"], + "_note_hidden": "See _doc_transform_widget_policy. UMjInertial::RegisterToSpec (hand-rolled) writes ParentBody->ipos/iquat from the UE transform.", + "hidden_canon_properties": ["spatial_pose", "orientation"] }, "frame": { "_note": "Like body: the UE component transform is the source of truth for placement. Codegen imports XML pos/quat into Pos/Quat UPROPERTYs (UE units / UE frame) and the cpp drives SetRelativeLocation/SetRelativeRotation from them. Spec export is skipped for the canon Pos/Quat because MjSpecWrapper::CreateFrame writes pos/quat from the UE transform.", - "exclude_attrs": [], "applies_canonicalizations": ["spatial_pose", "orientation"], - "canon_export_skip": ["spatial_pose", "orientation"] + "canon_export_skip": ["spatial_pose", "orientation"], + "hidden_canon_properties": ["spatial_pose", "orientation"] }, "flexcomp": { "_note": "Flexcomp doesn't register via mjs_addX — at spec time UMjFlexcomp builds a tiny standalone MJCF fragment and re-parses it via mj_parseXMLString + mjs_attach (the flexcomp macro is expanded by MuJoCo's XML parser, not the spec API). Codegen still owns the UPROPERTY surface so new MJCF attrs auto-appear; BuildFlexcompXml in MjFlexcomp.cpp reads from those codegen-owned fields. Sub-elements (///) remain hand-rolled because the codegen doesn't have per-sub-element UPROPERTY support yet.", "_note_material": "material codegen-owned for IMPORT but export-skipped — URLab handles materials as UE assets, not mjsMaterial spec entries.", - "exclude_attrs": [], "export_skip_attrs": ["material"], "applies_canonicalizations": ["spatial_pose", "orientation"], "canon_export_skip": ["spatial_pose", "orientation"], + "hidden_canon_properties": ["spatial_pose", "orientation"], + "property_units": { + "radius": "m", + "spacing": "m" + }, "xml_enum_attrs": { "type": { "ue_property": "FlexcompType", @@ -535,17 +722,19 @@ } }, "freejoint": { - "exclude_attrs": [] }, "contact_pair": { - "exclude_attrs": [] + "common_imports": [{"attr": "name", "ue_field": "Name"}], + "property_units": { + "margin": "m", + "gap": "m" + } }, "contact_exclude": { - "exclude_attrs": [] + "common_imports": [{"attr": "name", "ue_field": "Name"}] }, "keyframe": { "_note": "qpos/qvel/act/ctrl/mpos/mquat target mjsKey's mjDoubleVec* fields (std::vector*) — require ->clear()+->push_back() rather than direct assignment. Codegen emits the import (TArray read) + the mjs_double_vec-style export. RegisterToSpec hand-rolls freejoint-padding for qpos/qvel.", - "exclude_attrs": [], "mjs_double_vec_attrs": ["qpos", "qvel", "act", "ctrl", "mpos", "mquat"] } }, @@ -574,7 +763,7 @@ {"key": "adhesion", "enum_value": "Adhesion", "class_name": "UMjAdhesionActuator", "header": "MjAdhesionActuator.h"}, {"key": "dcmotor", "enum_value": "DcMotor", "class_name": "UMjDcMotorActuator", "header": "MjDcMotorActuator.h"} ], - "_note_subtype_setto": "Codegen-driven mjs_setTo* call config. Function signatures are scraped into Scripts/mjspec_snapshot.json by build_mjspec_snapshot.py; the generator emits the call from the signature + the per-subtype config below. NO hand-written C++ literals in this file.", + "_note_subtype_setto": "Codegen-driven mjs_setTo* call config. Function signatures come from the clang-AST introspect snapshot, projected by _mjspec_from_introspect; the generator emits the call from the signature + the per-subtype config below. NO hand-written C++ literals in this file.", "subtype_setto": { "general": null, "motor": {"call": "mjs_setToMotor"}, @@ -604,55 +793,57 @@ "schema_subtypes_block": "sensor_types", "type_enum_name": "EMjSensorType", "subtypes": [ - {"key": "touch", "enum_value": "Touch", "class_name": "UMjTouchSensor", "header": "MjTouchSensor.h"}, - {"key": "accelerometer", "enum_value": "Accelerometer", "class_name": "UMjAccelerometer", "header": "MjAccelerometer.h"}, - {"key": "velocimeter", "enum_value": "Velocimeter", "class_name": "UMjVelocimeter", "header": "MjVelocimeter.h"}, - {"key": "gyro", "enum_value": "Gyro", "class_name": "UMjGyro", "header": "MjGyro.h"}, - {"key": "force", "enum_value": "Force", "class_name": "UMjForceSensor", "header": "MjForceSensor.h"}, - {"key": "torque", "enum_value": "Torque", "class_name": "UMjTorqueSensor", "header": "MjTorqueSensor.h"}, - {"key": "magnetometer", "enum_value": "Magnetometer", "class_name": "UMjMagnetometer", "header": "MjMagnetometer.h"}, - {"key": "camprojection", "enum_value": "CamProjection", "class_name": "UMjCamProjectionSensor", "header": "MjCamProjectionSensor.h"}, - {"key": "rangefinder", "enum_value": "RangeFinder", "class_name": "UMjRangeFinderSensor", "header": "MjRangeFinderSensor.h"}, + {"key": "touch", "enum_value": "Touch", "class_name": "UMjTouchSensor", "header": "MjTouchSensor.h", "fully_emitted": true}, + {"key": "accelerometer", "enum_value": "Accelerometer", "class_name": "UMjAccelerometer", "header": "MjAccelerometer.h", "fully_emitted": true}, + {"key": "velocimeter", "enum_value": "Velocimeter", "class_name": "UMjVelocimeter", "header": "MjVelocimeter.h", "fully_emitted": true}, + {"key": "gyro", "enum_value": "Gyro", "class_name": "UMjGyro", "header": "MjGyro.h", "fully_emitted": true}, + {"key": "force", "enum_value": "Force", "class_name": "UMjForceSensor", "header": "MjForceSensor.h", "fully_emitted": true}, + {"key": "torque", "enum_value": "Torque", "class_name": "UMjTorqueSensor", "header": "MjTorqueSensor.h", "fully_emitted": true}, + {"key": "magnetometer", "enum_value": "Magnetometer", "class_name": "UMjMagnetometer", "header": "MjMagnetometer.h", "fully_emitted": true}, + {"key": "camprojection", "enum_value": "CamProjection", "class_name": "UMjCamProjectionSensor", "header": "MjCamProjectionSensor.h", "fully_emitted": true}, + {"key": "rangefinder", "enum_value": "RangeFinder", "class_name": "UMjRangeFinderSensor", "header": "MjRangeFinderSensor.h", + "case_body_override": "Element->type = mjSENS_RANGEFINDER; Element->objtype = (ObjType == EMjObjType::Camera) ? mjOBJ_CAMERA : mjOBJ_SITE;", + "fully_emitted": true}, {"key": "jointpos", "enum_value": "JointPos", "class_name": "UMjJointPosSensor", "header": "MjJointPosSensor.h"}, - {"key": "jointvel", "enum_value": "JointVel", "class_name": "UMjJointVelSensor", "header": "MjJointVelSensor.h"}, - {"key": "ballquat", "enum_value": "BallQuat", "class_name": "UMjBallQuatSensor", "header": "MjBallQuatSensor.h"}, - {"key": "ballangvel", "enum_value": "BallAngVel", "class_name": "UMjBallAngVelSensor", "header": "MjBallAngVelSensor.h"}, - {"key": "jointlimitpos", "enum_value": "JointLimitPos", "class_name": "UMjJointLimitPosSensor", "header": "MjJointLimitPosSensor.h"}, - {"key": "jointlimitvel", "enum_value": "JointLimitVel", "class_name": "UMjJointLimitVelSensor", "header": "MjJointLimitVelSensor.h"}, - {"key": "jointlimitfrc", "enum_value": "JointLimitFrc", "class_name": "UMjJointLimitFrcSensor", "header": "MjJointLimitFrcSensor.h"}, - {"key": "tendonpos", "enum_value": "TendonPos", "class_name": "UMjTendonPosSensor", "header": "MjTendonPosSensor.h"}, - {"key": "tendonvel", "enum_value": "TendonVel", "class_name": "UMjTendonVelSensor", "header": "MjTendonVelSensor.h"}, - {"key": "tendonlimitpos", "enum_value": "TendonLimitPos", "class_name": "UMjTendonLimitPosSensor", "header": "MjTendonLimitPosSensor.h"}, - {"key": "tendonlimitvel", "enum_value": "TendonLimitVel", "class_name": "UMjTendonLimitVelSensor", "header": "MjTendonLimitVelSensor.h"}, - {"key": "tendonlimitfrc", "enum_value": "TendonLimitFrc", "class_name": "UMjTendonLimitFrcSensor", "header": "MjTendonLimitFrcSensor.h"}, - {"key": "actuatorpos", "enum_value": "ActuatorPos", "class_name": "UMjActuatorPosSensor", "header": "MjActuatorPosSensor.h"}, - {"key": "actuatorvel", "enum_value": "ActuatorVel", "class_name": "UMjActuatorVelSensor", "header": "MjActuatorVelSensor.h"}, - {"key": "actuatorfrc", "enum_value": "ActuatorFrc", "class_name": "UMjActuatorFrcSensor", "header": "MjActuatorFrcSensor.h"}, - {"key": "jointactuatorfrc", "enum_value": "JointActFrc", "class_name": "UMjJointActFrcSensor", "header": "MjJointActFrcSensor.h"}, - {"key": "tendonactuatorfrc","enum_value": "TendonActFrc", "class_name": "UMjTendonActFrcSensor", "header": "MjTendonActFrcSensor.h"}, - {"key": "framepos", "enum_value": "FramePos", "class_name": "UMjFramePosSensor", "header": "MjFramePosSensor.h"}, - {"key": "framequat", "enum_value": "FrameQuat", "class_name": "UMjFrameQuatSensor", "header": "MjFrameQuatSensor.h"}, - {"key": "framexaxis", "enum_value": "FrameXAxis", "class_name": "UMjFrameXAxisSensor", "header": "MjFrameXAxisSensor.h"}, - {"key": "frameyaxis", "enum_value": "FrameYAxis", "class_name": "UMjFrameYAxisSensor", "header": "MjFrameYAxisSensor.h"}, - {"key": "framezaxis", "enum_value": "FrameZAxis", "class_name": "UMjFrameZAxisSensor", "header": "MjFrameZAxisSensor.h"}, - {"key": "framelinvel", "enum_value": "FrameLinVel", "class_name": "UMjFrameLinVelSensor", "header": "MjFrameLinVelSensor.h"}, - {"key": "frameangvel", "enum_value": "FrameAngVel", "class_name": "UMjFrameAngVelSensor", "header": "MjFrameAngVelSensor.h"}, - {"key": "framelinacc", "enum_value": "FrameLinAcc", "class_name": "UMjFrameLinAccSensor", "header": "MjFrameLinAccSensor.h"}, - {"key": "frameangacc", "enum_value": "FrameAngAcc", "class_name": "UMjFrameAngAccSensor", "header": "MjFrameAngAccSensor.h"}, - {"key": "subtreecom", "enum_value": "SubtreeCom", "class_name": "UMjSubtreeComSensor", "header": "MjSubtreeComSensor.h"}, - {"key": "subtreelinvel", "enum_value": "SubtreeLinVel", "class_name": "UMjSubtreeLinVelSensor", "header": "MjSubtreeLinVelSensor.h"}, - {"key": "subtreeangmom", "enum_value": "SubtreeAngMom", "class_name": "UMjSubtreeAngMomSensor", "header": "MjSubtreeAngMomSensor.h"}, - {"key": "insidesite", "enum_value": "InsideSite", "class_name": "UMjInsideSiteSensor", "header": "MjInsideSiteSensor.h"}, - {"key": "distance", "enum_value": "GeomDist", "class_name": "UMjGeomDistSensor", "header": "MjGeomDistSensor.h"}, - {"key": "normal", "enum_value": "GeomNormal", "class_name": "UMjGeomNormalSensor", "header": "MjGeomNormalSensor.h"}, - {"key": "fromto", "enum_value": "GeomFromTo", "class_name": "UMjGeomFromToSensor", "header": "MjGeomFromToSensor.h"}, - {"key": "contact", "enum_value": "Contact", "class_name": "UMjContactSensor", "header": "MjContactSensor.h"}, - {"key": "e_potential", "enum_value": "EPotential", "class_name": "UMjEPotentialSensor", "header": "MjEPotentialSensor.h"}, - {"key": "e_kinetic", "enum_value": "EKinetic", "class_name": "UMjEKineticSensor", "header": "MjEKineticSensor.h"}, - {"key": "clock", "enum_value": "Clock", "class_name": "UMjClockSensor", "header": "MjClockSensor.h"}, + {"key": "jointvel", "enum_value": "JointVel", "class_name": "UMjJointVelSensor", "header": "MjJointVelSensor.h", "fully_emitted": true}, + {"key": "ballquat", "enum_value": "BallQuat", "class_name": "UMjBallQuatSensor", "header": "MjBallQuatSensor.h", "fully_emitted": true}, + {"key": "ballangvel", "enum_value": "BallAngVel", "class_name": "UMjBallAngVelSensor", "header": "MjBallAngVelSensor.h", "fully_emitted": true}, + {"key": "jointlimitpos", "enum_value": "JointLimitPos", "class_name": "UMjJointLimitPosSensor", "header": "MjJointLimitPosSensor.h", "fully_emitted": true}, + {"key": "jointlimitvel", "enum_value": "JointLimitVel", "class_name": "UMjJointLimitVelSensor", "header": "MjJointLimitVelSensor.h", "fully_emitted": true}, + {"key": "jointlimitfrc", "enum_value": "JointLimitFrc", "class_name": "UMjJointLimitFrcSensor", "header": "MjJointLimitFrcSensor.h", "fully_emitted": true}, + {"key": "tendonpos", "enum_value": "TendonPos", "class_name": "UMjTendonPosSensor", "header": "MjTendonPosSensor.h", "fully_emitted": true}, + {"key": "tendonvel", "enum_value": "TendonVel", "class_name": "UMjTendonVelSensor", "header": "MjTendonVelSensor.h", "fully_emitted": true}, + {"key": "tendonlimitpos", "enum_value": "TendonLimitPos", "class_name": "UMjTendonLimitPosSensor", "header": "MjTendonLimitPosSensor.h", "fully_emitted": true}, + {"key": "tendonlimitvel", "enum_value": "TendonLimitVel", "class_name": "UMjTendonLimitVelSensor", "header": "MjTendonLimitVelSensor.h", "fully_emitted": true}, + {"key": "tendonlimitfrc", "enum_value": "TendonLimitFrc", "class_name": "UMjTendonLimitFrcSensor", "header": "MjTendonLimitFrcSensor.h", "fully_emitted": true}, + {"key": "actuatorpos", "enum_value": "ActuatorPos", "class_name": "UMjActuatorPosSensor", "header": "MjActuatorPosSensor.h", "fully_emitted": true}, + {"key": "actuatorvel", "enum_value": "ActuatorVel", "class_name": "UMjActuatorVelSensor", "header": "MjActuatorVelSensor.h", "fully_emitted": true}, + {"key": "actuatorfrc", "enum_value": "ActuatorFrc", "class_name": "UMjActuatorFrcSensor", "header": "MjActuatorFrcSensor.h", "fully_emitted": true}, + {"key": "jointactuatorfrc", "enum_value": "JointActFrc", "class_name": "UMjJointActFrcSensor", "header": "MjJointActFrcSensor.h", "fully_emitted": true}, + {"key": "tendonactuatorfrc","enum_value": "TendonActFrc", "class_name": "UMjTendonActFrcSensor", "header": "MjTendonActFrcSensor.h", "fully_emitted": true}, + {"key": "framepos", "enum_value": "FramePos", "class_name": "UMjFramePosSensor", "header": "MjFramePosSensor.h", "fully_emitted": true}, + {"key": "framequat", "enum_value": "FrameQuat", "class_name": "UMjFrameQuatSensor", "header": "MjFrameQuatSensor.h", "fully_emitted": true}, + {"key": "framexaxis", "enum_value": "FrameXAxis", "class_name": "UMjFrameXAxisSensor", "header": "MjFrameXAxisSensor.h", "fully_emitted": true}, + {"key": "frameyaxis", "enum_value": "FrameYAxis", "class_name": "UMjFrameYAxisSensor", "header": "MjFrameYAxisSensor.h", "fully_emitted": true}, + {"key": "framezaxis", "enum_value": "FrameZAxis", "class_name": "UMjFrameZAxisSensor", "header": "MjFrameZAxisSensor.h", "fully_emitted": true}, + {"key": "framelinvel", "enum_value": "FrameLinVel", "class_name": "UMjFrameLinVelSensor", "header": "MjFrameLinVelSensor.h", "fully_emitted": true}, + {"key": "frameangvel", "enum_value": "FrameAngVel", "class_name": "UMjFrameAngVelSensor", "header": "MjFrameAngVelSensor.h", "fully_emitted": true}, + {"key": "framelinacc", "enum_value": "FrameLinAcc", "class_name": "UMjFrameLinAccSensor", "header": "MjFrameLinAccSensor.h", "fully_emitted": true}, + {"key": "frameangacc", "enum_value": "FrameAngAcc", "class_name": "UMjFrameAngAccSensor", "header": "MjFrameAngAccSensor.h", "fully_emitted": true}, + {"key": "subtreecom", "enum_value": "SubtreeCom", "class_name": "UMjSubtreeComSensor", "header": "MjSubtreeComSensor.h", "fully_emitted": true}, + {"key": "subtreelinvel", "enum_value": "SubtreeLinVel", "class_name": "UMjSubtreeLinVelSensor", "header": "MjSubtreeLinVelSensor.h", "fully_emitted": true}, + {"key": "subtreeangmom", "enum_value": "SubtreeAngMom", "class_name": "UMjSubtreeAngMomSensor", "header": "MjSubtreeAngMomSensor.h", "fully_emitted": true}, + {"key": "insidesite", "enum_value": "InsideSite", "class_name": "UMjInsideSiteSensor", "header": "MjInsideSiteSensor.h", "fully_emitted": true}, + {"key": "distance", "enum_value": "GeomDist", "class_name": "UMjGeomDistSensor", "header": "MjGeomDistSensor.h", "fully_emitted": true}, + {"key": "normal", "enum_value": "GeomNormal", "class_name": "UMjGeomNormalSensor", "header": "MjGeomNormalSensor.h", "fully_emitted": true}, + {"key": "fromto", "enum_value": "GeomFromTo", "class_name": "UMjGeomFromToSensor", "header": "MjGeomFromToSensor.h", "fully_emitted": true}, + {"key": "contact", "enum_value": "Contact", "class_name": "UMjContactSensor", "header": "MjContactSensor.h", "fully_emitted": true}, + {"key": "e_potential", "enum_value": "EPotential", "class_name": "UMjEPotentialSensor", "header": "MjEPotentialSensor.h", "fully_emitted": true}, + {"key": "e_kinetic", "enum_value": "EKinetic", "class_name": "UMjEKineticSensor", "header": "MjEKineticSensor.h", "fully_emitted": true}, + {"key": "clock", "enum_value": "Clock", "class_name": "UMjClockSensor", "header": "MjClockSensor.h", "fully_emitted": true}, {"key": "tactile", "enum_value": "Tactile", "class_name": "UMjTactileSensor", "header": "MjTactileSensor.h"}, - {"key": "user", "enum_value": "User", "class_name": "UMjUserSensor", "header": "MjUserSensor.h"}, - {"key": "plugin", "enum_value": "Plugin", "class_name": "UMjPluginSensor", "header": "MjPluginSensor.h"} + {"key": "user", "enum_value": "User", "class_name": "UMjUserSensor", "header": "MjUserSensor.h", "fully_emitted": true}, + {"key": "plugin", "enum_value": "Plugin", "class_name": "UMjPluginSensor", "header": "MjPluginSensor.h", "fully_emitted": true} ] }, @@ -666,9 +857,13 @@ "schema_common_block": "joint.attrs", "type_enum_name": "EMjJointType", "subtypes": [ - {"key": "hinge", "enum_value": "Hinge", "class_name": "UMjHingeJoint", "header": "MjHingeJoint.h"}, - {"key": "slide", "enum_value": "Slide", "class_name": "UMjSlideJoint", "header": "MjSlideJoint.h"}, - {"key": "ball", "enum_value": "Ball", "class_name": "UMjBallJoint", "header": "MjBallJoint.h"}, + {"key": "hinge", "enum_value": "Hinge", "class_name": "UMjHingeJoint", "header": "MjHingeJoint.h", "fully_emitted": true, + "_note_extra_ctor": "UMjJoint::ExportTo only writes Element->type when bOverride_Type is true. Without this flag set in the subclass ctor, BP-spawned joints fall back to the mjsJoint default (mjJNT_HINGE), silently substituting Ball/Slide joints for Hinge.", + "extra_constructor": "bOverride_Type = true;"}, + {"key": "slide", "enum_value": "Slide", "class_name": "UMjSlideJoint", "header": "MjSlideJoint.h", "fully_emitted": true, + "extra_constructor": "bOverride_Type = true;"}, + {"key": "ball", "enum_value": "Ball", "class_name": "UMjBallJoint", "header": "MjBallJoint.h", "fully_emitted": true, + "extra_constructor": "bOverride_Type = true;"}, {"key": "free", "enum_value": "Free", "class_name": "UMjFreeJoint", "header": "MjFreeJoint.h"} ] }, @@ -681,11 +876,11 @@ "schema_common_block": "site.attrs", "type_enum_name": "EMjSiteType", "subtypes": [ - {"key": "box", "enum_value": "Box", "class_name": "UMjBoxSite", "display_name": "MuJoCo Box Site"}, - {"key": "sphere", "enum_value": "Sphere", "class_name": "UMjSphereSite", "display_name": "MuJoCo Sphere Site"}, - {"key": "capsule", "enum_value": "Capsule", "class_name": "UMjCapsuleSite", "display_name": "MuJoCo Capsule Site"}, - {"key": "cylinder", "enum_value": "Cylinder", "class_name": "UMjCylinderSite", "display_name": "MuJoCo Cylinder Site"}, - {"key": "ellipsoid", "enum_value": "Ellipsoid", "class_name": "UMjEllipsoidSite", "display_name": "MuJoCo Ellipsoid Site"} + {"key": "box", "enum_value": "Box", "class_name": "UMjBoxSite"}, + {"key": "sphere", "enum_value": "Sphere", "class_name": "UMjSphereSite"}, + {"key": "capsule", "enum_value": "Capsule", "class_name": "UMjCapsuleSite"}, + {"key": "cylinder", "enum_value": "Cylinder", "class_name": "UMjCylinderSite"}, + {"key": "ellipsoid", "enum_value": "Ellipsoid", "class_name": "UMjEllipsoidSite"} ] }, @@ -697,8 +892,8 @@ "schema_common_block": "tendon.spatial.attrs", "type_enum_name": "EMjTendonType", "subtypes": [ - {"key": "spatial", "enum_value": "Spatial", "class_name": "UMjSpatialTendon", "display_name": "MuJoCo Spatial Tendon"}, - {"key": "fixed", "enum_value": "Fixed", "class_name": "UMjFixedTendon", "display_name": "MuJoCo Fixed Tendon"} + {"key": "spatial", "enum_value": "Spatial", "class_name": "UMjSpatialTendon"}, + {"key": "fixed", "enum_value": "Fixed", "class_name": "UMjFixedTendon"} ] }, @@ -710,14 +905,26 @@ "schema_common_block": "equality.weld", "schema_common_extra_attrs": ["polycoef"], "type_enum_name": "EMjEqualityType", + "_note_objtype_dispatch": "mjsEquality.objtype tells MuJoCo what kind of object name1/name2 refer to. Connect/Weld are dual-mode: site-to-site if site1 was specified, else body-to-body. Codegen emits a switch on EqualityType into the CODEGEN_OBJTYPE_DISPATCH markers in MjEquality.cpp.", + "objtype_dispatch": { + "discriminator": "EqualityType", + "target": "Element->objtype", + "default": "mjOBJ_UNKNOWN", + "cases": [ + {"keys": ["Connect", "Weld"], "expr": "!site1.IsEmpty() ? mjOBJ_SITE : mjOBJ_BODY"}, + {"keys": ["Joint"], "expr": "mjOBJ_JOINT"}, + {"keys": ["Tendon"], "expr": "mjOBJ_TENDON"}, + {"keys": ["Flex", "FlexVert", "FlexStrain"], "expr": "mjOBJ_FLEX"} + ] + }, "subtypes": [ - {"key": "connect", "enum_value": "Connect", "class_name": "UMjConnectEquality", "display_name": "MuJoCo Connect Equality"}, - {"key": "weld", "enum_value": "Weld", "class_name": "UMjWeldEquality", "display_name": "MuJoCo Weld Equality"}, - {"key": "joint", "enum_value": "Joint", "class_name": "UMjJointEquality", "display_name": "MuJoCo Joint Equality"}, - {"key": "tendon", "enum_value": "Tendon", "class_name": "UMjTendonEquality", "display_name": "MuJoCo Tendon Equality"}, - {"key": "flex", "enum_value": "Flex", "class_name": "UMjFlexEquality", "display_name": "MuJoCo Flex Equality"}, - {"key": "flexvert", "enum_value": "FlexVert", "class_name": "UMjFlexVertEquality", "display_name": "MuJoCo FlexVert Equality"}, - {"key": "flexstrain", "enum_value": "FlexStrain", "class_name": "UMjFlexStrainEquality", "display_name": "MuJoCo FlexStrain Equality"} + {"key": "connect", "enum_value": "Connect", "class_name": "UMjConnectEquality"}, + {"key": "weld", "enum_value": "Weld", "class_name": "UMjWeldEquality"}, + {"key": "joint", "enum_value": "Joint", "class_name": "UMjJointEquality"}, + {"key": "tendon", "enum_value": "Tendon", "class_name": "UMjTendonEquality"}, + {"key": "flex", "enum_value": "Flex", "class_name": "UMjFlexEquality"}, + {"key": "flexvert", "enum_value": "FlexVert", "class_name": "UMjFlexVertEquality"}, + {"key": "flexstrain", "enum_value": "FlexStrain", "class_name": "UMjFlexStrainEquality"} ] }, @@ -730,14 +937,25 @@ "mjs_struct": "mjsGeom", "schema_common_block": "geom.attrs", "type_enum_name": "EMjGeomType", + "_note_geom_final_type": "Mesh-name export depends on the COMPILE-TIME geom type, which is either the UPROPERTY Type (if overridden) or the Default geom's type (otherwise). Codegen emits the resolution + the conditional mesh-name write into the CODEGEN_GEOM_FINAL_TYPE markers in MjGeom.cpp. The value_map is pulled from element_rules.geom.xml_enum_attrs.type so there's only one source of truth for the XML/UE/mj triplet.", + "geom_final_type": { + "xml_enum_ref": "type", + "override_field": "bOverride_Type", + "default_lookup": "Default->geom->type", + "default_fallback": "mjGEOM_MESH", + "name_field": "MeshName", + "name_export_for": "mjGEOM_MESH", + "name_target": "Element->meshname", + "name_setter": "MjSetStringRaw" + }, "subtypes": [ - {"key": "box", "enum_value": "Box", "class_name": "UMjBox", "header": "MjBox.h", "is_hybrid": true}, - {"key": "sphere", "enum_value": "Sphere", "class_name": "UMjSphere", "header": "MjSphere.h", "is_hybrid": true}, - {"key": "capsule", "enum_value": "Capsule", "class_name": "UMjCapsule", "header": "MjCapsule.h", "is_hybrid": true}, - {"key": "cylinder", "enum_value": "Cylinder", "class_name": "UMjCylinder", "header": "MjCylinder.h", "is_hybrid": true}, - {"key": "ellipsoid", "enum_value": "Ellipsoid", "class_name": "UMjEllipsoid", "header": "MjEllipsoid.h", "is_hybrid": false}, - {"key": "plane", "enum_value": "Plane", "class_name": "UMjPlane", "header": "MjPlane.h", "is_hybrid": false}, - {"key": "sdf", "enum_value": "SDF", "class_name": "UMjSdf", "header": "MjSdf.h", "is_hybrid": false} + {"key": "box", "enum_value": "Box", "class_name": "UMjBox", "header": "MjBox.h"}, + {"key": "sphere", "enum_value": "Sphere", "class_name": "UMjSphere", "header": "MjSphere.h"}, + {"key": "capsule", "enum_value": "Capsule", "class_name": "UMjCapsule", "header": "MjCapsule.h"}, + {"key": "cylinder", "enum_value": "Cylinder", "class_name": "UMjCylinder", "header": "MjCylinder.h"}, + {"key": "ellipsoid", "enum_value": "Ellipsoid", "class_name": "UMjEllipsoid", "header": "MjEllipsoid.h", "fully_emitted": true}, + {"key": "plane", "enum_value": "Plane", "class_name": "UMjPlane", "header": "MjPlane.h", "fully_emitted": true}, + {"key": "sdf", "enum_value": "SDF", "class_name": "UMjSdf", "header": "MjSdf.h", "fully_emitted": true} ], "_note_skipped_subtypes": ["hfield (URLab has its own hfield actor system)", "mesh (existing UMjMeshGeom)"] }, @@ -779,11 +997,13 @@ }, "inertial": { + "_note_export": "MJCF has no corresponding mjsInertial struct; the export path writes to ParentBody->{mass,inertia,fullinertia,ipos,iquat} in a hand-rolled UMjInertial::RegisterToSpec. disable_mjs_export_emission suppresses the codegen-emitted Element->* export block so the hand-rolled path stays canonical.", "layout": "no_subclasses", "base_class_name": "UMjInertial", "base_class_header": "MuJoCo/Components/Physics/MjInertial.h", "mjs_struct": "mjsInertial", - "schema_common_block": "inertial.attrs" + "schema_common_block": "inertial.attrs", + "disable_mjs_export_emission": true }, "contact_pair": { @@ -814,10 +1034,7 @@ "views": { "BodyView": { - "obj_type": "mjOBJ_BODY", - "owner_count_var": "nbody", "include_blocks": ["MJMODEL_POINTERS_BODY", "MJMODEL_POINTERS_TREE"], - "field_renames": {}, "data_fields": { "xpos": {"index_var": "id", "stride": "3"}, "xquat": {"index_var": "id", "stride": "4"}, @@ -828,8 +1045,6 @@ } }, "JointView": { - "obj_type": "mjOBJ_JOINT", - "owner_count_var": "njnt", "include_blocks": ["MJMODEL_POINTERS_JOINT", "MJMODEL_POINTERS_DOF"], "derived_index_vars": { "qpos_adr": "m->jnt_qposadr[id]", @@ -839,7 +1054,6 @@ "MJMODEL_POINTERS_JOINT": "id", "MJMODEL_POINTERS_DOF": "dof_adr" }, - "field_renames": {}, "data_fields": { "qpos": {"index_var": "qpos_adr", "stride": "1"}, "qvel": {"index_var": "dof_adr", "stride": "1"}, @@ -849,55 +1063,464 @@ } }, "GeomView": { - "obj_type": "mjOBJ_GEOM", - "owner_count_var": "ngeom", "include_blocks": ["MJMODEL_POINTERS_GEOM"], - "field_renames": {}, "data_fields": { "geom_xpos": {"index_var": "id", "stride": "3"}, "geom_xmat": {"index_var": "id", "stride": "9"} } }, "SiteView": { - "obj_type": "mjOBJ_SITE", - "owner_count_var": "nsite", "include_blocks": ["MJMODEL_POINTERS_SITE"], - "field_renames": {}, "data_fields": { "site_xpos": {"index_var": "id", "stride": "3"}, "site_xmat": {"index_var": "id", "stride": "9"} } }, "ActuatorView": { - "obj_type": "mjOBJ_ACTUATOR", - "owner_count_var": "nu", "include_blocks": ["MJMODEL_POINTERS_ACTUATOR"], - "field_renames": {}, "data_fields": { - "ctrl": {"index_var": "id", "stride": "1"}, - "actuator_force":{"index_var": "id", "stride": "1"}, + "ctrl": {"index_var": "id", "stride": "1"}, + "actuator_force": {"index_var": "id", "stride": "1"}, "actuator_length":{"index_var": "id", "stride": "1"}, - "actuator_velocity":{"index_var": "id", "stride": "1"} + "actuator_velocity":{"index_var": "id", "stride": "1"}, + "_note_moment": "Per-actuator row of the actuator_moment (nu x nv) matrix. Stride is m->nv, which is a valid stride expression — no bind_override needed.", + "actuator_moment": {"index_var": "id", "stride": "m->nv"}, + "_note_act": "act lives in d->act indexed by m->actuator_actadr[id]. The adr can be -1 for actuators without an internal activation state; bind_override emits the nullable lookup so consumers can null-check ``act`` directly.", + "act": {"bind_override": "act = (m->actuator_actadr[id] >= 0) ? d->act + m->actuator_actadr[id] : nullptr;"} } }, "TendonView": { - "obj_type": "mjOBJ_TENDON", - "owner_count_var": "ntendon", "include_blocks": ["MJMODEL_POINTERS_TENDON"], - "field_renames": {}, "data_fields": { "ten_length": {"index_var": "id", "stride": "1"}, "ten_velocity": {"index_var": "id", "stride": "1"} } }, "SensorView": { - "obj_type": "mjOBJ_SENSOR", - "owner_count_var": "nsensor", "include_blocks": ["MJMODEL_POINTERS_SENSOR"], - "field_renames": {}, "data_fields": { - "sensordata": {"index_var": "m->sensor_adr[id]", "stride": "m->sensor_dim[id]"} + "_note_sensordata": "Bounds-checked slice — the default base+id*stride formula is wrong for sensordata (it would double-multiply adr*dim). bind_override is a verbatim C++ statement the codegen drops inside the BIND marker.", + "sensordata": {"bind_override": "sensordata = (sensor_adr >= 0 && sensor_adr < m->nsensordata) ? d->sensordata + sensor_adr : nullptr;"} + } + } + }, + + "_note_editor_option_helpers": "Codegens trivial UMjX::GetYOptions() editor wrappers, injecting them between CODEGEN_EDITOR_OPTIONS_START/END markers inside each host .cpp's #if WITH_EDITOR block. Wrappers with real logic (TransmissionType / EqualityType / GetClassForObjType switches) stay hand-written in the same #if block.", + "editor_option_helpers": { + "wrappers": [ + {"class": "UMjActuator", "host_cpp": "MuJoCo/Components/Actuators/MjActuator.cpp", + "method": "GetSliderSiteOptions", "filter_class": "UMjSite"}, + {"class": "UMjActuator", "host_cpp": "MuJoCo/Components/Actuators/MjActuator.cpp", + "method": "GetRefSiteOptions", "filter_class": "UMjSite"}, + {"class": "UMjActuator", "host_cpp": "MuJoCo/Components/Actuators/MjActuator.cpp", + "method": "GetDefaultClassOptions", "filter_class": "UMjDefault", "include_defaults": true}, + {"class": "UMjBody", "host_cpp": "MuJoCo/Components/Bodies/MjBody.cpp", + "method": "GetChildClassOptions", "filter_class": "UMjDefault", "include_defaults": true}, + {"class": "UMjGeom", "host_cpp": "MuJoCo/Components/Geometry/MjGeom.cpp", + "method": "GetDefaultClassOptions", "filter_class": "UMjDefault", "include_defaults": true}, + {"class": "UMjSite", "host_cpp": "MuJoCo/Components/Geometry/MjSite.cpp", + "method": "GetDefaultClassOptions", "filter_class": "UMjDefault", "include_defaults": true}, + {"class": "UMjJoint", "host_cpp": "MuJoCo/Components/Joints/MjJoint.cpp", + "method": "GetDefaultClassOptions", "filter_class": "UMjDefault", "include_defaults": true}, + {"class": "UMjContactExclude","host_cpp": "MuJoCo/Components/Physics/MjContactExclude.cpp", + "method": "GetBodyOptions", "filter_class": "UMjBody"}, + {"class": "UMjContactPair", "host_cpp": "MuJoCo/Components/Physics/MjContactPair.cpp", + "method": "GetGeomOptions", "filter_class": "UMjGeom"}, + {"class": "UMjSensor", "host_cpp": "MuJoCo/Components/Sensors/MjSensor.cpp", + "method": "GetDefaultClassOptions", "filter_class": "UMjDefault", "include_defaults": true}, + {"class": "UMjTendon", "host_cpp": "MuJoCo/Components/Tendons/MjTendon.cpp", + "method": "GetDefaultClassOptions", "filter_class": "UMjDefault", "include_defaults": true} + ] + }, + + "_note_generated_enums": "Banner-mode .h with one or more UENUMs derived from the introspect snapshot's mjt* enums (projected into mjspec.enums by _mjspec_from_introspect). Hand-edits get clobbered on next regen. ``extra_members`` appends URLab-specific values that have no mjt counterpart (e.g. DcMotor).", + "generated_enums": { + "MjOptionEnums": { + "public_header": "MuJoCo/Generated/MjOptionEnums.h", + "enums": [ + { + "ue_name": "EMjIntegrator", + "from_mj_enum": "mjtIntegrator", + "ue_member_from_mj": { + "mjINT_EULER": "Euler", + "mjINT_RK4": "RK4", + "mjINT_IMPLICIT": "Implicit", + "mjINT_IMPLICITFAST": "ImplicitFast" + } + }, + { + "ue_name": "EMjCone", + "from_mj_enum": "mjtCone", + "ue_member_from_mj": { + "mjCONE_PYRAMIDAL": "Pyramidal", + "mjCONE_ELLIPTIC": "Elliptic" + } + }, + { + "ue_name": "EMjSolver", + "from_mj_enum": "mjtSolver", + "ue_member_from_mj": { + "mjSOL_PGS": "PGS", + "mjSOL_CG": "CG", + "mjSOL_NEWTON": "Newton" + } + } + ] + }, + "_note_MjArticulationEnums": "Pure value-mapping enums emitted as MuJoCo/Generated/MjArticulationEnums.h. Components that need them (MjActuator.h, MjGeom.h, MjCameraTypes.h, MjSensor.h, MjFlexcomp.h) include this header.", + "MjArticulationEnums": { + "public_header": "MuJoCo/Generated/MjArticulationEnums.h", + "enums": [ + { + "ue_name": "EMjGainType", + "from_mj_enum": "mjtGain", + "ue_member_from_mj": { + "mjGAIN_FIXED": "Fixed", + "mjGAIN_AFFINE": "Affine", + "mjGAIN_MUSCLE": "Muscle", + "mjGAIN_DCMOTOR": "DcMotor", + "mjGAIN_USER": "User" + } + }, + { + "ue_name": "EMjBiasType", + "from_mj_enum": "mjtBias", + "ue_member_from_mj": { + "mjBIAS_NONE": "None", + "mjBIAS_AFFINE": "Affine", + "mjBIAS_MUSCLE": "Muscle", + "mjBIAS_DCMOTOR": "DcMotor", + "mjBIAS_USER": "User" + } + }, + { + "ue_name": "EMjDynType", + "from_mj_enum": "mjtDyn", + "ue_member_from_mj": { + "mjDYN_NONE": "None", + "mjDYN_INTEGRATOR": "Integrator", + "mjDYN_FILTER": "Filter", + "mjDYN_FILTEREXACT": "FilterExact", + "mjDYN_MUSCLE": "Muscle", + "mjDYN_DCMOTOR": "DcMotor", + "mjDYN_USER": "User" + } + }, + { + "_note_EMjGeomInertia": "No mjt counterpart; MJCF geom inertia kind is parser-side enum string-mapped on import. Pure extra_members.", + "ue_name": "EMjGeomInertia", + "extra_members": [ + {"name": "Volume", "value": 0}, + {"name": "Shell", "value": 1} + ] + }, + { + "_note_EMjFluidShape": "URLab-only; MuJoCo fluid shape is a runtime computation, not a public enum. Pure extra_members.", + "ue_name": "EMjFluidShape", + "extra_members": [ + {"name": "None", "value": 0}, + {"name": "Ellipsoid", "value": 1} + ] + }, + { + "_note_EMjCameraTrackingMode": "Mirrors mjtCamLight but only the camera-side subset; values come from mjCAMLIGHT_* keyed by URLab member name.", + "ue_name": "EMjCameraTrackingMode", + "from_mj_enum": "mjtCamLight", + "ue_member_from_mj": { + "mjCAMLIGHT_FIXED": "Fixed", + "mjCAMLIGHT_TRACK": "Track", + "mjCAMLIGHT_TRACKCOM": "TrackCom", + "mjCAMLIGHT_TARGETBODY": "TargetBody", + "mjCAMLIGHT_TARGETBODYCOM": "TargetBodyCom" + } + }, + { + "ue_name": "EMjCameraProjection", + "from_mj_enum": "mjtProjection", + "ue_member_from_mj": { + "mjPROJ_PERSPECTIVE": "Perspective", + "mjPROJ_ORTHOGRAPHIC": "Orthographic" + } + }, + { + "ue_name": "EMjObjType", + "from_mj_enum": "mjtObj", + "exclude_mj_members": ["mjNOBJECT", "mjOBJ_DEFAULT", "mjOBJ_MODEL"], + "ue_member_from_mj": { + "mjOBJ_UNKNOWN": "Unknown", + "mjOBJ_BODY": "Body", + "mjOBJ_XBODY": "XBody", + "mjOBJ_JOINT": "Joint", + "mjOBJ_DOF": "DoF", + "mjOBJ_GEOM": "Geom", + "mjOBJ_SITE": "Site", + "mjOBJ_CAMERA": "Camera", + "mjOBJ_LIGHT": "Light", + "mjOBJ_FLEX": "Flex", + "mjOBJ_MESH": "Mesh", + "mjOBJ_SKIN": "Skin", + "mjOBJ_HFIELD": "HField", + "mjOBJ_TEXTURE": "Texture", + "mjOBJ_MATERIAL": "Material", + "mjOBJ_PAIR": "Pair", + "mjOBJ_EXCLUDE": "Exclude", + "mjOBJ_EQUALITY": "Equality", + "mjOBJ_TENDON": "Tendon", + "mjOBJ_ACTUATOR": "Actuator", + "mjOBJ_SENSOR": "Sensor", + "mjOBJ_NUMERIC": "Numeric", + "mjOBJ_TEXT": "Text", + "mjOBJ_TUPLE": "Tuple", + "mjOBJ_KEY": "Key", + "mjOBJ_PLUGIN": "Plugin", + "mjOBJ_FRAME": "Frame" + } + }, + { + "_note_EMjActuatorTrnType": "mjTRN_UNDEFINED has C value 1000 (way out of uint8 range), so it can't be a direct ue_member_from_mj entry. Excluded from the snapshot pass and reintroduced as an extra_member with the next contiguous slot (6).", + "ue_name": "EMjActuatorTrnType", + "from_mj_enum": "mjtTrn", + "exclude_mj_members": ["mjTRN_UNDEFINED"], + "ue_member_from_mj": { + "mjTRN_JOINT": "Joint", + "mjTRN_JOINTINPARENT": "JointInParent", + "mjTRN_SLIDERCRANK": "SliderCrank", + "mjTRN_TENDON": "Tendon", + "mjTRN_SITE": "Site", + "mjTRN_BODY": "Body" + }, + "extra_members": [ + {"name": "Undefined", "value": 6} + ] + }, + { + "_note_EMjFlexcompDof": "URLab-only flex-component DoF reduction kind; no mjt counterpart (the MJCF attr is `dof` and parsed string-side). Pure extra_members; matches the pre-migration hand-rolled set.", + "ue_name": "EMjFlexcompDof", + "extra_members": [ + {"name": "Full", "value": 0}, + {"name": "Radial", "value": 1}, + {"name": "Trilinear", "value": 2}, + {"name": "Quadratic", "value": 3}, + {"name": "TwoD", "value": 4} + ] + } + ] + } + }, + + "_note_synthetic_categories": "Whole-file banner-mode emission for USTRUCTs mirroring C structs from mjxmacro_block. Hand-edits to generated files get clobbered on next regen. See generate_ue_components.py::_phase_synthetic_categories.", + "synthetic_categories": { + "MjStatistic": { + "ue_struct_name": "FMjStatistic", + "mjxmacro_block": "MJSTATISTIC_FIELDS", + "c_struct_type": "mjStatistic", + "public_header": "MuJoCo/Generated/MjStatistic.h", + "private_source": "MuJoCo/Generated/MjStatistic.cpp", + "category_label": "Statistic" + }, + + "_note_MjOption": "Codegen-emitted FMjOptionGenerated mirrors mjOption (MJOPTION_FIELDS) with URLab extras (MemoryMB, bEnableMultiCCD, bEnableSleep, SleepTolerance). AMjArticulation::SimOptions and UMjPhysicsEngine::SimOptions point at this struct directly.", + "MjOption": { + "ue_struct_name": "FMjOptionGenerated", + "mjxmacro_block": "MJOPTION_FIELDS", + "c_struct_type": "mjOption", + "public_header": "MuJoCo/Generated/MjOptionGenerated.h", + "private_source": "MuJoCo/Generated/MjOptionGenerated.cpp", + "category_label": "MjOption", + "include_directives": [ + "mujoco/mujoco.h", + "MuJoCo/Generated/MjOptionEnums.h" + ], + "field_renames": { + "timestep": "Timestep", + "impratio": "Impratio", + "tolerance": "Tolerance", + "ls_tolerance": "LsTolerance", + "noslip_tolerance": "NoslipTolerance", + "ccd_tolerance": "CCD_Tolerance", + "sdf_initpoints": "SdfInitPoints", + "sdf_iterations": "SdfIterations", + "iterations": "Iterations", + "ls_iterations": "LsIterations", + "noslip_iterations": "NoslipIterations", + "ccd_iterations": "CCD_Iterations", + "disableflags": "DisableFlags", + "enableflags": "EnableFlags", + "disableactuator": "DisableActuator", + "apirate": "ApiRate", + "sleep_tolerance": "SleepToleranceMj", + "rebuild_interval": "RebuildInterval" + }, + "field_types": { + "timestep": "float", + "apirate": "float", + "integrator": "EMjIntegrator", + "cone": "EMjCone", + "solver": "EMjSolver" + }, + "field_defaults": { + "Timestep": "0.002", + "Impratio": "1.0", + "Tolerance": "1e-8", + "Iterations": "100", + "LsIterations": "50", + "NoslipTolerance": "1e-6", + "CCD_Tolerance": "1e-6", + "Gravity": "FVector(0.0f, 0.0f, -981.0f)", + "Magnetic": "FVector(0.0f, -0.5f, 0.0f)", + "Integrator": "EMjIntegrator::Euler", + "Cone": "EMjCone::Pyramidal", + "Solver": "EMjSolver::Newton" + }, + "field_apply_to_spec_mode": { + "gravity": "vec3_cm", + "wind": "vec3_cm", + "magnetic": "vec3_y_flip", + "integrator": "guarded", + "cone": "guarded", + "solver": "guarded", + "noslip_iterations": "guarded", + "noslip_tolerance": "guarded", + "ccd_iterations": "guarded", + "ccd_tolerance": "guarded" + }, + "_note_skip_vs_exclude": "field_skip_apply: emitted as UPROPERTY but not written to mjOption (apply body skips). exclude_fields: omitted from the struct entirely. exclude_fields takes precedence in iteration, so entries listed in both would be dead — keep them apart.", + "field_skip_apply": [ + "disableflags", "enableflags", "disableactuator", + "sdf_initpoints", "sdf_iterations", "sleep_tolerance" + ], + "exclude_fields": ["apirate", "rebuild_interval", "o_solref", "o_solimp", "o_friction"], + "urlab_extra_fields": [ + { + "name": "MemoryMB", + "type": "int32", + "default": "100", + "meta": "ClampMin=\"1\"", + "has_override": true + }, + { + "name": "bEnableMultiCCD", + "type": "bool", + "default": "false", + "sub_category": "Collision", + "meta": "ToolTip=\"Enable multi-contact convex collision detection. Useful for flat surfaces (e.g. mesh-mesh) where single-point contact causes sliding or wobbling.\"", + "has_override": false + }, + { + "name": "bEnableSleep", + "type": "bool", + "default": "false", + "sub_category": "Sleep", + "has_override": false + }, + { + "name": "SleepTolerance", + "type": "float", + "default": "1e-4f", + "sub_category": "Sleep", + "edit_condition": "bEnableSleep", + "has_override": false + } + ], + "apply_extras_function": "ApplyMjOptionExtras", + "emit_apply_methods": true + }, + + "_note_MjVisualStructs": "Codegen-emitted FMjVisual{Global,Headlight,Quality,Map,Scale,Rgba} parallel to mjVisual sub-blocks.", + "MjVisualGlobal": { + "ue_struct_name": "FMjVisualGlobal", + "mjxmacro_block": "MJVISUAL_GLOBAL_FIELDS", + "c_struct_type": "mjVisualGlobal", + "public_header": "MuJoCo/Generated/MjVisualGlobal.h", + "private_source": "MuJoCo/Generated/MjVisualGlobal.cpp", + "category_label": "Visual|Global", + "field_defaults": { + "Fovy": "45.0f", + "Ipd": "0.068f", + "Realtime": "1.0f" + } + }, + "MjVisualHeadlight": { + "ue_struct_name": "FMjVisualHeadlight", + "mjxmacro_block": "MJVISUAL_HEADLIGHT_FIELDS", + "c_struct_type": "mjVisualHeadlight", + "public_header": "MuJoCo/Generated/MjVisualHeadlight.h", + "private_source": "MuJoCo/Generated/MjVisualHeadlight.cpp", + "category_label": "Visual|Headlight", + "field_defaults": { + "Ambient": "FVector(0.1f, 0.1f, 0.1f)", + "Diffuse": "FVector(0.4f, 0.4f, 0.4f)", + "Specular": "FVector(0.5f, 0.5f, 0.5f)", + "Active": "1" + } + }, + "MjVisualQuality": { + "ue_struct_name": "FMjVisualQuality", + "mjxmacro_block": "MJVISUAL_QUALITY_FIELDS", + "c_struct_type": "mjVisualQuality", + "public_header": "MuJoCo/Generated/MjVisualQuality.h", + "category_label": "Visual|Quality", + "_note": "All quality fields are int in mjmodel.h (shadowsize=1024, offsamples=4, numslices=28, numstacks=16, numquads=4). mjxmacro carries no type info for these (bare X(name) form); explicit field_types override.", + "field_types": { + "shadowsize": "int32", "offsamples": "int32", "numslices": "int32", + "numstacks": "int32", "numquads": "int32" + }, + "field_defaults": { + "Shadowsize": "1024", "Offsamples": "4", "Numslices": "28", + "Numstacks": "16", "Numquads": "4" } + }, + "MjVisualMap": { + "ue_struct_name": "FMjVisualMap", + "mjxmacro_block": "MJVISUAL_MAP_FIELDS", + "c_struct_type": "mjVisualMap", + "public_header": "MuJoCo/Generated/MjVisualMap.h", + "category_label": "Visual|Map", + "_note": "All map fields are float scalars in mjVisualMap (force, torque, stiffness, etc.). mjxmacro defaults them to mjtNum (double) which compiles cleanly via implicit conversion." + }, + "MjVisualScale": { + "ue_struct_name": "FMjVisualScale", + "mjxmacro_block": "MJVISUAL_SCALE_FIELDS", + "c_struct_type": "mjVisualScale", + "public_header": "MuJoCo/Generated/MjVisualScale.h", + "category_label": "Visual|Scale", + "_note": "Same as MjVisualMap — float scalars in mjmodel.h, mjxmacro defaults to mjtNum which compiles fine." + }, + "MjVisualRgba": { + "ue_struct_name": "FMjVisualRgba", + "mjxmacro_block": "MJVISUAL_RGBA_FIELDS", + "c_struct_type": "mjVisualRgba", + "public_header": "MuJoCo/Generated/MjVisualRgba.h", + "category_label": "Visual|Rgba", + "_note": "Every field is float[4] color in mjVisualRgba. mjxmacro's bare X(name) form drops that info; all_fields_type forces FLinearColor for the UPROPERTY + flips the ApplyTo emit to .R/.G/.B/.A writes.", + "all_fields_type": "FLinearColor" + }, + "_note_MjsCompilerOptions": "Mirror of mjsCompiler (MJSCOMPILER_FIELDS in mjspecmacro.h, vendored via Scripts/codegen/sync_vendored.py). Header-only USTRUCT — no .cpp emission today since URLab parses compiler settings via the legacy FMjCompilerSettings struct in MjOrientationUtils.h. Future migration: route MjArticulation through this struct + an ApplyToSpec method.", + "MjsCompilerOptions": { + "ue_struct_name": "FMjsCompilerOptions", + "mjxmacro_block": "MJSCOMPILER_FIELDS", + "c_struct_type": "mjsCompiler", + "public_header": "MuJoCo/Generated/MjsCompilerOptions.h", + "category_label": "Spec|Compiler", + "_note_exclude": "LRopt is mjLROpt (nested struct, not mirror-able as a UPROPERTY); meshdir/texturedir are mjString* (different shape — handled by the existing MeshDir/AssetDir on FMjCompilerSettings). eulerseq is a char[3] vec — mirror as FString instead, but skip in ApplyTo since FString -> char[3] needs a copy not a cast.", + "exclude_fields": ["LRopt", "meshdir", "texturedir"], + "field_skip_apply": ["eulerseq"], + "field_types": {"eulerseq": "FString"}, + "field_defaults": {"Eulerseq": "TEXT(\"xyz\")"} + }, + "_note_MjsSpec": "Mirror of mjSpec top-level fields (MJSPEC_FIELDS in mjspecmacro.h). Many entries are NESTED structs (mjsCompiler, mjOption, mjVisual, mjStatistic) — those are exposed via the dedicated FMjsCompilerOptions / FMjOptionGenerated / FMjVisual* / FMjStatistic structs. We only mirror the scalar + string fields here.", + "MjsSpec": { + "ue_struct_name": "FMjsSpec", + "mjxmacro_block": "MJSPEC_FIELDS", + "c_struct_type": "mjSpec", + "public_header": "MuJoCo/Generated/MjsSpec.h", + "category_label": "Spec", + "_note_exclude": "element/compiler/option/visual/stat are nested structs already exposed via their own synthetic_categories. modelname / comment / modelfiledir / meshdir / texturedir are mjString* — distinct shape. memory is mjtSize (handle separately).", + "exclude_fields": [ + "element", "compiler", "option", "visual", "stat", + "modelname", "comment", "modelfiledir", "meshdir", "texturedir", + "memory", "strippath" + ] } } } diff --git a/Scripts/codegen/generate_ue_components.py b/Scripts/codegen/generate_ue_components.py index 477d92c..8388cd5 100644 --- a/Scripts/codegen/generate_ue_components.py +++ b/Scripts/codegen/generate_ue_components.py @@ -9,9 +9,12 @@ URLab UE component codegen, schema-driven. Inputs: - - Scripts/mjcf_schema_snapshot.json (MJCF schema attrs) - - Scripts/mjxmacro_snapshot.json (mjModel/mjData pointer table) - - Scripts/codegen/codegen_rules.json (per-category layout, rules) + - Scripts/codegen/snapshots/mjcf_schema_snapshot.json (MJCF schema attrs) + - Scripts/codegen/snapshots/mjxmacro_snapshot.json (mjModel/mjData pointer table) + - Scripts/codegen/snapshots/introspect_snapshot.json (libclang-scraped C API: + mjsX struct fields, mjt* + enums, mjs_setTo* signatures) + - Scripts/codegen/codegen_rules.json (per-category layout, rules) Outputs: - Component .h / .cpp files in Source/URLab/Public|Private/MuJoCo/Components/ @@ -38,15 +41,45 @@ import os import re import sys -from dataclasses import dataclass -from typing import Any, Dict, List, Optional, Sequence, Tuple +from dataclasses import dataclass, field +from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple + +# Sibling modules. Only names actually consumed by this orchestrator's +# body are imported here. Test files import private helpers (e.g. +# _resolve_direct, _classify_c_type, _check_brace_balance) directly from +# their owning module — the orchestrator is not a re-export surface. +from _codegen_core import ( + _DIAGS_BUFFER, _diag_add, _diag_flush, _reset_diags, + _ue_type_accepts_units_meta, _attr_default_value, + override_toggle_name, + schema_attrs, schema_subtype_attrs, + compute_canon_absorbed, iter_category_attrs, + _VEC3_CONVERT_FMT, + _resolve_mjs_field, _resolve_value_map, + FileWrite, +) +from _codegen_inject import ( + _find_matching_brace, + inject_between_tags, _inject_tags_into_cpp, +) +from _codegen_checks import ( + _check_hand_enum_drift, _check_type_shape_drift, + _check_new_attr_typing, _check_orphan_rule_entries, + _check_mjxmacro_block_coverage, _check_apply_mode_validity, + _check_embedded_cpp_references, + _check_allowlist_staleness, + _check_property_units_validity, _check_compiler_attrs_coverage, + _check_value_map_stale_mj_consts, + _emit_drift_diagnostics, +) SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PLUGIN_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..")) -DEFAULT_SCHEMA = os.path.join(PLUGIN_ROOT, "Scripts", "mjcf_schema_snapshot.json") -DEFAULT_MJXMACRO = os.path.join(PLUGIN_ROOT, "Scripts", "mjxmacro_snapshot.json") -DEFAULT_MJSPEC = os.path.join(PLUGIN_ROOT, "Scripts", "mjspec_snapshot.json") +_SNAPSHOT_DIR = os.path.join(PLUGIN_ROOT, "Scripts", "codegen", "snapshots") +DEFAULT_SCHEMA = os.path.join(_SNAPSHOT_DIR, "mjcf_schema_snapshot.json") +DEFAULT_MJXMACRO = os.path.join(_SNAPSHOT_DIR, "mjxmacro_snapshot.json") +DEFAULT_INTROSPECT = os.path.join(_SNAPSHOT_DIR, "introspect_snapshot.json") DEFAULT_RULES = os.path.join(SCRIPT_DIR, "codegen_rules.json") DEFAULT_PUBLIC_ROOT = os.path.join(PLUGIN_ROOT, "Source", "URLab", "Public") DEFAULT_PRIVATE_ROOT= os.path.join(PLUGIN_ROOT, "Source", "URLab", "Private") @@ -80,95 +113,31 @@ """ -# --------------------------------------------------------------------------- -# Naming helpers -# --------------------------------------------------------------------------- - -def pascal_case(snake_or_camel: str) -> str: - """**Schema-verbatim** naming. We use MuJoCo's attribute name AS-IS - as the C++ UPROPERTY identifier — no PascalCase, no renames. This - keeps the codegen pure: schema name == C++ name == wire field name. - - Future-proof for MuJoCo bumps: a new attr appears in MJCF → it - flows through without any rename table to maintain. +def _should_emit_xml_enum_at_this_layer( + attr: str, + attrs: Sequence[str], + global_excl: Set[str], + *, + apply_canonicalizations: bool, +) -> bool: + """Whether this codegen layer owns the xml_enum import/export for + ``attr``. Two cases fire: + + - The attr appears in this layer's attrs list — subtype-specific + case, e.g. ``dcmotor.input`` fires on the DCMotor subtype's + emission. + - The base-class layer (apply_canonicalizations=True) AND the + attr is in global_exclusions — always-emit-at-base case, e.g. + ``joint.type`` is globally excluded from per-attr UPROPERTY + emission but xml_enum_attrs still owns its import/export at + the base. """ - return snake_or_camel - - -def override_toggle_name(prop_name: str) -> str: - return f"bOverride_{prop_name}" + if attr in attrs: + return True + return apply_canonicalizations and attr in global_excl -# --------------------------------------------------------------------------- -# Schema access -# --------------------------------------------------------------------------- - -def schema_attrs(schema: Dict[str, Any], path: str) -> List[str]: - """Read an attribute list at a dotted path, e.g. ``actuator_common.attrs`` - or ``camera.attrs`` or ``tendon.spatial.attrs``. Returns [] if missing.""" - cur: Any = schema - for piece in path.split("."): - if isinstance(cur, dict) and piece in cur: - cur = cur[piece] - else: - return [] - if isinstance(cur, list): - # Could be list of strings OR list of dicts {name, attrs}; normalise. - if cur and isinstance(cur[0], str): - return list(cur) - attrs: List[str] = [] - for entry in cur: - if isinstance(entry, dict): - # equality types are dicts with key/attrs nested under - # the type name (e.g. {"connect": [...]}, or {"name": ..., "attrs": [...]}) - if "attrs" in entry and isinstance(entry["attrs"], list): - attrs.extend([str(x) for x in entry["attrs"]]) - else: - for v in entry.values(): - if isinstance(v, list): - attrs.extend([str(x) for x in v]) - # de-dupe preserving order - seen = set() - out = [] - for a in attrs: - if a not in seen: - seen.add(a) - out.append(a) - return out - if isinstance(cur, dict): - # E.g. equality.weld is a list inside a dict — handle by walking - # all string-list values one level deeper. - attrs2: List[str] = [] - for v in cur.values(): - if isinstance(v, list): - attrs2.extend([str(x) for x in v if isinstance(x, str)]) - return attrs2 - return [] - - -def schema_subtype_attrs(schema: Dict[str, Any], category: str, subtype_key: str) -> List[str]: - """Look up per-subtype attrs from schema['actuator_types'][key] / - schema['sensor_types'] (list-of-dict). Returns [] if not found.""" - if category == "actuator": - block = schema.get("actuator_types", {}) - if isinstance(block, dict): - entry = block.get(subtype_key) - if isinstance(entry, list): - return [str(x) for x in entry] - if isinstance(entry, dict) and "attrs" in entry: - return [str(x) for x in entry["attrs"]] - return [] - if category == "sensor": - block = schema.get("sensor_types", []) - if isinstance(block, list): - for entry in block: - if isinstance(entry, dict) and entry.get("name") == subtype_key: - attrs = entry.get("attrs", []) - return [str(x) for x in attrs] if isinstance(attrs, list) else [] - if isinstance(entry, str) and entry == subtype_key: - return [] # name-only entry, no extra attrs - return [] - return [] +# `schema_attrs` and `schema_subtype_attrs` live in `_codegen_core`. # --------------------------------------------------------------------------- @@ -183,33 +152,171 @@ class EmittedSchema: exports_cpp: str # ExportTo body (between codegen tags) -def _attr_default_value(ue_type: str) -> str: - if ue_type == "float": return "0.0f" - if ue_type == "int32": return "0" - if ue_type == "bool": return "false" - if ue_type == "FString": return "TEXT(\"\")" - if ue_type == "FVector": return "FVector::ZeroVector" - if ue_type == "FQuat": return "FQuat::Identity" - if ue_type == "FLinearColor": return "FLinearColor::White" - if ue_type.startswith("TArray"): return "{}" - return "{}" +@dataclass +class EmissionContext: + """Cross-cutting rules / element / call-site state threaded through + ``emit_schema_for_attrs`` and its helpers. Built once via ``from_call``. + + Carries every shared computation the property/import/export helpers + need (canon_absorbed, xml_enum_attr_names, elem_canons, the various + rule dicts) so the helpers take one ``ctx`` arg instead of 15 + positional parameters.""" + # --- caller-provided --- + attrs: Sequence[str] + rules: Dict[str, Any] + element_name: str + apply_canonicalizations: bool = True + mjs_fields: Optional[set] = None + consumed_by_setto: Optional[set] = None + mjs_array_caps: Optional[Dict[str, int]] = None + # --- derived from rules (cached on construct) --- + global_excl: set = field(default_factory=set) + type_map: Dict[str, str] = field(default_factory=dict) + default_type: str = "float" + renames: Dict[str, str] = field(default_factory=dict) + elem_rules: Dict[str, Any] = field(default_factory=dict) + elem_excl: set = field(default_factory=set) + canonicalizations: Dict[str, Any] = field(default_factory=dict) + attr_to_mjs_field: Dict[str, str] = field(default_factory=dict) + # --- derived in from_call but parameterised by apply_canonicalizations --- + elem_canons: List[str] = field(default_factory=list) + canon_absorbed: set = field(default_factory=set) + xml_enum_attr_names: set = field(default_factory=set) + + @classmethod + def from_call(cls, + attrs: Sequence[str], + rules: Dict[str, Any], + element_name: str, + *, + apply_canonicalizations: bool = True, + mjs_fields: Optional[set] = None, + consumed_by_setto: Optional[set] = None, + mjs_array_caps: Optional[Dict[str, int]] = None) -> "EmissionContext": + elem_rules = rules.get("element_rules", {}).get(element_name, {}) + canonicalizations = rules.get("canonicalizations", {}) + # ``elem_canons`` is the raw applied-canon list; the helpers + # clear it when apply_canonicalizations is False, but + # ``canon_absorbed`` keeps the raw absorbed set so per-attr + # emission still excludes them at the subtype layer. + elem_canons: List[str] = list( + elem_rules.get("applies_canonicalizations", []) + ) + canon_absorbed = compute_canon_absorbed(elem_canons, canonicalizations) + if not apply_canonicalizations: + elem_canons = [] + return cls( + attrs=attrs, + rules=rules, + element_name=element_name, + apply_canonicalizations=apply_canonicalizations, + mjs_fields=mjs_fields, + consumed_by_setto=consumed_by_setto, + mjs_array_caps=mjs_array_caps, + global_excl=set(rules.get("global_exclusions", [])), + type_map=rules.get("type_mappings", {}), + default_type=rules.get("default_type", "float"), + renames=rules.get("property_renames", {}), + elem_rules=elem_rules, + elem_excl=set(elem_rules.get("exclude_attrs", [])), + canonicalizations=canonicalizations, + attr_to_mjs_field=elem_rules.get("attr_to_mjs_field", {}), + elem_canons=elem_canons, + canon_absorbed=canon_absorbed, + xml_enum_attr_names=set(elem_rules.get("xml_enum_attrs", {}).keys()), + ) + + + +def _inject_or_diag( + text: str, + tag: str, + body: str, + *, + host_path: str, + host_kind: str, + block_label: str, + diag_source: str, +) -> Tuple[str, bool]: + """Inject ``body`` between the ``CODEGEN_`` markers in ``text``. + When the markers are missing AND the body is non-empty, fire a + diagnostic that names the host kind (e.g. 'subclass header'), the + path, the tag, and what didn't land. Returns (new_text, ok). + + This collapses ~12 near-identical try-inject-then-diag stanzas + that used to live in the emit_*_class_injection callers.""" + new_text, ok = inject_between_tags(text, tag, body, balance_source=diag_source) + if not ok and body.strip(): + _diag_add( + f"[diagnostic] {host_kind} '{host_path}' is missing the " + f"CODEGEN_{tag}_START/END marker pair; {block_label} was " + f"NOT injected.", + source=diag_source, + ) + return new_text, ok + + +def _guarded_export(toggle: str, body: str, + extra_cond: Optional[str] = None, + extra_cond_first: bool = False, + multiline: bool = False) -> str: + """Wrap ``body`` in an ``if ({toggle})`` guard and return the indented + emission. + + ``extra_cond=None``: ``if ({toggle}) {body}`` + ``extra_cond`` + first=False: ``if ({toggle} && {extra_cond}) {body}`` + ``extra_cond`` + first=True: ``if (({extra_cond}) && {toggle}) {body}`` + + ``multiline=True``: emit a braced block. ``body`` is dropped verbatim + inside the braces (caller controls inner indent — the helper does + NOT auto-indent each line so existing multi-line bodies migrate + byte-identically). Use for blocks that were previously hand-rolled + as ``if ({toggle})\\n{{\\n\\n}}\\n``. + """ + if extra_cond is None: + cond = toggle + elif extra_cond_first: + cond = f"({extra_cond}) && {toggle}" + else: + cond = f"{toggle} && {extra_cond}" + if multiline: + return f" if ({cond})\n {{\n{body} }}\n" + return f" if ({cond}) {body}\n" + + +# `_UEType`, `_UE_TYPE_INFO`, and `_attr_default_value` live in +# `_codegen_core` (re-exported at the top of this file). def _emit_uproperty(prop_name: str, ue_type: str, category_label: str, sub_category: Optional[str] = None, - extra_meta: Optional[str] = None) -> str: + extra_meta: Optional[str] = None, + default_override: Optional[str] = None, + hide_from_details: bool = False) -> str: """Emit the toggle + value UPROPERTY pair for a schema-driven attr. ``extra_meta`` appends to the value UPROPERTY's meta=() block — used to inject ``DisplayName``, ``GetOptions``, etc. via per-attr rules in ``codegen_rules.json#element_rules..property_meta.``. + + ``hide_from_details=True`` keeps the field as a C++ member (so codegen + import paths can still seed it and BPs can still read/write it) but + suppresses the Details-panel widget via + ``EditCondition="false", EditConditionHides``. Used for properties whose + canonical authoring surface is the UE Transform widget (Pos/Quat -> + RelativeLocation/Rotation, size -> RelativeScale3D). """ cat = f"MuJoCo|{category_label}" if sub_category: cat = f"{cat}|{sub_category}" toggle = override_toggle_name(prop_name) - default = _attr_default_value(ue_type) - meta_inner = f'EditCondition="{toggle}"' + default = default_override if default_override else _attr_default_value(ue_type) + if hide_from_details: + # EditConditionHides on the value also collapses the InlineEditConditionToggle + # toggle bool above it because UE renders them as a single merged row. + meta_inner = 'EditCondition="false", EditConditionHides' + else: + meta_inner = f'EditCondition="{toggle}"' if extra_meta: meta_inner = f'{meta_inner}, {extra_meta}' return ( @@ -221,11 +328,14 @@ def _emit_uproperty(prop_name: str, ue_type: str, category_label: str, ) -def _emit_import_line(attr: str, prop_name: str, ue_type: str) -> str: +def _emit_import_line(attr: str, prop_name: str, ue_type: str, + vec3_convert: Optional[str] = None) -> str: toggle = override_toggle_name(prop_name) key = f'TEXT("{attr}")' if ue_type == "float": return f' MjXmlUtils::ReadAttrFloat(Node, {key}, {prop_name}, {toggle});\n' + if ue_type == "double": + return f' MjXmlUtils::ReadAttrDouble(Node, {key}, {prop_name}, {toggle});\n' if ue_type == "int32": return f' MjXmlUtils::ReadAttrInt(Node, {key}, {prop_name}, {toggle});\n' if ue_type == "bool": @@ -234,7 +344,12 @@ def _emit_import_line(attr: str, prop_name: str, ue_type: str) -> str: return (f' if (MjXmlUtils::ReadAttrString(Node, {key}, {prop_name}))' f' {toggle} = true;\n') if ue_type == "FVector": - return f' MjXmlUtils::ReadAttrVec3(Node, {key}, {prop_name}, {toggle});\n' + out = f' MjXmlUtils::ReadAttrVec3(Node, {key}, {prop_name}, {toggle});\n' + # MuJoCo direction vectors don't carry units but DO use opposite Y + # handedness vs UE. Apply Y-negate post-read when configured. + if vec3_convert == "y_negate": + out += f' if ({toggle}) {prop_name}.Y = -{prop_name}.Y;\n' + return out if ue_type == "FLinearColor": return f' MjXmlUtils::ReadAttrColor(Node, {key}, {prop_name}, {toggle});\n' if ue_type.startswith("TArray str: return f' MjXmlUtils::ReadAttrFloat(Node, {key}, {prop_name}, {toggle});\n' -def _resolve_mjs_field(attr: str, mjs_fields: set, - attr_to_mjs_field: Dict[str, str] | None = None) -> str: - """Pick the correct C field name on a category's mjs struct for a - given schema attribute. Per-element ``attr_to_mjs_field`` overrides - apply first; otherwise we capture MuJoCo's own naming conventions: - - 0. Per-element ``attr_to_mjs_field`` override (target -> targetbody, - focal -> focal_length) - 1. ``attr`` itself (condim -> mjsPair.condim) - 2. ``attr + "name"`` (body1 -> bodyname1, mesh -> meshname) - 3. ``name`` (geom1 -> geomname1, body2 -> bodyname2) - 4. Underscore-normalised match (solreflimit -> solref_limit) - 5. ``actuator`` prefix compressed (actuatorfrclimited -> actfrclimited, - actuatorgravcomp -> actgravcomp) - - Falls back to ``attr`` if nothing matches — the build will then - surface the mismatch loudly.""" - if attr_to_mjs_field and attr in attr_to_mjs_field: - return attr_to_mjs_field[attr] - if not mjs_fields: - return attr - if attr in mjs_fields: - return attr - if (attr + "name") in mjs_fields: - return attr + "name" - m = re.match(r"^(.*?)(\d+)$", attr) - if m: - root = m.group(1) - digits = m.group(2) - for candidate in (f"{root}name{digits}", f"{root}_name{digits}"): - if candidate in mjs_fields: - return candidate - # Underscore-normalised match — strip all underscores and look for the - # same letters. E.g. mjsJoint.solref_limit <- schema solreflimit. - norm = attr.replace("_", "") - for f in mjs_fields: - if f.replace("_", "") == norm: - return f - # `actuator`-prefix compression: schema spells it out, mjs trims to `act`. - if attr.startswith("actuator"): - cand = "act" + attr[len("actuator"):] - if cand in mjs_fields: - return cand - cand_norm = cand.replace("_", "") - for f in mjs_fields: - if f.replace("_", "") == cand_norm: - return f - return attr +# Per-strategy resolvers for the schema-attr -> mjs-field name mapper. +# Each takes (attr, mjs_fields) and returns ``Optional[str]`` — the +# winning field name, or None to fall through to the next strategy. +# Order in _MJS_FIELD_RESOLVERS matters: more specific rules first. + + +# The 5-strategy mjs-field resolver chain (+ ``_resolve_mjs_field``) +# lives in `_codegen_core`. def _emit_export_line(attr: str, prop_name: str, ue_type: str, mjs_fields: set | None = None, slot_sentinel: str | None = None, attr_to_mjs_field: Dict[str, str] | None = None, - consumed_by_setto: set | None = None) -> str: + consumed_by_setto: set | None = None, + vec3_convert: Optional[str] = None, + array_cap: Optional[int] = None) -> str: toggle = override_toggle_name(prop_name) # If we have an mjs field set and the attr can't be resolved to one of # them, this attr isn't directly assignable on the mjs struct (e.g. @@ -322,31 +399,51 @@ def _emit_export_line(attr: str, prop_name: str, ue_type: str, else: field = attr_to_mjs_field.get(attr, attr) if attr_to_mjs_field else attr if ue_type.startswith("TArray gainprm[6]) doesn't memory-overrun. Dynamic + # vec destinations (mjFloatVec*, mjDoubleVec*) pass array_cap=None + # and use the raw prop.Num() — the dynamic vec resizes itself. + upper = f"FMath::Min({prop_name}.Num(), {array_cap})" if array_cap else f"{prop_name}.Num()" if slot_sentinel is not None: # Per-slot sentinel guard: skip slots whose value equals the # sentinel (used for `size` so fromto-only imports don't # clobber the inherited default radius / earlier slots). - return ( - f' if ({toggle}) {{ for (int32 i = 0; i < {prop_name}.Num(); ++i)' - f' {{ if ({prop_name}[i] != {slot_sentinel}) Element->{field}[i] = {prop_name}[i]; }} }}\n' + return _guarded_export(toggle, + f'{{ for (int32 i = 0; i < {upper}; ++i)' + f' {{ if ({prop_name}[i] != {slot_sentinel}) Element->{field}[i] = {prop_name}[i]; }} }}', ) - return (f' if ({toggle}) {{ for (int32 i = 0; i < {prop_name}.Num(); ++i)' - f' Element->{field}[i] = {prop_name}[i]; }}\n') + return _guarded_export(toggle, + f'{{ for (int32 i = 0; i < {upper}; ++i)' + f' Element->{field}[i] = {prop_name}[i]; }}', + ) if ue_type == "FVector": - return (f' if ({toggle}) {{ Element->{field}[0] = {prop_name}.X;' - f' Element->{field}[1] = {prop_name}.Y;' - f' Element->{field}[2] = {prop_name}.Z; }}\n') + if vec3_convert == "y_negate": + return _guarded_export(toggle, + f'{{ Element->{field}[0] = {prop_name}.X;' + f' Element->{field}[1] = -{prop_name}.Y;' + f' Element->{field}[2] = {prop_name}.Z; }}', + ) + return _guarded_export(toggle, + f'{{ Element->{field}[0] = {prop_name}.X;' + f' Element->{field}[1] = {prop_name}.Y;' + f' Element->{field}[2] = {prop_name}.Z; }}', + ) if ue_type == "FLinearColor": - return (f' if ({toggle}) {{ Element->{field}[0] = {prop_name}.R;' - f' Element->{field}[1] = {prop_name}.G;' - f' Element->{field}[2] = {prop_name}.B;' - f' Element->{field}[3] = {prop_name}.A; }}\n') + return _guarded_export(toggle, + f'{{ Element->{field}[0] = {prop_name}.R;' + f' Element->{field}[1] = {prop_name}.G;' + f' Element->{field}[2] = {prop_name}.B;' + f' Element->{field}[3] = {prop_name}.A; }}', + ) if ue_type == "FString": - return (f' if ({toggle} && !{prop_name}.IsEmpty())' - f' mjs_setString(Element->{field}, TCHAR_TO_UTF8(*{prop_name}));\n') + # MjSetString (Public/MuJoCo/Utils/MjUtils.h) internally skips empty + # FStrings, so the previous `!X.IsEmpty()` guard collapses into the + # helper. Toggle-guard stays. + return _guarded_export(toggle, f'MjSetString(Element->{field}, {prop_name});') if ue_type == "bool": - return f' if ({toggle}) Element->{field} = {prop_name} ? 1 : 0;\n' - return f' if ({toggle}) Element->{field} = {prop_name};\n' + return _guarded_export(toggle, f'Element->{field} = {prop_name} ? 1 : 0;') + return _guarded_export(toggle, f'Element->{field} = {prop_name};') # --- unit conversion ---------------------------------------------------------- @@ -425,25 +522,21 @@ def _emit_unit_conversion_export( return "" inner = "\n".join(branches) if is_array: - return ( - f" if ({toggle})\n" - f" {{\n" + body = ( f" for (int32 i = 0; i < {prop_name}.Num(); ++i)\n" f" {{\n" f" float V = {prop_name}[i];\n" f"{inner}\n" f" Element->{mjs_field}[i] = (mjtNum)V;\n" f" }}\n" - f" }}\n" ) - return ( - f" if ({toggle})\n" - f" {{\n" - f" float V = {prop_name};\n" - f"{inner}\n" - f" Element->{mjs_field} = (mjtNum)V;\n" - f" }}\n" - ) + else: + body = ( + f" float V = {prop_name};\n" + f"{inner}\n" + f" Element->{mjs_field} = (mjtNum)V;\n" + ) + return _guarded_export(toggle, body, multiline=True) def _emit_unit_conversion_block( @@ -493,12 +586,7 @@ def _apply(per_elem: str) -> str: if not branches: return "" body_lines = "\n".join(branches) - return ( - f" if ({toggle})\n" - f" {{\n" - f"{body_lines}\n" - f" }}\n" - ) + return _guarded_export(toggle, f"{body_lines}\n", multiline=True) def _emit_target_collation_import(prop_name: str, absorbs_attrs: Sequence[str]) -> str: @@ -524,28 +612,22 @@ def _emit_target_collation_import(prop_name: str, absorbs_attrs: Sequence[str]) def _emit_target_collation_export(prop_name: str, mjs_field: str) -> str: - return ( - f' if (!{prop_name}.IsEmpty()) ' - f'mjs_setString(Element->{mjs_field}, TCHAR_TO_UTF8(*{prop_name}));\n' - ) + # MjSetString skips empty FStrings internally; preserves the existing + # "only write when set" semantics without the explicit guard. + return f' MjSetString(Element->{mjs_field}, {prop_name});\n' def _emit_double_vec_export(attr: str, prop_name: str, mjs_field: str) -> str: """Emit export for an attr whose mjs counterpart is a ``mjDoubleVec*`` (std::vector*) — used by mjsKey for qpos/qvel/act/ctrl/mpos/mquat. - The mjs side requires ``->clear()`` + ``->push_back()`` per element, not - the standard ``Element->X[i] = X[i]`` pattern. Pre-condition: Element - field is non-null (mjs allocates the vector pointers on element create). + Delegates to ``MjSetDoubleVec`` (Public/MuJoCo/Utils/MjUtils.h) which + handles the ``clear() + push_back`` boilerplate. The helper accepts + a null Dest so we don't need the ``&& Element->X`` guard at the + call site. """ toggle = override_toggle_name(prop_name) - return ( - f" if ({toggle} && Element->{mjs_field})\n" - f" {{\n" - f" Element->{mjs_field}->clear();\n" - f" for (float V : {prop_name}) Element->{mjs_field}->push_back((double)V);\n" - f" }}\n" - ) + return f" if ({toggle}) MjSetDoubleVec(Element->{mjs_field}, {prop_name});\n" def _emit_data_packed_export(attr: str, packed_def: Dict[str, Any], @@ -568,7 +650,6 @@ def _emit_data_packed_export(attr: str, packed_def: Dict[str, Any], target = packed_def.get("target", "data") condition = packed_def.get("condition") toggle = override_toggle_name(prop_name) - inner_cond = toggle if condition is None else f"({condition}) && {toggle}" export_op_name = packed_def.get("export_op") op_body = "" @@ -580,23 +661,23 @@ def _emit_data_packed_export(attr: str, packed_def: Dict[str, Any], ) op_body = op["per_elem"] + def _wrap(body: str) -> str: + return _guarded_export(toggle, body, + extra_cond=condition, + extra_cond_first=True, + multiline=True) + if "slot" in packed_def: slot = packed_def["slot"] if op_body: - return ( - f" if ({inner_cond})\n" - f" {{\n" + body = ( f" float V = (float){prop_name};\n" f" {op_body}\n" f" Element->{target}[{slot}] = (mjtNum)V;\n" - f" }}\n" ) - return ( - f" if ({inner_cond})\n" - f" {{\n" - f" Element->{target}[{slot}] = (mjtNum){prop_name};\n" - f" }}\n" - ) + return _wrap(body) + body = f" Element->{target}[{slot}] = (mjtNum){prop_name};\n" + return _wrap(body) if "slot_range" in packed_def: start, end = packed_def["slot_range"] count = end - start @@ -605,27 +686,26 @@ def _emit_data_packed_export(attr: str, packed_def: Dict[str, Any], f"mjs_data_packed_attrs '{attr}': slot_range requires UE TArray; got {ue_type}" ) if op_body: - return ( - f" if ({inner_cond})\n" - f" {{\n" + body = ( f" for (int32 i = 0; i < {prop_name}.Num() && i < {count}; ++i)\n" f" {{\n" f" float V = {prop_name}[i];\n" f" {op_body}\n" f" Element->{target}[{start} + i] = (mjtNum)V;\n" f" }}\n" - f" }}\n" ) - return ( - f" if ({inner_cond})\n" - f" {{\n" + return _wrap(body) + body = ( f" for (int32 i = 0; i < {prop_name}.Num() && i < {count}; ++i)\n" f" Element->{target}[{start} + i] = (mjtNum){prop_name}[i];\n" - f" }}\n" ) + return _wrap(body) raise RuntimeError(f"mjs_data_packed_attrs '{attr}': must specify either 'slot' or 'slot_range'") +# `_resolve_value_map` lives in `_codegen_core`. + + def _emit_xml_enum_import(attr: str, enum_def: Dict[str, Any]) -> str: """Emit the XML-string -> URLab-enum mapping inside CODEGEN_IMPORT. @@ -640,29 +720,90 @@ def _emit_xml_enum_import(attr: str, enum_def: Dict[str, Any]) -> str: } """ ue_prop = enum_def["ue_property"] - value_map: Dict[str, Sequence[str]] = enum_def["value_map"] + value_map: Dict[str, Sequence[str]] = _resolve_value_map(attr, enum_def) has_toggle = enum_def.get("has_override_toggle", True) ue_enum_type = enum_def.get("ue_enum_type", "") lines: List[str] = [] lines.append(f' {{ // xml_enum: {attr} -> {ue_enum_type or ue_prop}') lines.append(f' FString S = Node->GetAttribute(TEXT("{attr}"));') lines.append(" S = S.ToLower();") + # Toggle fires only when a known XML value matched. A typo'd value + # (e.g. ``type="hindge"``) used to silently set the toggle on the + # UE-default enum value — misleadingly signalling "user overrode this" + # while actually masking the typo. + if has_toggle: + lines.append(" bool bMatched = false;") branches: List[str] = [] for xml_val, mapping in value_map.items(): - ue_enum_member = mapping[0] if isinstance(mapping, list) else mapping + ue_enum_member = mapping[0] prefix = "else if " if branches else "if " + match_assign = " bMatched = true;" if has_toggle else "" branches.append( - f' {prefix}(S == TEXT("{xml_val}")) {ue_prop} = ' - f'{ue_enum_type}::{ue_enum_member};' + f' {prefix}(S == TEXT("{xml_val}")) ' + f'{{ {ue_prop} = {ue_enum_type}::{ue_enum_member};{match_assign} }}' ) lines.extend(branches) if has_toggle: toggle = override_toggle_name(ue_prop) - lines.append(f" if (!S.IsEmpty()) {toggle} = true;") + lines.append(f" if (bMatched) {toggle} = true;") lines.append(" }") return "\n".join(lines) + "\n" +def emit_enum_switch( + discriminator: str, + enum_name: str, + cases: Sequence[Tuple[Any, str]], + *, + indent: str = " ", + default_break: bool = False, + default_body: Optional[str] = None, +) -> str: + """Emit ``switch (discriminator) { case Enum::M: ; break; ... }``. + + ``cases`` is a sequence of ``(member_or_members, body)`` pairs: + - When ``member_or_members`` is a ``str``, the case label + body + + break collapse onto one line: ``case Enum::M: ; break;``. + - When it is a sequence of strings (multi-key group, e.g. objtype + dispatch's BODY/XBODY → ``mjOBJ_BODY``), the case labels stack + and the body / break go on separate indented lines: + ``case Enum::A:`` + ``case Enum::B:`` + `` ;`` + `` break;`` + + ``default_break=True`` appends a single-line ``default: break;``. + ``default_body`` (when set) appends a multi-line ``default:`` arm + with that body. ``default_break`` is ignored if ``default_body`` is + given. + + All lines are prefixed with ``indent``; case labels use + ``indent + 4 spaces``; multi-line bodies use ``indent + 8 spaces``. + Result ends with a trailing newline. + """ + inner = indent + " " + body_indent = inner + " " + lines: List[str] = [] + lines.append(f"{indent}switch ({discriminator})") + lines.append(f"{indent}{{") + for members, body in cases: + if isinstance(members, str): + lines.append(f"{inner}case {enum_name}::{members}: {body}; break;") + continue + for m in members: + lines.append(f"{inner}case {enum_name}::{m}:") + lines.append(f"{body_indent}{body};") + lines.append(f"{body_indent}break;") + if default_body is not None: + lines.append(f"{inner}default:") + lines.append(f"{body_indent}{default_body};") + lines.append(f"{body_indent}break;") + elif default_break: + lines.append(f"{inner}default: break;") + lines.append(f"{indent}}}") + return "\n".join(lines) + "\n" + + def _emit_xml_enum_export(attr: str, enum_def: Dict[str, Any]) -> str: """Emit the URLab-enum -> mjt* / mjsField mapping inside CODEGEN_EXPORT. @@ -677,386 +818,535 @@ def _emit_xml_enum_export(attr: str, enum_def: Dict[str, Any]) -> str: """ ue_prop = enum_def["ue_property"] ue_enum_type = enum_def.get("ue_enum_type", "") - value_map: Dict[str, Sequence[str]] = enum_def["value_map"] + value_map: Dict[str, Sequence[str]] = _resolve_value_map(attr, enum_def) mjs_field = enum_def.get("mjs_field") if not mjs_field: return "" mjs_cast = enum_def.get("mjs_cast", "") has_toggle = enum_def.get("has_override_toggle", True) indent = " " if has_toggle else " " - lines: List[str] = [] - if has_toggle: - toggle = override_toggle_name(ue_prop) - lines.append(f" if ({toggle})") - lines.append(" {") - lines.append(f"{indent}switch ({ue_prop})") - lines.append(f"{indent}{{") + cases: List[Tuple[Any, str]] = [] for _, mapping in value_map.items(): if not isinstance(mapping, list) or len(mapping) < 2: raise RuntimeError( f"xml_enum {attr}: value_map entries must be [UE_enum, mj_const]; got {mapping!r}" ) ue_enum_member, mj_const = mapping[0], mapping[1] - cast_lhs = f"Element->{mjs_field}" cast_expr = f"({mjs_cast}){mj_const}" if mjs_cast else mj_const - lines.append( - f"{indent} case {ue_enum_type}::{ue_enum_member}: {cast_lhs} = {cast_expr}; break;" - ) - lines.append(f"{indent} default: break;") - lines.append(f"{indent}}}") + cases.append((ue_enum_member, f"Element->{mjs_field} = {cast_expr}")) + switch_body = emit_enum_switch( + ue_prop, ue_enum_type, cases, + indent=indent, default_break=True, + ) if has_toggle: - lines.append(" }") - return "\n".join(lines) + "\n" + toggle = override_toggle_name(ue_prop) + return _guarded_export(toggle, switch_body, multiline=True) + return switch_body -def _canon_property_block(canon_name: str, canon_def: Dict[str, Any], category_label: str) -> str: +def _canon_property_block(canon_name: str, canon_def: Dict[str, Any], + category_label: str, + hide_from_details: bool = False) -> str: prop = canon_def.get("emits_property") if not prop: return "" return _emit_uproperty(prop["name"], prop["type"], category_label, - sub_category=canon_name.replace("_", " ").title()) + sub_category=canon_name.replace("_", " ").title(), + hide_from_details=hide_from_details) -def _canon_import_block(canon_name: str, canon_def: Dict[str, Any], element_name: str = "") -> str: +# --------------------------------------------------------------------------- +# Canonicalisation registry +# +# Five canonicalisations collapse multiple raw MJCF attrs into one URLab +# property: spatial_pose (pos -> Pos), orientation (quat/euler/etc -> Quat), +# fromto_decompose (fromto -> Pos/Quat/size), body_sleep_policy (sleep -> +# SleepPolicy enum), actuator_transmission (joint/tendon/site/... -> +# TransmissionType + names). The previous design hard-coded each as an +# if-branch in _canon_import_block / _canon_export_block; a new rule +# entry without a matching branch silently dropped its emission. The +# registry below is the single source of truth. +# --------------------------------------------------------------------------- + + +def _canon_import_body_sleep_policy(canon_def, element_name) -> str: + return ( + ' { // canonicalize body.sleep -> EMjBodySleepPolicy + bOverride_SleepPolicy\n' + ' FString S = Node->GetAttribute(TEXT("sleep"));\n' + ' S = S.ToLower();\n' + ' if (S == TEXT("never")) { SleepPolicy = EMjBodySleepPolicy::Never; bOverride_SleepPolicy = true; }\n' + ' else if (S == TEXT("allowed")) { SleepPolicy = EMjBodySleepPolicy::Allowed; bOverride_SleepPolicy = true; }\n' + ' else if (S == TEXT("init")) { SleepPolicy = EMjBodySleepPolicy::InitAsleep; bOverride_SleepPolicy = true; }\n' + ' }\n' + ) + + +def _canon_import_actuator_transmission(canon_def, element_name) -> str: + return ( + ' { // canonicalize actuator transmission attrs\n' + ' FString TrnTarget;\n' + ' if (MjXmlUtils::ReadAttrString(Node, TEXT("joint"), TrnTarget))\n' + ' {\n' + ' TransmissionType = EMjActuatorTrnType::Joint;\n' + ' TargetName = TrnTarget;\n' + ' }\n' + ' if (MjXmlUtils::ReadAttrString(Node, TEXT("jointinparent"), TrnTarget))\n' + ' {\n' + ' TransmissionType = EMjActuatorTrnType::JointInParent;\n' + ' TargetName = TrnTarget;\n' + ' }\n' + ' if (MjXmlUtils::ReadAttrString(Node, TEXT("tendon"), TrnTarget))\n' + ' {\n' + ' TransmissionType = EMjActuatorTrnType::Tendon;\n' + ' TargetName = TrnTarget;\n' + ' }\n' + ' if (MjXmlUtils::ReadAttrString(Node, TEXT("site"), TrnTarget))\n' + ' {\n' + ' TransmissionType = EMjActuatorTrnType::Site;\n' + ' TargetName = TrnTarget;\n' + ' }\n' + ' if (MjXmlUtils::ReadAttrString(Node, TEXT("body"), TrnTarget))\n' + ' {\n' + ' TransmissionType = EMjActuatorTrnType::Body;\n' + ' TargetName = TrnTarget;\n' + ' }\n' + ' MjXmlUtils::ReadAttrString(Node, TEXT("refsite"), RefSite);\n' + ' // SliderSite must run AFTER the main-target reads so it\n' + ' // overrides the transmission type while preserving the\n' + ' // TargetName captured above (per MJCF: slider-crank carries\n' + ' // a main target attr PLUS slidersite).\n' + ' if (MjXmlUtils::ReadAttrString(Node, TEXT("slidersite"), SliderSite))\n' + ' {\n' + ' TransmissionType = EMjActuatorTrnType::SliderCrank;\n' + ' }\n' + ' }\n' + ) + + +def _canon_import_fromto_decompose(canon_def, element_name) -> str: + helper = canon_def["import_helper"] + cat_spec = canon_def.get("category_specifics", {}).get(element_name, {}) + z_slot_check = cat_spec.get("z_slot_check", "false") + return ( + f' {{ // canonicalize fromto -> Pos/Quat/size half-length\n' + f' FVector FTPos; FQuat FTQuat; float FTHalf = 0.f;\n' + f' if ({helper}(Node, FTPos, FTQuat, FTHalf))\n' + f' {{\n' + f' Pos = FTPos; bOverride_Pos = true;\n' + f' Quat = FTQuat; bOverride_Quat = true;\n' + f' const bool bFTZSlot = {z_slot_check};\n' + f' const int32 FTSlot = bFTZSlot ? 2 : 1;\n' + f' while (size.Num() <= FTSlot) {{ size.Add(-1.0f); }}\n' + f' size[FTSlot] = FTHalf;\n' + f' bOverride_size = true;\n' + f' }}\n' + f' }}\n' + ) + + +def _canon_import_orientation(canon_def, element_name) -> str: prop = canon_def.get("emits_property") helper = canon_def["import_helper"] - if canon_name == "body_sleep_policy": - # MJCF body.sleep is a string ("never"/"allowed"/"init"); map to URLab's - # EMjBodySleepPolicy. Absent attr leaves SleepPolicy at its default - # (Default = let the global option decide). - return ( - ' { // canonicalize body.sleep -> EMjBodySleepPolicy\n' - ' FString S = Node->GetAttribute(TEXT("sleep"));\n' - ' S = S.ToLower();\n' - ' if (S == TEXT("never")) SleepPolicy = EMjBodySleepPolicy::Never;\n' - ' else if (S == TEXT("allowed")) SleepPolicy = EMjBodySleepPolicy::Allowed;\n' - ' else if (S == TEXT("init")) SleepPolicy = EMjBodySleepPolicy::InitAsleep;\n' - ' }\n' - ) - if canon_name == "actuator_transmission": - # MJCF actuators encode transmission via {joint,tendon,site,body, - # jointinparent} (target name) + optional {slidersite, refsite}. - # Collapse into URLab's TransmissionType enum + Target/Slider/RefSite - # strings. First match wins (matches the legacy ordering). - return ( - ' { // canonicalize actuator transmission attrs\n' - ' FString TrnTarget;\n' - ' if (MjXmlUtils::ReadAttrString(Node, TEXT("joint"), TrnTarget))\n' - ' {\n' - ' TransmissionType = EMjActuatorTrnType::Joint;\n' - ' TargetName = TrnTarget;\n' - ' }\n' - ' if (MjXmlUtils::ReadAttrString(Node, TEXT("jointinparent"), TrnTarget))\n' - ' {\n' - ' TransmissionType = EMjActuatorTrnType::JointInParent;\n' - ' TargetName = TrnTarget;\n' - ' }\n' - ' if (MjXmlUtils::ReadAttrString(Node, TEXT("tendon"), TrnTarget))\n' - ' {\n' - ' TransmissionType = EMjActuatorTrnType::Tendon;\n' - ' TargetName = TrnTarget;\n' - ' }\n' - ' if (MjXmlUtils::ReadAttrString(Node, TEXT("slidersite"), SliderSite))\n' - ' {\n' - ' TransmissionType = EMjActuatorTrnType::SliderCrank;\n' - ' }\n' - ' if (MjXmlUtils::ReadAttrString(Node, TEXT("site"), TrnTarget))\n' - ' {\n' - ' TransmissionType = EMjActuatorTrnType::Site;\n' - ' TargetName = TrnTarget;\n' - ' }\n' - ' MjXmlUtils::ReadAttrString(Node, TEXT("refsite"), RefSite);\n' - ' if (MjXmlUtils::ReadAttrString(Node, TEXT("body"), TrnTarget))\n' - ' {\n' - ' TransmissionType = EMjActuatorTrnType::Body;\n' - ' TargetName = TrnTarget;\n' - ' }\n' - ' }\n' - ) - if canon_name == "fromto_decompose": - # MJCF's `fromto="x1 y1 z1 x2 y2 z2"` is decomposed into URLab's - # canonical Pos/Quat plus a half-length scalar that lands in either - # size[1] or size[2] of the codegen-owned TArray, depending on shape - # Type. Slots before the half-length slot are filled with the - # ``-1.0f`` sentinel so the per-attr export skips them (preserves - # the parent default class's radius / earlier-slot defaults — the - # fromto-only XML form does NOT specify the radius). - cat_spec = canon_def.get("category_specifics", {}).get(element_name, {}) - z_slot_check = cat_spec.get("z_slot_check", "false") - return ( - f' {{ // canonicalize fromto -> Pos/Quat/size half-length\n' - f' FVector FTPos; FQuat FTQuat; float FTHalf = 0.f;\n' - f' if ({helper}(Node, FTPos, FTQuat, FTHalf))\n' - f' {{\n' - f' Pos = FTPos; bOverride_Pos = true;\n' - f' Quat = FTQuat; bOverride_Quat = true;\n' - f' const bool bFTZSlot = {z_slot_check};\n' - f' const int32 FTSlot = bFTZSlot ? 2 : 1;\n' - f' while (size.Num() <= FTSlot) {{ size.Add(-1.0f); }}\n' - f' size[FTSlot] = FTHalf;\n' - f' bOverride_size = true;\n' - f' }}\n' - f' }}\n' - ) - if canon_name == "orientation": - # OrientationToMjQuat(Node, CompilerSettings, double OutQuat[4]) -> bool - # MjToUERotation applies the wxyz->xyzw reorder AND the X/Z sign-flip - # for the RHS-to-LHS handedness conversion. Storing the result in the - # UPROPERTY gives a valid UE-frame rotation usable by SetRelativeRotation - # and visible in the details panel. - return ( - f' {{ // canonicalize orientation (quat/euler/axisangle/xyaxes/zaxis)\n' - f' double TmpQuat[4] = {{1.0, 0.0, 0.0, 0.0}};\n' - f' if ({helper}(Node, CompilerSettings, TmpQuat))\n' - f' {{\n' - f' {prop["name"]} = MjUtils::MjToUERotation(TmpQuat);\n' - f' {override_toggle_name(prop["name"])} = true;\n' - f' }}\n' - f' }}\n' - ) - if canon_name == "spatial_pose": - # ReadVec3InMeters(Node, key, OutVec, bOutHasField) - return ( - f' {helper}(Node, TEXT("pos"), {prop["name"]}, {override_toggle_name(prop["name"])});\n' - ) + return ( + f' {{ // canonicalize orientation (quat/euler/axisangle/xyaxes/zaxis)\n' + f' double TmpQuat[4] = {{1.0, 0.0, 0.0, 0.0}};\n' + f' if ({helper}(Node, CompilerSettings, TmpQuat))\n' + f' {{\n' + f' {prop["name"]} = MjUtils::MjToUERotation(TmpQuat);\n' + f' {override_toggle_name(prop["name"])} = true;\n' + f' }}\n' + f' }}\n' + ) + + +def _canon_import_spatial_pose(canon_def, element_name) -> str: + prop = canon_def.get("emits_property") + helper = canon_def["import_helper"] + return ( + f' {helper}(Node, TEXT("pos"), {prop["name"]}, {override_toggle_name(prop["name"])});\n' + ) + + +def _canon_export_body_sleep_policy(canon_def) -> str: + return _guarded_export( + "bOverride_SleepPolicy", + " Element->sleep = static_cast(static_cast(SleepPolicy));\n", + multiline=True, + ) + + +def _canon_export_actuator_transmission(canon_def) -> str: + return ( + ' MjSetString(Element->target, TargetName);\n' + ' switch (TransmissionType)\n' + ' {\n' + ' case EMjActuatorTrnType::Joint: Element->trntype = mjTRN_JOINT; break;\n' + ' case EMjActuatorTrnType::JointInParent: Element->trntype = mjTRN_JOINTINPARENT; break;\n' + ' case EMjActuatorTrnType::SliderCrank: Element->trntype = mjTRN_SLIDERCRANK; break;\n' + ' case EMjActuatorTrnType::Tendon: Element->trntype = mjTRN_TENDON; break;\n' + ' case EMjActuatorTrnType::Site: Element->trntype = mjTRN_SITE; break;\n' + ' case EMjActuatorTrnType::Body: Element->trntype = mjTRN_BODY; break;\n' + ' default: Element->trntype = mjTRN_UNDEFINED; break;\n' + ' }\n' + ' if (TransmissionType == EMjActuatorTrnType::SliderCrank && !SliderSite.IsEmpty())\n' + ' {\n' + ' MjSetStringRaw(Element->slidersite, SliderSite);\n' + ' }\n' + ' if (TransmissionType == EMjActuatorTrnType::Site && !RefSite.IsEmpty())\n' + ' {\n' + ' MjSetStringRaw(Element->refsite, RefSite);\n' + ' }\n' + ) + + +def _canon_export_fromto_decompose(canon_def) -> str: + # fromto resolves to Pos/Quat/Size on import — those properties carry + # the values through to export via their own canonicalisations. return "" -def _canon_export_block(canon_name: str, canon_def: Dict[str, Any]) -> str: +def _canon_export_orientation(canon_def) -> str: prop = canon_def.get("emits_property") helper = canon_def.get("export_helper") - if canon_name == "body_sleep_policy": - # Only write to mjsBody.sleep when the user chose a non-Default policy. - # Default lets the global AAMjManager option decide. - return ( - ' if (SleepPolicy != EMjBodySleepPolicy::Default)\n' - ' {\n' - ' Element->sleep = static_cast(static_cast(SleepPolicy));\n' - ' }\n' - ) - if canon_name == "actuator_transmission": - # Write the URLab transmission state back to mjsActuator fields. Strings - # are only written when non-empty (mjs_setString must not be called on - # an empty FString — its TCHAR_TO_UTF8 buffer would dangle). - return ( - ' if (!TargetName.IsEmpty()) mjs_setString(Element->target, TCHAR_TO_UTF8(*TargetName));\n' - ' switch (TransmissionType)\n' - ' {\n' - ' case EMjActuatorTrnType::Joint: Element->trntype = mjTRN_JOINT; break;\n' - ' case EMjActuatorTrnType::JointInParent: Element->trntype = mjTRN_JOINTINPARENT; break;\n' - ' case EMjActuatorTrnType::SliderCrank: Element->trntype = mjTRN_SLIDERCRANK; break;\n' - ' case EMjActuatorTrnType::Tendon: Element->trntype = mjTRN_TENDON; break;\n' - ' case EMjActuatorTrnType::Site: Element->trntype = mjTRN_SITE; break;\n' - ' case EMjActuatorTrnType::Body: Element->trntype = mjTRN_BODY; break;\n' - ' default: Element->trntype = mjTRN_UNDEFINED; break;\n' - ' }\n' - ' if (TransmissionType == EMjActuatorTrnType::SliderCrank && !SliderSite.IsEmpty())\n' - ' {\n' - ' mjs_setString(Element->slidersite, TCHAR_TO_UTF8(*SliderSite));\n' - ' }\n' - ' if (TransmissionType == EMjActuatorTrnType::Site && !RefSite.IsEmpty())\n' - ' {\n' - ' mjs_setString(Element->refsite, TCHAR_TO_UTF8(*RefSite));\n' - ' }\n' - ) - if canon_name == "fromto_decompose": - # fromto resolves to Pos/Quat/Size on import — those properties carry - # the values through to export via their own canonicalisations. No - # export-side emission needed here. - return "" - if canon_name == "orientation": - return ( - f' if ({override_toggle_name(prop["name"])})\n' - f' {{\n' - f' double TmpQuat[4];\n' - f' {helper}({prop["name"]}, TmpQuat);\n' - f' Element->quat[0] = TmpQuat[0]; Element->quat[1] = TmpQuat[1];\n' - f' Element->quat[2] = TmpQuat[2]; Element->quat[3] = TmpQuat[3];\n' - f' }}\n' - ) - if canon_name == "spatial_pose": - return ( - f' if ({override_toggle_name(prop["name"])})\n' - f' {{\n' - f' double TmpPos[3];\n' - f' {helper}({prop["name"]}, TmpPos);\n' - f' Element->pos[0] = TmpPos[0]; Element->pos[1] = TmpPos[1]; Element->pos[2] = TmpPos[2];\n' - f' }}\n' - ) - return "" + return _guarded_export( + override_toggle_name(prop["name"]), + f' double TmpQuat[4];\n' + f' {helper}({prop["name"]}, TmpQuat);\n' + f' Element->quat[0] = TmpQuat[0]; Element->quat[1] = TmpQuat[1];\n' + f' Element->quat[2] = TmpQuat[2]; Element->quat[3] = TmpQuat[3];\n', + multiline=True, + ) -def emit_schema_for_attrs( - attrs: Sequence[str], - rules: Dict[str, Any], - element_name: str, - category_label: str, - *, - apply_canonicalizations: bool = True, - mjs_fields: set | None = None, - consumed_by_setto: set | None = None, -) -> EmittedSchema: - """Emit UPROPERTY + import/export blocks for a list of schema attrs. +def _canon_export_spatial_pose(canon_def) -> str: + prop = canon_def.get("emits_property") + helper = canon_def.get("export_helper") + return _guarded_export( + override_toggle_name(prop["name"]), + f' double TmpPos[3];\n' + f' {helper}({prop["name"]}, TmpPos);\n' + f' Element->pos[0] = TmpPos[0]; Element->pos[1] = TmpPos[1]; Element->pos[2] = TmpPos[2];\n', + multiline=True, + ) - Applies global exclusions, element exclusions, canonicalisation - absorption, and type mappings from `codegen_rules.json`. - Pass ``apply_canonicalizations=False`` when emitting for a subclass - in a category whose base class already owns the canonicalised - properties (e.g. site/tendon/equality subtypes in multi_uclass - layout, or geom subtypes that share base canonicalisations). - Raw canonicalised attrs (pos/quat/euler/etc.) are still excluded - so they don't re-appear as per-attr UPROPERTYs. +@dataclass(frozen=True) +class Canonicalisation: + """One canonicalisation's import + export emitters. Looked up by + canon name from `codegen_rules.json[canonicalizations]`. The + importer takes (canon_def, element_name) and returns C++ text; + the exporter takes (canon_def) and returns C++ text.""" + name: str + import_emitter: Callable[[Dict[str, Any], str], str] + export_emitter: Callable[[Dict[str, Any]], str] + + +_CANONICALISATIONS: Dict[str, Canonicalisation] = { + c.name: c for c in [ + Canonicalisation("body_sleep_policy", + _canon_import_body_sleep_policy, + _canon_export_body_sleep_policy), + Canonicalisation("actuator_transmission", + _canon_import_actuator_transmission, + _canon_export_actuator_transmission), + Canonicalisation("fromto_decompose", + _canon_import_fromto_decompose, + _canon_export_fromto_decompose), + Canonicalisation("orientation", + _canon_import_orientation, + _canon_export_orientation), + Canonicalisation("spatial_pose", + _canon_import_spatial_pose, + _canon_export_spatial_pose), + ] +} - ``consumed_by_setto`` is the set of schema attrs that will be packed - into the mjs spec by an ``mjs_setTo*`` call prepended to the export - block (see ``_emit_setto_call``). For those attrs, we suppress the - fallback "(skipped: mjs has no field)" comment to keep the emitted - file uncluttered. - """ - global_excl = set(rules.get("global_exclusions", [])) - type_map: Dict[str, str] = rules.get("type_mappings", {}) - default_type: str = rules.get("default_type", "float") - renames: Dict[str, str] = rules.get("property_renames", {}) - elem_rules: Dict[str, Any] = rules.get("element_rules", {}).get(element_name, {}) - elem_excl = set(elem_rules.get("exclude_attrs", [])) - elem_canons: List[str] = elem_rules.get("applies_canonicalizations", []) - canonicalizations: Dict[str, Any] = rules.get("canonicalizations", {}) +def _canon_import_block(canon_name: str, canon_def: Dict[str, Any], element_name: str = "") -> str: + entry = _CANONICALISATIONS.get(canon_name) + if entry is None: + _diag_add( + f"[diagnostic] canonicalization '{canon_name}' has a rule entry " + f"but no registry entry in _CANONICALISATIONS; per-element XML " + f"import for absorbed attrs will be silently dropped.", + source="canon_dispatch", + ) + return "" + return entry.import_emitter(canon_def, element_name) - # All attrs absorbed by an applied canonicalisation are silently excluded - # from per-attr emission (the canonicalisation owns them collectively). - canon_absorbed: set = set() - for c in elem_canons: - cd = canonicalizations.get(c) - if cd: - canon_absorbed.update(cd.get("absorbs_attrs", [])) - # If we're emitting a subtype and the base already owns the - # canonicalisations, suppress the canonicalised property block here. - # Raw absorbed attrs still excluded so they don't fall through to - # per-attr emission. - if not apply_canonicalizations: - elem_canons = [] +def _canon_export_block(canon_name: str, canon_def: Dict[str, Any]) -> str: + entry = _CANONICALISATIONS.get(canon_name) + if entry is None: + _diag_add( + f"[diagnostic] canonicalization '{canon_name}' has a rule entry " + f"but no registry entry in _CANONICALISATIONS; per-element mjs " + f"export for absorbed attrs will be silently dropped.", + source="canon_dispatch", + ) + return "" + return entry.export_emitter(canon_def) - props = "" - imports = "" - exports = "" - # 1) Canonicalisations first (so canonical properties appear at the top). +# --------------------------------------------------------------------------- +# Property-block emitters +# +# emit_schema_for_attrs used to inline both the canonicalisation property +# loop and the per-attr property loop. They're factored out here so the +# orchestration in emit_schema_for_attrs reads as "props + imports + +# exports" instead of one 400-line function. +# --------------------------------------------------------------------------- + + +def _emit_canon_property_block( + elem_canons: List[str], + canonicalizations: Dict[str, Any], + category_label: str, + hidden_canons: Set[str], +) -> str: + """Emit canonicalisation-owned UPROPERTY blocks at the top of the + component so the canonical authoring surface (Pos / Quat / etc) + appears first in the Details panel.""" + out = "" for c in elem_canons: cd = canonicalizations.get(c) if not cd: continue - props += _canon_property_block(c, cd, category_label) + out += _canon_property_block( + c, cd, category_label, + hide_from_details=(c in hidden_canons), + ) + return out + - # 2) Per-attribute properties. Attrs handled by xml_enum_attrs use a hand- - # declared URLab enum UPROPERTY; skip default per-attr UPROPERTY emission - # for those (codegen only owns the import/export mapping, not the decl). - xml_enum_attr_names: set = set(elem_rules.get("xml_enum_attrs", {}).keys()) +def _emit_per_attr_property_block( + attrs: Sequence[str], + elem_rules: Dict[str, Any], + type_map: Dict[str, str], + default_type: str, + renames: Dict[str, str], + category_label: str, + *, + global_excl: Set[str], + elem_excl: Set[str], + canon_absorbed: Set[str], + xml_enum_attr_names: Set[str], + hidden_attrs: Set[str], +) -> str: + """Emit per-attr UPROPERTY blocks (the bulk of the component's + Details panel). Attrs handled by xml_enum_attrs are skipped — those + use a hand-declared URLab enum UPROPERTY; codegen owns only the + import/export mapping. + + ``property_units`` lowers to UE-native ``Units="m"`` meta on numeric + scalars/structs; on TArray/FString/FLinearColor it lowers to a + custom ``MjUnit="m"`` meta tag the URLab detail customization reads + at runtime (UHT rejects Units on those types).""" prop_meta: Dict[str, str] = elem_rules.get("property_meta", {}) - for attr in attrs: - if attr in global_excl or attr in elem_excl or attr in canon_absorbed: - continue - if attr in xml_enum_attr_names: - continue + property_defaults: Dict[str, str] = elem_rules.get("property_defaults", {}) + property_units: Dict[str, str] = elem_rules.get("property_units", {}) + out = "" + for attr in iter_category_attrs(attrs, global_excl=global_excl, + elem_excl=elem_excl, + canon_absorbed=canon_absorbed, + extra_excl=xml_enum_attr_names): ue_type = type_map.get(attr, default_type) - prop_name = renames.get(attr, pascal_case(attr)) - props += _emit_uproperty( + prop_name = renames.get(attr, attr) + attr_meta_parts: List[str] = [] + if prop_meta.get(attr): + attr_meta_parts.append(prop_meta[attr]) + unit = property_units.get(attr) or property_units.get(prop_name) + if unit: + if _ue_type_accepts_units_meta(ue_type): + attr_meta_parts.append(f'Units="{unit}"') + else: + attr_meta_parts.append(f'MjUnit="{unit}"') + out += _emit_uproperty( prop_name, ue_type, category_label, - extra_meta=prop_meta.get(attr), + extra_meta=", ".join(attr_meta_parts) if attr_meta_parts else None, + default_override=property_defaults.get(attr) or property_defaults.get(prop_name), + hide_from_details=(attr in hidden_attrs or prop_name in hidden_attrs), + ) + return out + + +def _emit_xml_enum_property_decls( + elem_rules: Dict[str, Any], + category_label: str, + *, + apply_canonicalizations: bool, +) -> str: + """Emit UPROPERTY decls for xml_enum_attrs entries that opt in via + ``emit_property_decl: true``. URLab usually hand-declares the + UE-side enum properties (e.g. ``EMjJointType Type`` in MjJoint.h); + the codegen-owned path is reserved for cases where the rule author + wants the decl + initializer to live in the rule JSON. Only fires + on the BASE class emission (subclasses would shadow the base decl + and fail UHT). + + Per-rule ``property_default`` lets the enum decl take a real + initializer like ``EMjGainType::Fixed`` instead of the ``{}`` + fallback. A typo'd default (``"Fxed"``) surfaces as a codegen + diagnostic, not a misleading UHT compile error far downstream.""" + if not apply_canonicalizations: + return "" + out = "" + for attr, enum_def in elem_rules.get("xml_enum_attrs", {}).items(): + if not enum_def.get("emit_property_decl"): + continue + ue_prop = enum_def.get("ue_property") + ue_enum_type = enum_def.get("ue_enum_type") + if not ue_prop or not ue_enum_type: + continue + prop_default = enum_def.get("property_default") + if prop_default: + value_map = enum_def.get("value_map", {}) + valid_members = {m[0] for m in value_map.values() + if isinstance(m, (list, tuple)) and m} + if valid_members and prop_default not in valid_members: + _diag_add( + f"[diagnostic] xml_enum '{attr}' property_default " + f"'{prop_default}' is not in value_map UE members " + f"({sorted(valid_members)}); UPROPERTY default will " + f"fail UHT compile.", + source="property_default", + ) + full_default = ( + f"{ue_enum_type}::{prop_default}" if prop_default else None + ) + out += _emit_uproperty( + ue_prop, ue_enum_type, category_label, + extra_meta=enum_def.get("property_meta"), + default_override=full_default, ) + return out + + +def _emit_imports_block(ctx: EmissionContext) -> str: + """Emit the ``ImportFromXml`` body — every read-from-XML line. Order: + common imports prefix (name/class), xml_enum imports, per-attr + imports, canon imports, SetRelativeTransform driver, target- + collation imports, unit-conversion imports.""" + attrs = ctx.attrs + elem_rules = ctx.elem_rules + type_map = ctx.type_map + default_type = ctx.default_type + renames = ctx.renames + global_excl = ctx.global_excl + elem_excl = ctx.elem_excl + canon_absorbed = ctx.canon_absorbed + elem_canons = ctx.elem_canons + canonicalizations = ctx.canonicalizations + apply_canon = ctx.apply_canonicalizations + xml_enum_attr_names = ctx.xml_enum_attr_names + + imports = "" + + # 2a) Common imports prefix (name / class) — emits at the top. + _COMMON_IMPORT_FIELDS = {"name": "MjName", "class": "MjClassName"} + common_imports_list = elem_rules.get("common_imports", []) if apply_canon else [] + if common_imports_list: + common_block = "" + for entry in common_imports_list: + if isinstance(entry, str): + attr = entry + ue_field = _COMMON_IMPORT_FIELDS.get(attr, attr) + else: + attr = entry["attr"] + ue_field = entry.get("ue_field", _COMMON_IMPORT_FIELDS.get(attr, attr)) + common_block += ( + f' MjXmlUtils::ReadAttrString(Node, TEXT("{attr}"), {ue_field});\n' + ) + imports = common_block + imports - # 3a) XML enum attr imports run FIRST so downstream emission can depend - # on the resolved enum value (e.g. fromto_decompose reads Type to pick - # the size[] slot for the half-length write). URLab enums (EMjGeomType, - # EMjJointType, etc.) are hand-declared; codegen owns the string<->enum - # string map. - # - # Emission policy: emit xml_enum_attrs[attr] at this level if - # - attr is in the current attrs list (subtype-specific case like - # dcmotor.input — fires on the subtype's emission), OR - # - apply_canonicalizations=True (base-class emission) AND attr is in - # global_exclusions (always-emit-at-base case like joint.type — the - # attr is excluded from per-attr UPROPERTY emission but xml_enum - # owns its import/export). + # 3a) XML enum imports first (downstream emission can depend on the + # resolved enum value, e.g. fromto_decompose reads Type). xml_enum_attrs: Dict[str, Any] = elem_rules.get("xml_enum_attrs", {}) - def _should_emit_xml_enum(attr: str) -> bool: - if attr in attrs: - return True - if apply_canonicalizations and attr in global_excl: - return True - return False for attr, enum_def in xml_enum_attrs.items(): - if _should_emit_xml_enum(attr): + if _should_emit_xml_enum_at_this_layer( + attr, attrs, global_excl, apply_canonicalizations=apply_canon, + ): imports += _emit_xml_enum_import(attr, enum_def) - # 3b) Per-attribute import lines run BEFORE the canonicalisations so a - # canon like fromto_decompose can override individual slots (e.g. - # ``size[1] = halflength``) on top of the XML-provided values without - # being clobbered by a later per-attr read. - for attr in attrs: - if attr in global_excl or attr in elem_excl or attr in canon_absorbed: - continue - if attr in xml_enum_attr_names: - continue + # 3b) Per-attr imports. + vec3_convert_map: Dict[str, str] = elem_rules.get("vec3_convert", {}) + for attr in iter_category_attrs(attrs, global_excl=global_excl, + elem_excl=elem_excl, + canon_absorbed=canon_absorbed, + extra_excl=xml_enum_attr_names): ue_type = type_map.get(attr, default_type) - prop_name = renames.get(attr, pascal_case(attr)) - imports += _emit_import_line(attr, prop_name, ue_type) + prop_name = renames.get(attr, attr) + imports += _emit_import_line(attr, prop_name, ue_type, + vec3_convert=vec3_convert_map.get(attr)) - # 3c) Canonicalisations now run AFTER per-attr imports. + # 3c) Canon imports run AFTER per-attr so canons (fromto) can + # override individual slots. for c in elem_canons: cd = canonicalizations.get(c) if cd: - imports += _canon_import_block(c, cd, element_name=element_name) - - # 3d) Drive the UE component transform from the codegen-owned Pos/Quat - # UPROPERTYs. Every category that applies spatial_pose / orientation is - # USceneComponent-derived (body, frame, geom, site, camera, inertial, - # flexcomp) — pushing the just-read Pos/Quat onto the relative transform - # is what makes the SCS component visible in the right place. Pos is - # already in UE cm (ReadVec3InMeters applies MjToUEPosition) and Quat is - # already in UE frame (orientation canon applies MjToUERotation), so a - # straight assign is the right call. Skipped when apply_canonicalizations - # is False (subclass emission — base class already drove the transform). - if apply_canonicalizations: + imports += _canon_import_block(c, cd, element_name=ctx.element_name) + + # 3d) Drive the UE component transform from the codegen-owned + # Pos/Quat UPROPERTYs. + if apply_canon: if "spatial_pose" in elem_canons: imports += " if (bOverride_Pos) SetRelativeLocation(Pos);\n" if "orientation" in elem_canons: imports += " if (bOverride_Quat) SetRelativeRotation(Quat);\n" - # 4c) Target collations (e.g. mjsEquality.name1 absorbs body1/joint1/ - # tendon1/flex on the XML side). UE property is hand-declared (Obj1/Obj2 - # with dynamic GetOptions); codegen owns the first-non-empty import + - # mjs_setString export. + # 4c) Target-collation imports. target_collations: Dict[str, Any] = elem_rules.get("target_collations", {}) - if apply_canonicalizations: + if apply_canon: for prop_name, coll_def in target_collations.items(): imports += _emit_target_collation_import( prop_name, coll_def.get("absorbs_attrs", []) ) - # 4d) Unit conversions (e.g. joint.range: XML deg/m -> UPROPERTY UE - # deg/cm). Runs AFTER the default per-attr ReadAttr* so the converter - # operates on the freshly-read value. Each conversion entry is a - # data-driven dict; the converter ops live in _UNIT_CONVERT_OPS in the - # generator. Adding a new conversion is one Python dict entry — schema/ - # rules edits stay data-only. + # 4d) Unit-conversion imports. unit_conversions: Dict[str, Any] = elem_rules.get("unit_conversion", {}) for attr, conv_list in unit_conversions.items(): - if attr not in attrs and not apply_canonicalizations: + if attr not in attrs and not apply_canon: continue - prop_name = renames.get(attr, pascal_case(attr)) + prop_name = renames.get(attr, attr) ue_type = type_map.get(attr, default_type) is_array = ue_type.startswith("TArray") - imports += _emit_unit_conversion_block(prop_name, conv_list, side="import", is_array=is_array) - - # 5) Canonicalisation export lines (first — so they set the canonical - # MJ struct fields before any per-attr tweaks). Some elements opt out of - # specific canon exports via ``canon_export_skip`` (e.g. body's pos/quat - # are written by MjSpecWrapper::CreateBody from the UE transform, not - # from the Pos/Quat UPROPERTYs, so the spatial_pose/orientation export - # for body would overwrite the transform-based values with stale data). + imports += _emit_unit_conversion_block( + prop_name, conv_list, side="import", is_array=is_array, + ) + + return imports + + +def _emit_exports_block(ctx: EmissionContext) -> str: + """Emit the ``ExportTo`` body — every write-back-to-mjs line. Order: + canon exports, xml_enum exports, per-attr exports, data-packed + exports, target-collation exports, unit-conversion exports, double- + vec exports.""" + attrs = ctx.attrs + elem_rules = ctx.elem_rules + type_map = ctx.type_map + default_type = ctx.default_type + renames = ctx.renames + global_excl = ctx.global_excl + elem_excl = ctx.elem_excl + canon_absorbed = ctx.canon_absorbed + elem_canons = ctx.elem_canons + canonicalizations = ctx.canonicalizations + apply_canon = ctx.apply_canonicalizations + xml_enum_attr_names = ctx.xml_enum_attr_names + mjs_fields = ctx.mjs_fields + mjs_array_caps = ctx.mjs_array_caps or {} + consumed_by_setto = ctx.consumed_by_setto + attr_to_mjs_field = ctx.attr_to_mjs_field + + exports = "" + target_collations: Dict[str, Any] = elem_rules.get("target_collations", {}) + unit_conversions: Dict[str, Any] = elem_rules.get("unit_conversion", {}) + vec3_convert_map: Dict[str, str] = elem_rules.get("vec3_convert", {}) + + # 5) Canon exports first (set canonical mjs fields before per-attr + # tweaks). canon_export_skip opts an element out per-canon (e.g. + # body's pos/quat are written by MjSpecWrapper from the transform). canon_export_skip = set(elem_rules.get("canon_export_skip", [])) for c in elem_canons: if c in canon_export_skip: @@ -1065,166 +1355,174 @@ def _should_emit_xml_enum(attr: str) -> bool: if cd: exports += _canon_export_block(c, cd) - # 5b) XML enum attr exports (URLab enum -> mjt* via switch). Same emission - # policy as imports (see 3a): subtype-only attrs emit on the subtype that - # actually has the attr, globally-excluded "type"-like attrs emit on base. + # 5b) XML enum exports — same layer policy as imports (3a). + xml_enum_attrs: Dict[str, Any] = elem_rules.get("xml_enum_attrs", {}) for attr, enum_def in xml_enum_attrs.items(): - if _should_emit_xml_enum(attr): + if _should_emit_xml_enum_at_this_layer( + attr, attrs, global_excl, apply_canonicalizations=apply_canon, + ): exports += _emit_xml_enum_export(attr, enum_def) - # 6) Per-attribute export lines. Attrs handled by mjs_data_packed_attrs, - # mjs_double_vec_attrs, xml_enum_attrs, or unit_conversion are suppressed - # from the default per-attr emission — they each get their own - # specialised export block above or below. + # 6) Per-attr exports. data_packed_attrs: Dict[str, Any] = elem_rules.get("mjs_data_packed_attrs", {}) double_vec_attrs: List[str] = elem_rules.get("mjs_double_vec_attrs", []) double_vec_set: set = set(double_vec_attrs) - # Per-attr export-side slot sentinels. Used by the fromto canon for `size` - # — slots set to the sentinel value are skipped so the parent default's - # radius / earlier-slot value is preserved. sentinel_skip: Dict[str, str] = elem_rules.get("sentinel_skip_export", {}) - # Per-attr "import but don't export to mjs" list. Used when an mjsX - # field exists for an attr but URLab never registers the referenced - # asset in the spec (e.g. geom.material -> mjsGeom.material; URLab - # materials are UE-side assets, NOT mjsMaterial spec elements). The - # codegen import still populates the UPROPERTY so consumers can read - # the name for UE-side material lookups. export_skip_attrs: set = set(elem_rules.get("export_skip_attrs", [])) unit_convert_export_attrs: set = { a for a, convs in unit_conversions.items() - if any(c.get("export_op") for c in convs) + if any(cv.get("export_op") for cv in convs) } - # Per-element mjs field-name overrides. Used when MuJoCo's struct field - # name differs enough from the schema attr name that the auto-resolver - # in _resolve_mjs_field can't bridge it (e.g. camera "target" -> - # mjsCamera.targetbody, geom "shellinertia" -> mjsGeom.typeinertia). - attr_to_mjs_field: Dict[str, str] = elem_rules.get("attr_to_mjs_field", {}) - # Attrs absorbed by target_collations get a per-attr UPROPERTY on the - # import side (so the user can read them e.g. for the site-mode - # discriminator in equality), but on the export side their value - # already flows into the target spec via the collated Obj1/Obj2 -> - # name1/name2 writes. Skip per-attr export emission to avoid a - # misleading "(skipped: mjs has no field)" comment. target_collation_absorbed: set = set() - if apply_canonicalizations: + if apply_canon: for prop_name, coll_def in target_collations.items(): target_collation_absorbed.update(coll_def.get("absorbs_attrs", [])) - for attr in attrs: - if attr in global_excl or attr in elem_excl or attr in canon_absorbed: - continue - if attr in xml_enum_attr_names: - continue - if attr in data_packed_attrs and apply_canonicalizations: - continue - if attr in double_vec_set: - continue - if attr in unit_convert_export_attrs: - continue - if attr in export_skip_attrs: - continue - if attr in target_collation_absorbed: - continue + export_extra_excl: set = set(xml_enum_attr_names) + export_extra_excl |= double_vec_set + export_extra_excl |= unit_convert_export_attrs + export_extra_excl |= export_skip_attrs + export_extra_excl |= target_collation_absorbed + if apply_canon: + export_extra_excl |= set(data_packed_attrs.keys()) + for attr in iter_category_attrs(attrs, global_excl=global_excl, + elem_excl=elem_excl, + canon_absorbed=canon_absorbed, + extra_excl=export_extra_excl): ue_type = type_map.get(attr, default_type) - prop_name = renames.get(attr, pascal_case(attr)) + prop_name = renames.get(attr, attr) + # Cap export loops against the destination C array size so a + # narrower mjs field can't overrun. + resolved_field = _resolve_mjs_field( + attr, mjs_fields, attr_to_mjs_field, + ) if mjs_fields else (attr_to_mjs_field or {}).get(attr, attr) + array_cap = mjs_array_caps.get(resolved_field) exports += _emit_export_line( attr, prop_name, ue_type, mjs_fields=mjs_fields, slot_sentinel=sentinel_skip.get(attr), attr_to_mjs_field=attr_to_mjs_field, consumed_by_setto=consumed_by_setto, + vec3_convert=vec3_convert_map.get(attr), + array_cap=array_cap, ) - # 6b) Data-packed exports (e.g. mjsEquality.data[]). Run AFTER per-attr - # so any earlier mjsField writes are in place when these pack values in. - if apply_canonicalizations: + # 6b) Data-packed exports. + if apply_canon: for attr, packed_def in data_packed_attrs.items(): ue_type = type_map.get(attr, default_type) - prop_name = renames.get(attr, pascal_case(attr)) - exports += _emit_data_packed_export(attr, packed_def, ue_type, prop_name) + prop_name = renames.get(attr, attr) + exports += _emit_data_packed_export( + attr, packed_def, ue_type, prop_name, + ) - # 6d) Target collation exports (e.g. Obj1 -> mjs_setString(name1)). - if apply_canonicalizations: + # 6d) Target-collation exports. + if apply_canon: for prop_name, coll_def in target_collations.items(): - exports += _emit_target_collation_export(prop_name, coll_def["mjs_field"]) + exports += _emit_target_collation_export( + prop_name, coll_def["mjs_field"], + ) - # 6e) Unit-conversion exports (replace default per-attr export with a - # converting write — e.g. joint.range: UE deg -> mjs rad). + # 6e) Unit-conversion exports. for attr, conv_list in unit_conversions.items(): - if attr not in attrs and not apply_canonicalizations: + if attr not in attrs and not apply_canon: continue - prop_name = renames.get(attr, pascal_case(attr)) + prop_name = renames.get(attr, attr) ue_type = type_map.get(attr, default_type) is_array = ue_type.startswith("TArray") - # Resolve mjs field name (e.g. attr "solreflimit" -> "solref_limit"). - mjs_field = attr if mjs_fields: mjs_field = _resolve_mjs_field(attr, mjs_fields, attr_to_mjs_field) - exports += _emit_unit_conversion_export(prop_name, mjs_field, conv_list, is_array=is_array) + else: + mjs_field = (attr_to_mjs_field or {}).get(attr, attr) + exports += _emit_unit_conversion_export( + prop_name, mjs_field, conv_list, is_array=is_array, + ) - # 6c) Double-vec exports (mjsKey.qpos/qvel/etc — mjDoubleVec* not - # directly assignable, requires ->clear()+->push_back()). + # 6c) Double-vec exports. for attr in double_vec_attrs: - prop_name = renames.get(attr, pascal_case(attr)) - # mjs_field default = attr name; resolved via _resolve_mjs_field if mjs_fields is known. - mjs_field = attr + prop_name = renames.get(attr, attr) if mjs_fields: mjs_field = _resolve_mjs_field(attr, mjs_fields, attr_to_mjs_field) + else: + mjs_field = (attr_to_mjs_field or {}).get(attr, attr) exports += _emit_double_vec_export(attr, prop_name, mjs_field) - return EmittedSchema(properties_h=props, imports_cpp=imports, exports_cpp=exports) + return exports -def emit_xml_passthrough_body( +def emit_schema_for_attrs( attrs: Sequence[str], rules: Dict[str, Any], element_name: str, -) -> str: - """Emit the body of a `BuildSchemaAttrsXml() const -> FString` method. - - For categories with ``xml_passthrough_emission: true`` in their codegen - rule, the spec-registration path goes through an MJCF re-parse - (mj_parseXMLString + mjs_attach) instead of the mjs_addX API — flexcomp - is the canonical example because MuJoCo expands the flexcomp macro in - the XML parser, not the spec compiler. To keep new schema attrs - flowing end-to-end without hand-edits, the codegen emits a single - method that walks every override-tracked UPROPERTY and writes its - value as an ``name="value"`` XML attribute string. The hand-rolled - BuildFlexcompXml just calls this helper for the main attrs and - handles sub-elements (which the codegen doesn't model yet) itself. + category_label: str, + *, + apply_canonicalizations: bool = True, + mjs_fields: set | None = None, + consumed_by_setto: set | None = None, + mjs_array_caps: Dict[str, int] | None = None, +) -> EmittedSchema: + """Emit UPROPERTY + import/export blocks for a list of schema attrs. + + Applies global exclusions, element exclusions, canonicalisation + absorption, and type mappings from `codegen_rules.json`. - Attribute emission rules per UE type: - - float -> ` X="%f"` - - int -> ` X="%d"` - - bool -> ` X="true"` / ` X="false"` - - FString -> ` X="..."` (skipped when empty) - - TArray -> space-separated joined list - - FLinearColor -> ` X="r g b a"` - Canonicalised attrs (pos/quat) round-trip through MjUtils::UEToMjPosition - + ::UEToMjRotation (matching their export_helper in canonicalizations). - xml_enum_attrs write the XML-side string value selected by the enum. - - Output is the indented C++ statements (no signature, no braces) — the - caller wraps them in a method body. + Pass ``apply_canonicalizations=False`` when emitting for a subclass + in a category whose base class already owns the canonicalised + properties (e.g. site/tendon/equality subtypes in multi_uclass + layout, or geom subtypes that share base canonicalisations). + Raw canonicalised attrs (pos/quat/euler/etc.) are still excluded + so they don't re-appear as per-attr UPROPERTYs. + + ``consumed_by_setto`` is the set of schema attrs that will be packed + into the mjs spec by an ``mjs_setTo*`` call prepended to the export + block (see ``_emit_setto_call``). For those attrs, we suppress the + fallback "(skipped: mjs has no field)" comment to keep the emitted + file uncluttered. """ - global_excl = set(rules.get("global_exclusions", [])) - elem_rules = rules.get("element_rules", {}).get(element_name, {}) - elem_excl = set(elem_rules.get("exclude_attrs", [])) - elem_canons: List[str] = elem_rules.get("applies_canonicalizations", []) - canonicalizations = rules.get("canonicalizations", {}) - canon_absorbed: set = set() - for c in elem_canons: - cd = canonicalizations.get(c) - if cd: - canon_absorbed.update(cd.get("absorbs_attrs", [])) - xml_enum_attrs: Dict[str, Any] = elem_rules.get("xml_enum_attrs", {}) - type_map: Dict[str, str] = rules.get("type_mappings", {}) - default_type: str = rules.get("default_type", "float") - renames: Dict[str, str] = rules.get("property_renames", {}) + ctx = EmissionContext.from_call( + attrs, rules, element_name, + apply_canonicalizations=apply_canonicalizations, + mjs_fields=mjs_fields, + consumed_by_setto=consumed_by_setto, + mjs_array_caps=mjs_array_caps, + ) + elem_rules = ctx.elem_rules + hidden_canons: set = set(elem_rules.get("hidden_canon_properties", [])) + hidden_attrs: set = set(elem_rules.get("hidden_attrs", [])) + + props = ( + _emit_canon_property_block( + ctx.elem_canons, ctx.canonicalizations, + category_label, hidden_canons, + ) + + _emit_per_attr_property_block( + attrs, elem_rules, ctx.type_map, ctx.default_type, ctx.renames, + category_label, + global_excl=ctx.global_excl, elem_excl=ctx.elem_excl, + canon_absorbed=ctx.canon_absorbed, + xml_enum_attr_names=ctx.xml_enum_attr_names, + hidden_attrs=hidden_attrs, + ) + + _emit_xml_enum_property_decls( + elem_rules, category_label, + apply_canonicalizations=apply_canonicalizations, + ) + ) - lines: List[str] = [] - lines.append(" FString Out;") + imports = _emit_imports_block(ctx) + exports = _emit_exports_block(ctx) + + return EmittedSchema(properties_h=props, imports_cpp=imports, exports_cpp=exports) - # Canonicalisations first (pos -> "pos=\"x y z\"", quat -> "quat=...") + +def _emit_passthrough_canon_lines( + elem_canons: List[str], + canonicalizations: Dict[str, Any], +) -> List[str]: + """Emit ``pos="x y z"`` / ``quat="w x y z"`` formatters for the + canonicalisation-owned UPROPERTYs. Round-trips through the same + UEToMjPosition / UEToMjRotation helpers the canon export blocks + use, so the XML matches the spec write exactly.""" + lines: List[str] = [] for c in elem_canons: cd = canonicalizations.get(c) if not cd: @@ -1249,78 +1547,135 @@ def emit_xml_passthrough_body( lines.append(f" MjUtils::UEToMjRotation({prop}, Tmp);") lines.append(' Out += FString::Printf(TEXT(" quat=\\"%f %f %f %f\\""), Tmp[0], Tmp[1], Tmp[2], Tmp[3]);') lines.append(" }") + return lines - # xml_enum_attrs: emit the XML attribute string for the chosen enum value. + +def _emit_passthrough_xml_enum_lines( + xml_enum_attrs: Dict[str, Any], +) -> List[str]: + """Emit the per-attr if/else-if chain that picks the XML string for + the chosen enum value.""" + lines: List[str] = [] for attr, enum_def in xml_enum_attrs.items(): ue_prop = enum_def["ue_property"] ue_enum = enum_def["ue_enum_type"] - value_map = enum_def["value_map"] + value_map = _resolve_value_map(attr, enum_def) toggle = override_toggle_name(ue_prop) lines.append(f" if ({toggle})") lines.append(" {") first = True for xml_val, mapping in value_map.items(): - ue_member = mapping[0] if isinstance(mapping, list) else mapping + ue_member = mapping[0] prefix = "if " if first else "else if " first = False lines.append(f' {prefix}({ue_prop} == {ue_enum}::{ue_member}) ' f'Out += TEXT(" {attr}=\\"{xml_val}\\"");') lines.append(" }") + return lines - # Per-attr lines - for attr in attrs: - if attr in global_excl or attr in elem_excl or attr in canon_absorbed: - continue - if attr in xml_enum_attrs: - continue - if attr == "name": - # Name is written by the caller (it knows the prefix/MjName logic). - continue - prop_name = renames.get(attr, pascal_case(attr)) + +def _emit_passthrough_attr_line( + attr: str, prop_name: str, ue_type: str, toggle: str, +) -> List[str]: + """Emit the per-type XML-attr formatter line(s) for a single attr. + Returns a list of indented C++ lines (one for scalars, multiple + for TArray loops). Unknown types fall through with a TODO comment + so the build still compiles.""" + if ue_type == "FString": + return [f' if ({toggle} && !{prop_name}.IsEmpty()) ' + f'Out += FString::Printf(TEXT(" {attr}=\\"%s\\""), *{prop_name});'] + if ue_type == "bool": + return [f' if ({toggle}) ' + f'Out += FString::Printf(TEXT(" {attr}=\\"%s\\""), ' + f'{prop_name} ? TEXT("true") : TEXT("false"));'] + if ue_type == "int32": + return [f' if ({toggle}) ' + f'Out += FString::Printf(TEXT(" {attr}=\\"%d\\""), {prop_name});'] + if ue_type == "float": + return [f' if ({toggle}) ' + f'Out += FString::Printf(TEXT(" {attr}=\\"%f\\""), {prop_name});'] + if ue_type == "FLinearColor": + return [f" if ({toggle}) " + f'Out += FString::Printf(TEXT(" {attr}=\\"%f %f %f %f\\""), ' + f'{prop_name}.R, {prop_name}.G, {prop_name}.B, {prop_name}.A);'] + if ue_type.startswith("TArray 0)", + " {", + f' Out += TEXT(" {attr}=\\"");', + f" for (int32 i = 0; i < {prop_name}.Num(); ++i)", + " {", + ' if (i > 0) Out += TEXT(" ");', + f' Out += FString::Printf(TEXT("%f"), {prop_name}[i]);', + " }", + ' Out += TEXT("\\"");', + " }", + ] + if ue_type.startswith("TArray 0)", + " {", + f' Out += TEXT(" {attr}=\\"");', + f" for (int32 i = 0; i < {prop_name}.Num(); ++i)", + " {", + ' if (i > 0) Out += TEXT(" ");', + f' Out += FString::Printf(TEXT("%d"), {prop_name}[i]);', + " }", + ' Out += TEXT("\\"");', + " }", + ] + return [f' // TODO(xml_passthrough): unsupported UE type "{ue_type}" for attr "{attr}"'] + + +def emit_xml_passthrough_body( + attrs: Sequence[str], + rules: Dict[str, Any], + element_name: str, +) -> str: + """Emit the body of a `BuildSchemaAttrsXml() const -> FString` method. + + For categories with ``xml_passthrough_emission: true`` in their codegen + rule, the spec-registration path goes through an MJCF re-parse + (mj_parseXMLString + mjs_attach) instead of the mjs_addX API — flexcomp + is the canonical example because MuJoCo expands the flexcomp macro in + the XML parser, not the spec compiler. To keep new schema attrs + flowing end-to-end without hand-edits, the codegen emits a single + method that walks every override-tracked UPROPERTY and writes its + value as an ``name="value"`` XML attribute string. The hand-rolled + BuildFlexcompXml just calls this helper for the main attrs and + handles sub-elements (which the codegen doesn't model yet) itself. + + Output is the indented C++ statements (no signature, no braces) — + the caller wraps them in a method body. Per-type emission lives in + ``_emit_passthrough_attr_line``; canon + xml_enum live in their own + helpers. + """ + global_excl = set(rules.get("global_exclusions", [])) + elem_rules = rules.get("element_rules", {}).get(element_name, {}) + elem_excl = set(elem_rules.get("exclude_attrs", [])) + elem_canons: List[str] = elem_rules.get("applies_canonicalizations", []) + canonicalizations = rules.get("canonicalizations", {}) + canon_absorbed: set = compute_canon_absorbed(elem_canons, canonicalizations) + xml_enum_attrs: Dict[str, Any] = elem_rules.get("xml_enum_attrs", {}) + type_map: Dict[str, str] = rules.get("type_mappings", {}) + default_type: str = rules.get("default_type", "float") + renames: Dict[str, str] = rules.get("property_renames", {}) + + lines: List[str] = [" FString Out;"] + lines.extend(_emit_passthrough_canon_lines(elem_canons, canonicalizations)) + lines.extend(_emit_passthrough_xml_enum_lines(xml_enum_attrs)) + + # ``name`` is written by the caller (it knows the prefix / MjName + # logic). + passthrough_extra_excl = set(xml_enum_attrs) | {"name"} + for attr in iter_category_attrs(attrs, global_excl=global_excl, + elem_excl=elem_excl, + canon_absorbed=canon_absorbed, + extra_excl=passthrough_extra_excl): + prop_name = renames.get(attr, attr) ue_type = type_map.get(attr, default_type) toggle = override_toggle_name(prop_name) - - if ue_type == "FString": - lines.append(f' if ({toggle} && !{prop_name}.IsEmpty()) ' - f'Out += FString::Printf(TEXT(" {attr}=\\"%s\\""), *{prop_name});') - elif ue_type == "bool": - lines.append(f' if ({toggle}) ' - f'Out += FString::Printf(TEXT(" {attr}=\\"%s\\""), ' - f'{prop_name} ? TEXT("true") : TEXT("false"));') - elif ue_type == "int32": - lines.append(f' if ({toggle}) ' - f'Out += FString::Printf(TEXT(" {attr}=\\"%d\\""), {prop_name});') - elif ue_type == "float": - lines.append(f' if ({toggle}) ' - f'Out += FString::Printf(TEXT(" {attr}=\\"%f\\""), {prop_name});') - elif ue_type == "FLinearColor": - lines.append(f" if ({toggle}) " - f'Out += FString::Printf(TEXT(" {attr}=\\"%f %f %f %f\\""), ' - f'{prop_name}.R, {prop_name}.G, {prop_name}.B, {prop_name}.A);') - elif ue_type.startswith("TArray 0)") - lines.append(" {") - lines.append(f' Out += TEXT(" {attr}=\\"");') - lines.append(f" for (int32 i = 0; i < {prop_name}.Num(); ++i)") - lines.append(" {") - lines.append(' if (i > 0) Out += TEXT(" ");') - lines.append(f' Out += FString::Printf(TEXT("%f"), {prop_name}[i]);') - lines.append(" }") - lines.append(' Out += TEXT("\\"");') - lines.append(" }") - elif ue_type.startswith("TArray 0)") - lines.append(" {") - lines.append(f' Out += TEXT(" {attr}=\\"");') - lines.append(f" for (int32 i = 0; i < {prop_name}.Num(); ++i)") - lines.append(" {") - lines.append(' if (i > 0) Out += TEXT(" ");') - lines.append(f' Out += FString::Printf(TEXT("%d"), {prop_name}[i]);') - lines.append(" }") - lines.append(' Out += TEXT("\\"");') - lines.append(" }") - else: - lines.append(f' // TODO(xml_passthrough): unsupported UE type "{ue_type}" for attr "{attr}"') + lines.extend(_emit_passthrough_attr_line(attr, prop_name, ue_type, toggle)) lines.append(" return Out;") return "\n".join(lines) + "\n" @@ -1398,31 +1753,11 @@ class URLAB_API {ClassName} : public {BaseClassName} # Boundary-tag injection # --------------------------------------------------------------------------- -def _make_tag_pair(tag: str) -> Tuple[str, str]: - return (f"// --- CODEGEN_{tag}_START ---", f"// --- CODEGEN_{tag}_END ---") - - -def inject_between_tags(file_text: str, tag: str, new_inner: str) -> Tuple[str, bool]: - """Replace the content between ``// --- CODEGEN__START ---`` and - ``// --- CODEGEN__END ---`` with ``new_inner``. Returns - (new_text, was_found). If the tags are missing, returns the input - unchanged with was_found=False — callers decide whether that's - fatal.""" - start, end = _make_tag_pair(tag) - pattern = re.compile( - r"(" + re.escape(start) + r")(.*?)(" + re.escape(end) + r")", - re.DOTALL, - ) - matched = [False] - - def repl(m: re.Match) -> str: - matched[0] = True - # Preserve the start/end lines with a newline before the content. - body = "\n" + new_inner.rstrip() + "\n " - return m.group(1) + body + m.group(3) - - new_text = pattern.sub(repl, file_text) - return new_text, matched[0] +# Text-injection machinery lives in `_codegen_inject`. The symbols +# (`_make_tag_pair`, `_strip_cpp_braces_in_strings`, +# `_find_matching_brace`, `_check_brace_balance`, +# `inject_between_tags`, `_inject_tags_into_cpp`) are re-exported +# through the import block at the top of this file. # --------------------------------------------------------------------------- @@ -1446,35 +1781,28 @@ def codegen_owned_property_names(category: str, attrs: List[str], rules: Dict[st elem_excl = set(elem_rules.get("exclude_attrs", [])) elem_canons: List[str] = elem_rules.get("applies_canonicalizations", []) canonicalizations: Dict[str, Any] = rules.get("canonicalizations", {}) - canon_absorbed: set = set() + canon_absorbed: set = compute_canon_absorbed(elem_canons, canonicalizations) owned: set = set() for c in elem_canons: cdef = canonicalizations.get(c) if cdef: - canon_absorbed.update(cdef.get("absorbs_attrs", [])) prop = cdef.get("emits_property") if prop: owned.add(prop["name"]) - for a in attrs: - if a in global_excl or a in elem_excl or a in canon_absorbed: - continue - owned.add(renames.get(a, pascal_case(a))) + for a in iter_category_attrs(attrs, global_excl=global_excl, + elem_excl=elem_excl, + canon_absorbed=canon_absorbed): + owned.add(renames.get(a, a)) return owned -def all_owned_decl_names(props: set) -> set: - """Codegen-owned property names plus their ``bOverride_X`` toggles.""" - return props | {f"bOverride_{p}" for p in props} # --------------------------------------------------------------------------- # Pipeline: emit subclass files # --------------------------------------------------------------------------- -@dataclass -class FileWrite: - path: str - content: str +# `FileWrite` lives in `_codegen_core`. def _resolve_include_path(public_root: str, file_relpath: str) -> str: @@ -1486,6 +1814,91 @@ def _resolve_include_path(public_root: str, file_relpath: str) -> str: return rel.replace(os.sep, "/") +_BANNER_TEMPLATE_INCLUDES = { + "MuJoCo/Utils/MjXmlUtils.h", + "MuJoCo/Utils/MjOrientationUtils.h", + "MuJoCo/Utils/MjUtils.h", + "XmlNode.h", + "mujoco/mjspec.h", +} + + +def _audit_banner_safety(source_path: str, subtype: Dict[str, Any]) -> None: + """Scan an existing source file the codegen is ABOUT to overwrite via + ``fully_emitted: true`` and emit a diagnostic if it carries content + the template wouldn't reproduce (extra includes beyond the template + set, extra method definitions, ctor extras not in ``extra_constructor``). + + Non-fatal — the rewrite still proceeds. The diagnostic exists so a + rule author who flips ``fully_emitted: true`` without running the + audit helper sees a loud warning the next time the codegen runs. + """ + try: + with open(source_path, "r", encoding="utf-8") as f: + text = f.read() + except FileNotFoundError: + return + except OSError as e: + _diag_add( + f"[diagnostic] banner_overwrite: could not read '{source_path}' " + f"({e}) — skipping the pre-overwrite audit. The rewrite still " + f"proceeds, but any hand-edits in the existing file may be lost " + f"unnoticed.", + source="banner_overwrite", + ) + return + + rel = os.path.basename(source_path) + own_h = os.path.splitext(rel)[0] + ".h" + + # Extra includes beyond the template set. + extras = [] + for inc in re.findall(r'#include\s+"([^"]+)"', text): + if inc.endswith(own_h) or inc in _BANNER_TEMPLATE_INCLUDES: + continue + extras.append(inc) + if extras: + _diag_add( + f"[diagnostic] fully_emitted: true on '{subtype.get('class_name', rel)}' " + f"is about to OVERWRITE {rel} which has non-template includes " + f"{extras}. Run Scripts/codegen/_audit_banner_candidates.py " + f"before flipping, or revert fully_emitted on this subtype.", + source="banner_overwrite", + ) + + # Extra ctor lines beyond what the rule provides via extra_constructor. + # The ctor body can contain its own brace-bearing statements (range-for + # loops, init lists, nested ifs); use the brace-aware extractor so the + # diagnostic doesn't truncate at the first inner ``}`` and report a + # spurious "non-template ctor content". + expected = {subtype.get("extra_constructor", "").strip()} + expected.discard("") + class_name = subtype.get("class_name", "") + if class_name: + sig = re.search( + rf'{re.escape(class_name)}::{re.escape(class_name)}\(\)\s*\{{', + text, + ) + if sig: + open_idx = sig.end() - 1 + close_idx = _find_matching_brace(text, open_idx) + if close_idx is not None: + body = text[open_idx + 1:close_idx] + stripped = re.sub(r"(Type\s*=\s*EMj\w+::\w+;|//[^\n]*|\s+)", "", body) + for e in expected: + # The expected extras may themselves contain whitespace — + # strip to compare. + stripped = stripped.replace(re.sub(r"\s+", "", e), "") + if stripped: + _diag_add( + f"[diagnostic] fully_emitted: true on " + f"'{class_name}' is about to OVERWRITE the ctor in " + f"{rel} — non-template ctor content remains after " + f"stripping Type+extra_constructor: {stripped!r}.", + source="banner_overwrite", + ) + + def _subclass_constructor_body( category: str, subtype: Dict[str, Any], @@ -1558,8 +1971,9 @@ def _emit_setto_call( return "" if not mjspec or fn_name not in mjspec.get("setto_functions", {}): raise RuntimeError( - f"mjs_setTo* function '{fn_name}' not found in mjspec snapshot. " - f"Rebuild Scripts/mjspec_snapshot.json." + f"mjs_setTo* function '{fn_name}' not found in the projected " + f"mjspec. Rebuild the introspect snapshot via " + f"`python Scripts/codegen/build_introspect_snapshot.py`." ) sig = mjspec["setto_functions"][fn_name] if not sig["params"]: @@ -1684,6 +2098,32 @@ def _mjs_fields_for(cat_rules: Dict[str, Any], mjspec: Dict[str, Any] | None) -> return set(mjspec.get("structs", {}).get(struct_name, [])) +def _mjs_array_caps_for( + cat_rules: Dict[str, Any], + mjspec: Dict[str, Any] | None, +) -> Dict[str, int]: + """Pull {field_name: c_array_dim} for a category's mjs_struct from the + introspect snapshot, scoped to fixed-size C arrays only (skips scalars, + dynamic vectors, pointers). The TArray export loop uses these caps to + emit ``FMath::Min(prop.Num(), cap)`` so a future MuJoCo array-shrink + (e.g. ``gainprm[10]`` → ``gainprm[6]``) doesn't overrun memory. + """ + if not mjspec: + return {} + struct_name = cat_rules.get("mjs_struct") + if not struct_name: + return {} + introspect = mjspec.get("introspect") or {} + struct_table = introspect.get("structs", {}) + fields = struct_table.get(struct_name, {}).get("fields", []) + caps: Dict[str, int] = {} + for f in fields: + dim = f.get("array_dim") + if isinstance(dim, int) and dim > 1: + caps[f["name"]] = dim + return caps + + def emit_subclass_files( category: str, cat_rules: Dict[str, Any], @@ -1705,6 +2145,7 @@ def emit_subclass_files( base_header_relpath = cat_rules["base_class_header"] mjs_struct = cat_rules["mjs_struct"] mjs_fields = _mjs_fields_for(cat_rules, mjspec) + mjs_array_caps = _mjs_array_caps_for(cat_rules, mjspec) type_enum = cat_rules.get("type_enum_name") pub_dir = os.path.join(public_root, cat_rules.get("subclass_directory_pub", "")) priv_dir = os.path.join(private_root, cat_rules.get("subclass_directory_priv", "")) @@ -1726,12 +2167,12 @@ def emit_subclass_files( emitted = emit_schema_for_attrs( attrs, rules, element_name=category, - category_label=base_class.removeprefix("U"), + category_label=base_class.removeprefix("UMj"), apply_canonicalizations=False, # base owns the canon block mjs_fields=mjs_fields, consumed_by_setto=setto_consumed, + mjs_array_caps=mjs_array_caps, ) - owned = codegen_owned_property_names(category, attrs, rules) # Per-subtype ``mjs_setTo*`` preset call. Codegen owns this snippet — it # lands at the TOP of the CODEGEN_EXPORT block so every regeneration @@ -1760,21 +2201,69 @@ def emit_subclass_files( header_path = os.path.join(pub_dir, header_filename) source_path = os.path.join(priv_dir, class_file_stem + ".cpp") - if os.path.exists(header_path): + # ``fully_emitted: true`` on a subtype rule means codegen owns the + # entire file (header + source). Existing files get overwritten + # from the template every regen — equivalent to "delete and let + # the codegen recreate", but stable across runs. Use this for + # pure-stub subclasses (no extra includes, no extra methods, ctor + # only sets Type). The ``Scripts/codegen/_audit_banner_candidates.py`` + # helper identifies the safe subset. + fully_emitted = bool(subtype.get("fully_emitted")) + + if os.path.exists(header_path) and not fully_emitted: # Existing subclass file — inject between pre-prepped tags. + # Diagnose missing markers loudly so a typo in the marker pair + # (or a forgotten pre-prep step on a hand-rolled subclass) + # surfaces here rather than as wrong runtime behaviour. with open(header_path, "r", encoding="utf-8") as f: h_text = f.read() - h_text, _ = inject_between_tags(h_text, "PROPERTIES", emitted.properties_h) + h_text, _ = _inject_or_diag( + h_text, "PROPERTIES", emitted.properties_h, + host_path=header_path, host_kind="subclass header", + block_label="per-subtype UPROPERTY block", + diag_source="subclass_inject", + ) writes.append(FileWrite(path=header_path, content=h_text)) if os.path.exists(source_path): with open(source_path, "r", encoding="utf-8") as f: c_text = f.read() - c_text, _ = inject_between_tags(c_text, "IMPORT", emitted.imports_cpp) - c_text, _ = inject_between_tags(c_text, "EXPORT", emitted.exports_cpp) + c_text, _ = _inject_or_diag( + c_text, "IMPORT", emitted.imports_cpp, + host_path=source_path, host_kind="subclass source", + block_label="per-subtype import block", + diag_source="subclass_inject", + ) + c_text, _ = _inject_or_diag( + c_text, "EXPORT", emitted.exports_cpp, + host_path=source_path, host_kind="subclass source", + block_label="per-subtype export block", + diag_source="subclass_inject", + ) writes.append(FileWrite(path=source_path, content=c_text)) + else: + _diag_add( + f"[diagnostic] subclass source '{source_path}' does not " + f"exist alongside its header; import + export blocks " + f"could not be injected.", + source="subclass_inject", + ) else: - # Brand-new subclass file — emit from template. + # Brand-new file OR ``fully_emitted: true`` → write the whole + # file from the template. + # + # Safety check on the ``fully_emitted`` overwrite path: if the + # existing file carries non-template content (extra includes + # beyond the template, hand-written methods, ctor extras not + # covered by ``extra_constructor``), the rewrite would silently + # destroy it. The audit-helper script + # (Scripts/codegen/_audit_banner_candidates.py) is the + # expected pre-flip gate; this is a defence-in-depth diagnostic + # for cases where someone flips ``fully_emitted: true`` without + # running the helper first. + if fully_emitted and os.path.exists(source_path): + _audit_banner_safety(source_path, subtype) + include_path = _resolve_include_path(public_root, header_path) ctor_body = _subclass_constructor_body(category, subtype, type_enum) @@ -1825,24 +2314,17 @@ def emit_base_class_injection( base_class = cat_rules["base_class_name"] base_header_relpath = cat_rules["base_class_header"] mjs_fields = _mjs_fields_for(cat_rules, mjspec) - # Categories that opt out of schema-driven UPROPERTY/import/export - # emission entirely. Used for hand-rolled components that aren't yet - # ready for full codegen ownership (e.g. UMjFlexcomp). The snapshot - # still includes the element's schema attrs so the rest of the - # pipeline (e.g. completeness tests) can see them, but no C++ is - # emitted from this rule. - if cat_rules.get("disable_schema_emission"): - return writes + mjs_array_caps = _mjs_array_caps_for(cat_rules, mjspec) common_attrs = schema_attrs(schema, cat_rules["schema_common_block"]) # Extras: attrs that URLab puts on the base class even though MJCF # schema lists them per-subtype (e.g. gainprm/biasprm/dynprm). common_attrs = list(common_attrs) + cat_rules.get("schema_common_extra_attrs", []) emitted = emit_schema_for_attrs( - common_attrs, rules, element_name=category, category_label=base_class.removeprefix("U"), + common_attrs, rules, element_name=category, category_label=base_class.removeprefix("UMj"), mjs_fields=mjs_fields, + mjs_array_caps=mjs_array_caps, ) - owned = codegen_owned_property_names(category, common_attrs, rules) header_path = os.path.join(public_root, base_header_relpath) rel = os.path.relpath(header_path, public_root) @@ -1851,21 +2333,68 @@ def emit_base_class_injection( if os.path.exists(header_path): with open(header_path, "r", encoding="utf-8") as f: h_text = f.read() - new_h, ok = inject_between_tags(h_text, "PROPERTIES", emitted.properties_h) + new_h, ok = _inject_or_diag( + h_text, "PROPERTIES", emitted.properties_h, + host_path=header_path, host_kind="base header", + block_label=f"category '{category}' UPROPERTY block", + diag_source="base_inject", + ) if ok: writes.append(FileWrite(path=header_path, content=new_h)) + else: + _diag_add( + f"[diagnostic] category '{category}' has a rule but base header " + f"'{header_path}' does not exist; codegen emitted no writes for " + f"this category.", + source="base_inject", + ) if os.path.exists(source_path): with open(source_path, "r", encoding="utf-8") as f: c_text = f.read() - c_text, ok_i = inject_between_tags(c_text, "IMPORT", emitted.imports_cpp) - c_text, ok_e = inject_between_tags(c_text, "EXPORT", emitted.exports_cpp) + c_text, ok_i = _inject_or_diag( + c_text, "IMPORT", emitted.imports_cpp, + host_path=source_path, host_kind="base source", + block_label=f"category '{category}' import block", + diag_source="base_inject", + ) + # ``xml_passthrough_emission`` routes per-attr export through the + # XML_PASSTHROUGH block, NOT the EXPORT block — the mjs-side + # ``Element->field = ...`` writes don't apply (flexcomp). + # ``disable_mjs_export_emission`` covers categories that have no + # corresponding mjs struct so the export block can't compile even + # if injected (inertial — writes through ParentBody->ipos/iquat + # in a hand-rolled RegisterToSpec). Both flags suppress EXPORT + # injection AND its missing-marker diagnostic. + skip_export = ( + cat_rules.get("xml_passthrough_emission") + or cat_rules.get("disable_mjs_export_emission") + ) + ok_e = False + if not skip_export: + c_text, ok_e = _inject_or_diag( + c_text, "EXPORT", emitted.exports_cpp, + host_path=source_path, host_kind="base source", + block_label=f"category '{category}' export block", + diag_source="base_inject", + ) ok_x = False if cat_rules.get("xml_passthrough_emission"): xml_body = emit_xml_passthrough_body(common_attrs, rules, element_name=category) - c_text, ok_x = inject_between_tags(c_text, "XML_PASSTHROUGH", xml_body) + c_text, ok_x = _inject_or_diag( + c_text, "XML_PASSTHROUGH", xml_body, + host_path=source_path, host_kind="base source", + block_label=f"category '{category}' xml_passthrough block", + diag_source="base_inject", + ) if ok_i or ok_e or ok_x: writes.append(FileWrite(path=source_path, content=c_text)) + else: + _diag_add( + f"[diagnostic] category '{category}' base source '{source_path}' " + f"does not exist; import + export blocks could not be injected.", + source="base_inject", + ) return writes @@ -1914,6 +2443,7 @@ def emit_multi_uclass( base_class = cat_rules["base_class_name"] mjs_fields = _mjs_fields_for(cat_rules, mjspec) + mjs_array_caps = _mjs_array_caps_for(cat_rules, mjspec) common_attrs = set(schema_attrs(schema, cat_rules["schema_common_block"])) common_attrs |= set(cat_rules.get("schema_common_extra_attrs", [])) @@ -1923,15 +2453,36 @@ def emit_multi_uclass( attrs = [a for a in per_type_attrs if a not in common_attrs] emitted = emit_schema_for_attrs( attrs, rules, element_name=category, - category_label=base_class.removeprefix("U"), + category_label=base_class.removeprefix("UMj"), apply_canonicalizations=False, # base owns the canon block mjs_fields=mjs_fields, + mjs_array_caps=mjs_array_caps, ) type_tag = subtype["enum_value"] - h_text, _ = inject_between_tags(h_text, f"SUBCLASS_{type_tag}_PROPERTIES", emitted.properties_h) + # Diagnose missing per-subtype marker pairs ONLY when there's a + # non-empty body to inject. Subtypes whose schema attrs are entirely + # in the common set (or whose mjs export is handled elsewhere) emit + # nothing per-subtype; not pre-prepping a marker pair for those is + # legitimate, so suppress the diagnostic. + h_text, _ = _inject_or_diag( + h_text, f"SUBCLASS_{type_tag}_PROPERTIES", emitted.properties_h, + host_path=header_path, host_kind="multi_uclass base header", + block_label=f"subtype '{sub_key}' UPROPERTY block", + diag_source="multi_uclass_inject", + ) if c_text: - c_text, _ = inject_between_tags(c_text, f"SUBCLASS_{type_tag}_IMPORT", emitted.imports_cpp) - c_text, _ = inject_between_tags(c_text, f"SUBCLASS_{type_tag}_EXPORT", emitted.exports_cpp) + c_text, _ = _inject_or_diag( + c_text, f"SUBCLASS_{type_tag}_IMPORT", emitted.imports_cpp, + host_path=source_path, host_kind="multi_uclass base source", + block_label=f"subtype '{sub_key}' import block", + diag_source="multi_uclass_inject", + ) + c_text, _ = _inject_or_diag( + c_text, f"SUBCLASS_{type_tag}_EXPORT", emitted.exports_cpp, + host_path=source_path, host_kind="multi_uclass base source", + block_label=f"subtype '{sub_key}' export block", + diag_source="multi_uclass_inject", + ) # Rewrite the merged writes (drop stale base writes; replace with merged). writes = [w for w in writes if w.path != header_path and w.path != source_path] @@ -1951,12 +2502,32 @@ def _view_field_type_cpp(c_type: str) -> str: _MJ_M_MACRO_RE = re.compile(r"MJ_M\(\s*(\w+)\s*\)") +# Any MJ_*( ... ) macro that survives _expand_stride is an unhandled +# stride shape — emit invalid C++ in MjBind.h. The guard fires a +# diagnostic so a MuJoCo bump that introduces new stride macros (e.g. +# MJ_D(...) for mjData, MJ_V(...) for variable-size views) surfaces +# loudly rather than landing as a compile error far downstream. +_RESIDUAL_MJ_MACRO_RE = re.compile(r"\bMJ_[A-Z]\(\s*\w+\s*\)") def _expand_stride(stride: str) -> str: """Convert mjxmacro stride expressions to plain C++ expressions usable - in MjBind.h. ``MJ_M(nuser_jnt)`` -> ``m->nuser_jnt``.""" - return _MJ_M_MACRO_RE.sub(r"m->\1", stride) + in MjBind.h. ``MJ_M(nuser_jnt)`` -> ``m->nuser_jnt``. + + Fires a diagnostic if any ``MJ_*(...)`` macro survives the + substitution — that's an unhandled stride shape we'd otherwise + silently emit into MjBind.h verbatim.""" + expanded = _MJ_M_MACRO_RE.sub(r"m->\1", stride) + residual = _RESIDUAL_MJ_MACRO_RE.findall(expanded) + if residual: + _diag_add( + f"[diagnostic] _expand_stride saw stride '{stride}' with " + f"unhandled MuJoCo macro(s) {residual}. Result '{expanded}' " + f"will land in MjBind.h verbatim and likely fail to compile. " + f"Teach _expand_stride about the new macro shape.", + source="expand_stride", + ) + return expanded def emit_view_structs(rules: Dict[str, Any], mjxmacro: Dict[str, Any]) -> Dict[str, Tuple[str, str]]: @@ -1993,27 +2564,58 @@ def emit_view_structs(rules: Dict[str, Any], mjxmacro: Dict[str, Any]) -> Dict[s bind_lines.append(f" const int {var} = {expr};") # mjModel pointer fields. + # + # Stride-1 ``int`` entries (e.g. ``geom_type``, ``body_mocapid``, + # ``actuator_trntype``) are emitted as DEREFERENCED scalars rather + # than pointers — there's exactly one int per element, and the + # consumer always wants the value, not the pointer. Matches the + # ergonomic shape the hand-written MjBind.h had before activation. + # Mat-vec entries (``geom_size`` stride 3, ``jnt_solref`` stride + # mjNREF, etc.) stay as pointers since consumers index into them. for block in include_blocks: entries = mjxmacro["mjmodel_pointers"].get(block, []) index_var = block_index_var.get(block, "id") for entry in entries: name = entry["name"] - cpp_type = _view_field_type_cpp(entry["type"]) view_field = renames.get(name, name) stride = _expand_stride(entry["stride"]) - fields_lines.append(f" {cpp_type} {view_field};") - bind_lines.append( - f" {view_field} = m->{name} + {index_var} * {stride};" - ) + is_scalar_int = (entry["type"] == "int" and entry["stride"] == "1") + if is_scalar_int: + fields_lines.append(f" int {view_field};") + bind_lines.append( + f" {view_field} = m->{name}[{index_var}];" + ) + else: + cpp_type = _view_field_type_cpp(entry["type"]) + fields_lines.append(f" {cpp_type} {view_field};") + bind_lines.append( + f" {view_field} = m->{name} + {index_var} * {stride};" + ) # mjData fields (explicitly listed per view). + # + # Each spec dict has ``index_var`` + ``stride``. Some fields don't + # fit the simple ``d->src + index_var * stride`` formula — e.g. + # SensorView::sensordata, where the right slice depends on a + # bounds-checked sensor_adr lookup. For those, set ``bind_override`` + # in the rule to a C++ statement that assigns the field; the field + # decl is still emitted at the standard cpp_type. This kills the + # fragile "codegen emits wrong code, hand-written override after + # the marker" pattern. for data_name, spec in data_fields.items(): + # ``_note_*`` keys document the data_fields entries; skip them. + if data_name.startswith("_note_"): + continue cpp_type = "mjtNum*" view_field = renames.get(data_name, data_name) - index_var = spec.get("index_var", "id") - stride = _expand_stride(spec.get("stride", "1")) fields_lines.append(f" {cpp_type} {view_field};") - bind_lines.append(f" {view_field} = d->{data_name} + {index_var} * {stride};") + bind_override = spec.get("bind_override") + if bind_override: + bind_lines.append(f" {bind_override}") + else: + index_var = spec.get("index_var", "id") + stride = _expand_stride(spec.get("stride", "1")) + bind_lines.append(f" {view_field} = d->{data_name} + {index_var} * {stride};") fields_block = "\n".join(fields_lines) + ("\n" if fields_lines else "") bind_block = "\n".join(bind_lines) + ("\n" if bind_lines else "") @@ -2037,8 +2639,18 @@ def emit_bind_h_injection( views = emit_view_structs(rules, mjxmacro) new_text = text for view_name, (fields_block, bind_block) in views.items(): - new_text, _ = inject_between_tags(new_text, f"VIEW_{view_name}_FIELDS", fields_block) - new_text, _ = inject_between_tags(new_text, f"VIEW_{view_name}_BIND", bind_block) + new_text, _ = _inject_or_diag( + new_text, f"VIEW_{view_name}_FIELDS", fields_block, + host_path=bind_h_path, host_kind="MjBind.h", + block_label=f"view struct '{view_name}' fields block (struct will ship empty)", + diag_source="bind_inject", + ) + new_text, _ = _inject_or_diag( + new_text, f"VIEW_{view_name}_BIND", bind_block, + host_path=bind_h_path, host_kind="MjBind.h", + block_label=f"view '{view_name}' Bind() body", + diag_source="bind_inject", + ) with open(bind_h_path, "r", encoding="utf-8") as f: original = f.read() @@ -2048,12 +2660,55 @@ def emit_bind_h_injection( # --------------------------------------------------------------------------- -# Pipeline: schema-for-tests header (T3) +# Pipeline: schema-for-tests header # --------------------------------------------------------------------------- +def kept_props_for_category( + cat: str, cat_rules: Dict[str, Any], + schema: Dict[str, Any], rules: Dict[str, Any], +) -> List[str]: + """Return the ordered prop names the codegen will emit for one + category. Order matches the canonical emission order: canon- + owned properties first, then per-attr in schema order. xml_enum + attrs lower to their ``ue_property`` because that's the hand- + declared UPROPERTY the completeness test resolves against.""" + elem_rules = rules.get("element_rules", {}).get(cat, {}) + elem_excl = set(elem_rules.get("exclude_attrs", [])) + elem_canons: List[str] = elem_rules.get("applies_canonicalizations", []) + canonicalizations = rules.get("canonicalizations", {}) + canon_absorbed: set = compute_canon_absorbed(elem_canons, canonicalizations) + global_excl = set(rules.get("global_exclusions", [])) + renames: Dict[str, str] = rules.get("property_renames", {}) + xml_enum_attrs = elem_rules.get("xml_enum_attrs", {}) + + attrs = list(schema_attrs(schema, cat_rules["schema_common_block"])) + # ``schema_common_extra_attrs`` covers UPROPERTYs schema attrs miss + # (frame's pos/quat/childclass come via this path because frame.attrs + # is empty in the snapshot). + for a in cat_rules.get("schema_common_extra_attrs", []): + if a not in attrs: + attrs.append(a) + + kept: List[str] = [] + for c in elem_canons: + cd = canonicalizations.get(c) + if cd and cd.get("emits_property"): + kept.append(cd["emits_property"]["name"]) + for a in iter_category_attrs(attrs, global_excl=global_excl, + elem_excl=elem_excl, + canon_absorbed=canon_absorbed): + if a in xml_enum_attrs: + kept.append(xml_enum_attrs[a]["ue_property"]) + continue + kept.append(renames.get(a, a)) + return kept + + def emit_schema_for_tests(schema: Dict[str, Any], rules: Dict[str, Any]) -> FileWrite: """Generate a C++ header that exposes schema attribute lists per - category to URLab automation tests.""" + category to URLab automation tests. Every category emits a + ``CatProps()`` accessor returning a static ``TArray`` of + the codegen-owned UPROPERTY names.""" lines: List[str] = [ COPYRIGHT_BLOCK, "#pragma once", @@ -2068,64 +2723,8 @@ def emit_schema_for_tests(schema: Dict[str, Any], rules: Dict[str, Any]) -> File "{", ] - categories: Dict[str, Any] = rules.get("categories", {}) - global_excl = set(rules.get("global_exclusions", [])) - type_map = rules.get("type_mappings", {}) - default_type = rules.get("default_type", "float") - renames: Dict[str, str] = rules.get("property_renames", {}) - - for cat, cat_rules in categories.items(): - elem_rules = rules.get("element_rules", {}).get(cat, {}) - elem_excl = set(elem_rules.get("exclude_attrs", [])) - elem_canons: List[str] = elem_rules.get("applies_canonicalizations", []) - canonicalizations = rules.get("canonicalizations", {}) - canon_absorbed: set = set() - for c in elem_canons: - cd = canonicalizations.get(c) - if cd: - canon_absorbed.update(cd.get("absorbs_attrs", [])) - - # If schema emission is disabled for this category, the codegen - # produces no UPROPERTYs from the schema — so the completeness - # test shouldn't expect any. Emit an empty list and skip the - # rest of the per-attr accumulation. The category is still - # tracked (entry function still emitted) so call sites compile. - if cat_rules.get("disable_schema_emission"): - ident = cat.replace(".", "_") - lines.append(f" inline const TArray& {ident.title()}Props()") - lines.append(" {") - lines.append(" static const TArray P{};") - lines.append(" return P;") - lines.append(" }") - lines.append("") - continue - - attrs = list(schema_attrs(schema, cat_rules["schema_common_block"])) - # Extras live outside the schema block (e.g. frame.attrs doesn't - # exist in the snapshot; we provide pos/quat/childclass via - # schema_common_extra_attrs). Include them so the T3 completeness - # test asserts on the full property surface. - for a in cat_rules.get("schema_common_extra_attrs", []): - if a not in attrs: - attrs.append(a) - # xml_enum_attrs map schema-attr -> hand-declared UE enum UPROPERTY - # (e.g. camera.mode -> TrackingMode). Use the ue_property name in - # the schema-for-tests output so the completeness test resolves - # the actual UPROPERTY on the class. - xml_enum_attrs = elem_rules.get("xml_enum_attrs", {}) - kept_props: List[str] = [] - for c in elem_canons: - cd = canonicalizations.get(c) - if cd and cd.get("emits_property"): - kept_props.append(cd["emits_property"]["name"]) - for a in attrs: - if a in global_excl or a in elem_excl or a in canon_absorbed: - continue - if a in xml_enum_attrs: - kept_props.append(xml_enum_attrs[a]["ue_property"]) - continue - kept_props.append(renames.get(a, pascal_case(a))) - + for cat, cat_rules in rules.get("categories", {}).items(): + kept_props = kept_props_for_category(cat, cat_rules, schema, rules) ident = cat.replace(".", "_") joined = ", ".join(f'TEXT("{p}")' for p in kept_props) lines.append(f" inline const TArray& {ident.title()}Props()") @@ -2147,220 +2746,1286 @@ def emit_schema_for_tests(schema: Dict[str, Any], rules: Dict[str, Any]) -> File # Top-level orchestration # --------------------------------------------------------------------------- -def collect_all_writes( - schema: Dict[str, Any], - rules: Dict[str, Any], - mjxmacro: Dict[str, Any], - public_root: str, - private_root: str, - bind_h_path: str, - mjspec: Dict[str, Any] | None = None, -) -> List[FileWrite]: - """Walk every category in `codegen_rules.json` and produce the full set - of file writes the codegen would perform. No I/O side effects.""" - writes: List[FileWrite] = [] - categories: Dict[str, Any] = rules.get("categories", {}) +@dataclass +class PhaseContext: + """All state a codegen emission phase needs. Phases mutate + ``writes`` and surface diagnostics through ``_diag_add``.""" + schema: Dict[str, Any] + rules: Dict[str, Any] + mjxmacro: Dict[str, Any] + mjspec: Optional[Dict[str, Any]] + public_root: str + private_root: str + bind_h_path: str + writes: List["FileWrite"] - for cat, cat_rules in categories.items(): - layout = cat_rules.get("layout", "no_subclasses") - if layout == "single_uclass_per_file": - # Base class injection + N subclass files. - writes.extend(emit_base_class_injection(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) - writes.extend(emit_subclass_files(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) - elif layout == "multi_uclass": - writes.extend(emit_multi_uclass(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) - elif layout == "no_subclasses": - writes.extend(emit_base_class_injection(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) - bind_write = emit_bind_h_injection(rules, mjxmacro, bind_h_path) - if bind_write: - writes.append(bind_write) +@dataclass +class EmissionPhase: + """One step in the codegen pipeline. Phases are run in order; each + either appends to ``ctx.writes`` (emit phases) or has side effects + only (the diagnostics phase). The registry below makes adding a + phase a one-line insert rather than another `writes.extend(...)` + block in ``collect_all_writes``. + """ + name: str + fn: Callable[["PhaseContext"], None] - writes.append(emit_schema_for_tests(schema, rules)) - # Diagnostics: surface schema/snapshot drift that the rules don't yet - # account for. Stdout, not fatal — the codegen has emitted what it can; - # the operator reads these to know what manual rule edits are needed. - _emit_drift_diagnostics(schema, rules, mjspec) +# --------------------------------------------------------------------------- +# Synthetic categories: whole-file banner-mode emission +# --------------------------------------------------------------------------- +# +# "Synthetic" because the USTRUCT doesn't correspond to one entry in the +# MJCF schema (which describes XML element shapes). Instead it mirrors a +# C struct laid out in mjxmacro.h (MJOPTION_FIELDS, MJSTATISTIC_FIELDS, +# MJVISUAL_*_FIELDS) — the runtime-only state URLab exposes as USTRUCT +# blueprint properties. +# +# Files are emitted in BANNER mode (no // --- CODEGEN_*_START/END --- +# tags). The whole .h / .cpp pair is codegen-owned; hand-edits get +# clobbered on next regen. +# +# Rule shape (under top-level ``synthetic_categories`` in codegen_rules.json): +# "MjStatistic": { +# "ue_struct_name": "FMjStatistic", +# "mjxmacro_block": "MJSTATISTIC_FIELDS", +# "public_header": "MuJoCo/Generated/MjStatistic.h", +# "private_source": "MuJoCo/Generated/MjStatistic.cpp", +# "category_label": "MuJoCo|Statistic", +# "exclude_fields": [], +# "per_field_meta": { "extent": "ClampMin=0.0" }, +# "urlab_extra_fields": [], // empty for pure mirrors +# } + + +_CPP_TO_UE_TYPE = { + "int": "int32", + "float": "float", + "mjtNum": "double", + "mjtByte": "uint8", +} - return writes +def _ue_field_name(c_name: str) -> str: + """snake_case mjxmacro name -> PascalCase UE field. Preserves URLab's + naming convention from the hand-written MjSimOptions.h (ls_iterations + -> LsIterations, ccd_iterations -> CCD_Iterations is a deliberate + one-off — synthetic_categories rules can override via field_renames).""" + parts = c_name.split("_") + return "".join(p[:1].upper() + p[1:] for p in parts if p) -def _emit_drift_diagnostics(schema: Dict[str, Any], rules: Dict[str, Any], - mjspec: Dict[str, Any] | None) -> None: - """Print diagnostics that flag schema or mjspec drift the rules don't - cover. Run after every codegen pass so a MuJoCo version bump or a - schema-snapshot regen surfaces: - - - new top-level schema elements with no category in codegen_rules.json - - new actuator subtypes (entries in schema['actuator_types']) with no - rule under categories.actuator.subtypes - - new sensor subtypes ditto - - new mjs_setTo* function parameters not mapped by subtype_setto rules - - schema attrs whose UE type would fall back to default_type ("float") - because they're missing from type_mappings (catches when MuJoCo - adds a new attr like ``cellcount`` that we want a richer type for) - - Each item prints a one-line ``[diagnostic] ...`` hint with the file + - rule path the operator should edit. None of these are fatal because - the codegen is still useful in the partially-covered state. - """ - categories = rules.get("categories", {}) - msgs: List[str] = [] - - # 1) Top-level schema elements with no category coverage. - known_blocks = {c.get("schema_common_block", "").split(".", 1)[0] - for c in categories.values()} - known_blocks.discard("") - # Items like asset/contact/equality are nested containers that aren't - # categories themselves but whose children are bucketed elsewhere — they - # don't need their own category, so we ignore them here. - container_keys = { - "_meta", "actuator_common", "actuator_types", "sensor_common", - "sensor_types", "sensor_extras", "tendon", "equality", "contact", - "asset", "compiler", "option", "keyframe", "default", - } - # Schema elements URLab intentionally does NOT codegen (yet). Each - # entry comes with a one-line reason so the rule-file reader knows - # why it's silenced. New MuJoCo elements that aren't here will trigger - # a diagnostic. - unmodeled: Dict[str, str] = rules.get("intentionally_unmodeled_elements", {}) - for key in schema: - if key.startswith("_") or key in container_keys or key in known_blocks: + +# `_VEC3_CONVERT_FMT` lives in `_codegen_core`. + + +def _emit_synth_mirror_properties( + fields: List[Dict[str, Any]], + def_: Dict[str, Any], + category_label: str, +) -> Tuple[List[str], List[Dict[str, Any]]]: + """Emit the UPROPERTY block for the mjxmacro mirror fields and + return the parallel ``fields_meta`` list. ``fields_meta`` carries + the per-field shape (c_name, ue_name, ue_type, is_vec, count) the + out-of-line ApplyTo emitters need.""" + exclude = set(def_.get("exclude_fields", [])) + field_renames: Dict[str, str] = def_.get("field_renames", {}) + field_types: Dict[str, str] = def_.get("field_types", {}) + all_fields_type: Optional[str] = def_.get("all_fields_type") + field_defaults: Dict[str, str] = def_.get("field_defaults", {}) + + prop_lines: List[str] = [] + fields_meta: List[Dict[str, Any]] = [] + for f in fields: + c_name = f["name"] + if c_name in exclude: continue - if key in unmodeled: + ue_name = field_renames.get(c_name, _ue_field_name(c_name)) + c_type = f["type"] + is_vec = f.get("is_vec", False) + # Accept both str ("3") and int (3) — the mjxmacro snapshot + # currently emits strings, but a future shape bump that yields + # ints must NOT silently collapse vec3 fields to ``TArray``. + raw_count = f.get("count", 1) + if isinstance(raw_count, int): + count = raw_count + elif isinstance(raw_count, str) and raw_count.isdigit(): + count = int(raw_count) + else: + count = 1 + + if c_name in field_types: + ue_type = field_types[c_name] + elif all_fields_type: + ue_type = all_fields_type + elif is_vec and count == 3: + ue_type = "FVector" + elif is_vec and count == 4: + ue_type = "FLinearColor" + elif is_vec: + ue_type = "TArray" + else: + ue_type = _CPP_TO_UE_TYPE.get(c_type, "float") + + default_override = field_defaults.get(ue_name) or field_defaults.get(c_name) + + cat = f"MuJoCo|{category_label}" + toggle = override_toggle_name(ue_name) + default = default_override if default_override else _attr_default_value(ue_type) + prop_lines.append( + f' UPROPERTY(EditAnywhere, Category = "{cat}", meta=(InlineEditConditionToggle))\n' + f' bool {toggle} = false;\n\n' + f' UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "{cat}", meta=(EditCondition="{toggle}"))\n' + f' {ue_type} {ue_name} = {default};\n\n' + ) + fields_meta.append({ + "c_name": c_name, + "ue_name": ue_name, + "ue_type": ue_type, + "is_vec": is_vec, + "count": count, + }) + return prop_lines, fields_meta + + +def _emit_synth_extras_properties( + urlab_extras: List[Dict[str, Any]], + category_label: str, +) -> Tuple[List[str], List[Dict[str, Any]]]: + """Emit UPROPERTY blocks for the URLab-extra fields (non-mjxmacro + additions like ``MemoryMB`` on MjOption). Returns prop_lines + + extras_meta. Each extra carries optional ``has_override``, + ``edit_condition``, ``meta`` knobs that the mirror loop above + doesn't surface.""" + prop_lines: List[str] = [] + extras_meta: List[Dict[str, Any]] = [] + for extra in urlab_extras: + ue_name = extra["name"] + ue_type = extra["type"] + default = extra.get("default", _attr_default_value(ue_type)) + sub_category = extra.get("sub_category") + has_override = extra.get("has_override", True) + edit_condition = extra.get("edit_condition") + meta_extra = extra.get("meta") + cat = f"MuJoCo|{category_label}" + if sub_category: + cat = f"{cat}|{sub_category}" + if has_override: + toggle = override_toggle_name(ue_name) + meta_inner = f'EditCondition="{toggle}"' + if meta_extra: + meta_inner = f'{meta_inner}, {meta_extra}' + prop_lines.append( + f' UPROPERTY(EditAnywhere, Category = "{cat}", meta=(InlineEditConditionToggle))\n' + f' bool {toggle} = false;\n\n' + f' UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "{cat}", meta=({meta_inner}))\n' + f' {ue_type} {ue_name} = {default};\n\n' + ) + else: + meta_parts = [] + if edit_condition: + meta_parts.append(f'EditCondition="{edit_condition}"') + if meta_extra: + meta_parts.append(meta_extra) + meta_str = ", ".join(meta_parts) + meta_clause = f', meta=({meta_str})' if meta_str else "" + prop_lines.append( + f' UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "{cat}"{meta_clause})\n' + f' {ue_type} {ue_name} = {default};\n\n' + ) + extras_meta.append({"ue_name": ue_name, "type": ue_type, + "has_override": has_override}) + return prop_lines, extras_meta + + +def _emit_synth_inline_apply_template( + fields_meta: List[Dict[str, Any]], + field_skip_apply: Set[str], +) -> str: + """Emit the templated inline ``ApplyTo`` body for pure-mirror + synthetic structs (mjStatistic etc.). The shape mirrors the + out-of-line ApplyToSpec but lives in the header so it's reusable + against any compatible C struct (mjStatistic, mjVisualRgba).""" + apply_lines: List[str] = [] + for fm in fields_meta: + c_name = fm["c_name"] + ue_name = fm["ue_name"] + if c_name in field_skip_apply: continue - msgs.append( - f"[diagnostic] schema has top-level element '{key}' but no " - f"category in codegen_rules.json (rules['categories']). " - f"Either add a category entry, list '{key}' in " - f"container_keys, or add an " - f"'intentionally_unmodeled_elements' entry explaining why " - f"it's skipped." + if fm["ue_type"] == "FLinearColor": + apply_lines.append( + f" Dst.{c_name}[0] = static_cast({ue_name}.R);\n" + f" Dst.{c_name}[1] = static_cast({ue_name}.G);\n" + f" Dst.{c_name}[2] = static_cast({ue_name}.B);\n" + f" Dst.{c_name}[3] = static_cast({ue_name}.A);" + ) + elif fm["ue_type"] == "FVector": + apply_lines.append( + f" Dst.{c_name}[0] = static_cast({ue_name}.X);\n" + f" Dst.{c_name}[1] = static_cast({ue_name}.Y);\n" + f" Dst.{c_name}[2] = static_cast({ue_name}.Z);" + ) + elif fm["is_vec"]: + apply_lines.append( + f" for (int32 I = 0; I < {ue_name}.Num() && I < {fm['count']}; ++I)\n" + f" Dst.{c_name}[I] = static_cast({ue_name}[I]);" + ) + else: + apply_lines.append(f" Dst.{c_name} = static_cast({ue_name});") + return ( + f" /** @brief Mirror every field into a runtime C struct. */\n" + f" template \n" + f" void ApplyTo(TDst& Dst) const\n" + f" {{\n" + f"{chr(10).join(apply_lines)}\n" + f" }}\n" + ) + + +def _emit_synthetic_struct_files( + cat_name: str, def_: Dict[str, Any], mjxmacro: Dict[str, Any], + public_root: str, private_root: str, +) -> List["FileWrite"]: + """Emit the .h + .cpp pair for one synthetic_categories entry. + + Currently supports the mjxmacro_block source (X-macro field list). + """ + block_name = def_.get("mjxmacro_block") + if not block_name: + return [] + fields = mjxmacro.get("struct_fields", {}).get(block_name, []) + if not fields: + _diag_add( + f"[diagnostic] synthetic_categories['{cat_name}'] references " + f"mjxmacro_block='{block_name}' which is empty or missing in " + f"the snapshot. Skipping emission.", + source="synthetic_categories", ) + return [] - # 2) Actuator subtypes not mapped. - act_cat = categories.get("actuator", {}) - known_act_subs = {s.get("key") for s in act_cat.get("subtypes", [])} - for name in schema.get("actuator_types", {}): - if name not in known_act_subs: - msgs.append( - f"[diagnostic] schema actuator subtype '{name}' has no " - f"entry in categories.actuator.subtypes. Add a subtype " - f"+ subtype_setto rule pair so codegen emits the UMj" - f"{name.title()}Actuator class." + ue_struct = def_["ue_struct_name"] + category_label = def_.get("category_label", "MuJoCo") + field_apply_mode: Dict[str, str] = def_.get("field_apply_to_spec_mode", {}) + field_skip_apply: set = set(def_.get("field_skip_apply", [])) + public_relpath = def_["public_header"] + private_relpath = def_.get("private_source") + extra_includes: List[str] = def_.get("include_directives", []) + urlab_extras: List[Dict[str, Any]] = def_.get("urlab_extra_fields", []) + apply_extras_function: Optional[str] = def_.get("apply_extras_function") + emit_apply_methods: bool = bool(def_.get("emit_apply_methods", False)) + + mirror_lines, fields_meta = _emit_synth_mirror_properties( + fields, def_, category_label, + ) + extras_lines, _extras_meta = _emit_synth_extras_properties( + urlab_extras, category_label, + ) + properties_block = "".join(mirror_lines + extras_lines) + c_struct = def_.get("c_struct_type", block_name.lower().replace("_fields", "")) + + # ---------- header content ---------- + extra_includes_block = "".join(f'#include "{inc}"\n' for inc in extra_includes) + header_basename = os.path.basename(public_relpath).replace('.h', '') + public_path = os.path.join(public_root, public_relpath.replace("/", os.sep)) + + # Method decls in the header. If emit_apply_methods=True, declare + # ApplyToSpec / ApplyOverridesToModel as forward decls (definitions + # land in the .cpp). Otherwise emit an inline-templated ApplyTo for + # pure-mirror structs (mjStatistic etc.). + if emit_apply_methods: + method_decls = ( + f" /** @brief Writes every mirror field plus URLab extras into the " + f"runtime spec. Used by articulations to set child spec options. */\n" + f" void ApplyToSpec(mjSpec* Spec) const;\n\n" + f" /** @brief Applies only override-toggled mirror fields to a " + f"compiled model (post-compile override path). */\n" + f" void ApplyOverridesToModel(mjModel* Model) const;\n" + ) + else: + method_decls = _emit_synth_inline_apply_template( + fields_meta, field_skip_apply, + ) + + # Forward-decl the extras function so the codegen-emitted .cpp can + # call it without #including a hand-written header. Operator writes + # the body in *Extras.cpp. + extras_forward_decl = "" + if apply_extras_function and urlab_extras: + extras_forward_decl = ( + f"// Forward-decl: hand-written body lives in " + f"{os.path.basename(public_relpath).replace('.h', '')}Extras.cpp.\n" + f"struct {ue_struct};\n" + f"void {apply_extras_function}(" + f"mjOption* Opt, const {ue_struct}& Self, " + f"mjSpec* Spec, mjModel* Model = nullptr);\n\n" + ) + + header_content = ( + f"{COPYRIGHT_BLOCK}\n" + f"#pragma once\n\n" + f"#include \"CoreMinimal.h\"\n" + f"{extra_includes_block}" + f"#include \"{header_basename}.generated.h\"\n\n" + f"{extras_forward_decl}" + f"// Mirror of MuJoCo's ``{c_struct}`` ({block_name}). Codegen-owned —\n" + f"// hand-edits get clobbered on next regen. Add fields by editing\n" + f"// codegen_rules.json[synthetic_categories.{cat_name}].\n" + f"USTRUCT(BlueprintType)\n" + f"struct URLAB_API {ue_struct}\n" + f"{{\n" + f" GENERATED_BODY()\n\n" + f"{properties_block}" + f"{method_decls}" + f"}};\n" + ) + + writes: List[FileWrite] = [FileWrite(path=public_path, content=header_content)] + + if emit_apply_methods and private_relpath: + cpp_content = _emit_synth_apply_methods_cpp( + ue_struct=ue_struct, + fields_meta=fields_meta, + field_apply_mode=field_apply_mode, + field_skip_apply=field_skip_apply, + apply_extras_function=apply_extras_function, + urlab_extras=urlab_extras, + public_relpath=public_relpath, + header_basename=header_basename, + ) + private_path = os.path.join(private_root, private_relpath.replace("/", os.sep)) + writes.append(FileWrite(path=private_path, content=cpp_content)) + + return writes + + +def _emit_synth_apply_methods_cpp( + *, + ue_struct: str, + fields_meta: List[Dict[str, Any]], + field_apply_mode: Dict[str, str], + field_skip_apply: Set[str], + apply_extras_function: Optional[str], + urlab_extras: List[Dict[str, Any]], + public_relpath: str, + header_basename: str, +) -> str: + """Emit the out-of-line ``ApplyToSpec`` and ``ApplyOverridesToModel`` + bodies for a synthetic struct whose mirror writes go through mjSpec + + mjModel (mjOption is the canonical case). + + Both methods gate every field write with ``bOverride_X``. The earlier + ``unconditional`` SPEC default silently clobbered MJCF-XML defaults + with whatever the UE struct happened to carry, even for fields the + user never authored. ``field_apply_mode`` now selects only the + per-FVector conversion flavour (``vec3_cm`` / ``vec3_y_flip`` / + ``pos``); the toggle guard is applied uniformly. + """ + apply_to_spec_lines: List[str] = [" if (!Spec) return;"] + apply_to_model_lines: List[str] = [" if (!Model) return;"] + for fm in fields_meta: + c_name = fm["c_name"] + ue_name = fm["ue_name"] + ue_type = fm["ue_type"] + if c_name in field_skip_apply: + continue + toggle = override_toggle_name(ue_name) + spec_mode = field_apply_mode.get(c_name, "") + if ue_type == "FVector": + # Strip a legacy "guarded_" prefix; the guard is now uniform. + conv = spec_mode.replace("guarded_", "") if spec_mode.startswith("guarded_") else spec_mode + if conv not in _VEC3_CONVERT_FMT: + conv = "vec3_y_flip" + stmt_spec_inner = _VEC3_CONVERT_FMT[conv].format( + c=f"Spec->option.{c_name}", ue=ue_name, + ) + stmt_model_inner = _VEC3_CONVERT_FMT[conv].format( + c=f"Model->opt.{c_name}", ue=ue_name, ) + elif ue_type.startswith("EMj"): + stmt_spec_inner = f"Spec->option.{c_name} = static_cast({ue_name});" + stmt_model_inner = f"Model->opt.{c_name} = static_cast({ue_name});" + else: + stmt_spec_inner = f"Spec->option.{c_name} = {ue_name};" + stmt_model_inner = f"Model->opt.{c_name} = {ue_name};" + + apply_to_spec_lines.append(f" if ({toggle}) {{ {stmt_spec_inner} }}") + apply_to_model_lines.append(f" if ({toggle}) {{ {stmt_model_inner} }}") + + if apply_extras_function and urlab_extras: + # Spec / Model already null-checked by the early return at the + # top of each body, so the ternary is dead — pass the address + # directly. + apply_to_spec_lines.append( + f" {apply_extras_function}(&Spec->option, *this, Spec);" + ) + apply_to_model_lines.append( + f" {apply_extras_function}(&Model->opt, *this, nullptr, Model);" + ) - # 3) Sensor subtypes not mapped. - sens_cat = categories.get("sensor", {}) - known_sens_subs = {s.get("key") for s in sens_cat.get("subtypes", [])} - for name in schema.get("sensor_types", []): - if name not in known_sens_subs: - msgs.append( - f"[diagnostic] schema sensor type '{name}' has no entry " - f"in categories.sensor.subtypes. Add it so the per-sensor " - f"UMjXSensor subclass is emitted." + return ( + f"{COPYRIGHT_BLOCK}\n" + f"#include \"{os.path.dirname(public_relpath).replace(os.sep, '/')}/{header_basename}.h\"\n" + f"#include \n\n" + f"void {ue_struct}::ApplyToSpec(mjSpec* Spec) const\n" + f"{{\n" + + "\n".join(apply_to_spec_lines) + "\n" + f"}}\n\n" + f"void {ue_struct}::ApplyOverridesToModel(mjModel* Model) const\n" + f"{{\n" + + "\n".join(apply_to_model_lines) + "\n" + f"}}\n" + ) + + +def _phase_synthetic_categories(ctx: PhaseContext) -> None: + """Run after the main category walk; emits whole-file synthetic structs.""" + synth = ctx.rules.get("synthetic_categories", {}) + for cat_name, def_ in synth.items(): + # Skip _note_* sibling keys used for inline documentation. + if cat_name.startswith("_") or not isinstance(def_, dict): + continue + ctx.writes.extend(_emit_synthetic_struct_files( + cat_name, def_, ctx.mjxmacro, ctx.public_root, ctx.private_root, + )) + + +# --------------------------------------------------------------------------- +# Sensor switch + TagToType codegen +# --------------------------------------------------------------------------- +# +# Replaces the hand-written switch + map in MjSensor.cpp with codegen +# output driven by: +# - codegen_rules.json[categories.sensor.subtypes] for XML key + enum +# value + (optional) case_body_override +# - sensor_per_type (from build_mjcf_schema_snapshot.py's Sensor() +# scrape) for mj_type + static objtype/reftype literals +# +# Variable-objtype/reftype branches (frame*, geomdist, contact, plugin, +# user) stay hand-written in the post-switch block — that block reads +# UE-side ObjType / RefType properties and applies them after the +# codegen case fires. + +def _emit_sensor_switch_block(cat_rules: Dict[str, Any], + sensor_per_type: Dict[str, Any]) -> str: + """One ``case EMjSensorType::X: ...`` per subtype + the default fallback. + Lives between ``CODEGEN_SENSOR_TYPE_SWITCH_*`` markers in MjSensor.cpp. + """ + lines: List[str] = [] + type_enum = cat_rules.get("type_enum_name", "EMjSensorType") + for subtype in cat_rules.get("subtypes", []): + key = subtype["key"] + enum_value = subtype["enum_value"] + override = subtype.get("case_body_override") + if override: + lines.append(f" case {type_enum}::{enum_value}:") + lines.append(f" {override} break;") + continue + per = sensor_per_type.get(key, {}) + mj_type = per.get("mj_type") + if not mj_type: + # The sensor switch will fall through to ``default:`` for this + # subtype at runtime — i.e. all framejerk/whatever sensors get + # the default mjSENS_ACCELEROMETER + mjOBJ_SITE substitution. + # Loud diagnostic so a regression in build_mjcf_schema_snapshot's + # _extract_sensor_per_type regex doesn't silently miscompile. + _diag_add( + f"[diagnostic] sensor subtype '{key}' has no entry in " + f"sensor_per_type snapshot — runtime will fall through to " + f"the default mjSENS_ACCELEROMETER + mjOBJ_SITE branch. " + f"Check the _extract_sensor_per_type regex against " + f"mujoco/src/user/user_objects.cc.", + source="sensor_scrape_miss", ) + lines.append(f" // (skipped: no mj_type for '{key}' in sensor_per_type)") + continue + stmts = [f"Element->type = {mj_type};"] + # Only emit static objtype/reftype when sensor_per_type carries a + # literal mjOBJ_X. "from_xml" and "computed" entries are handled + # by the post-switch block reading UE-side ObjType/RefType. + objtype = per.get("objtype") + if isinstance(objtype, str) and objtype.startswith("mjOBJ_"): + stmts.append(f"Element->objtype = {objtype};") + reftype = per.get("reftype") + if isinstance(reftype, str) and reftype.startswith("mjOBJ_"): + stmts.append(f"Element->reftype = {reftype};") + lines.append(f" case {type_enum}::{enum_value}: " + f"{' '.join(stmts)} break;") + default_per = sensor_per_type.get("accelerometer", {}) + default_type = default_per.get("mj_type", "mjSENS_ACCELEROMETER") + default_objtype = default_per.get("objtype") or "mjOBJ_SITE" + if not (isinstance(default_objtype, str) and default_objtype.startswith("mjOBJ_")): + default_objtype = "mjOBJ_SITE" + lines.append(f" default: Element->type = {default_type}; " + f"Element->objtype = {default_objtype}; break;") + return "\n".join(lines) + "\n" - # 4) mjs_setTo* params with no UE-side mapping AND no explicit - # sentinel override. Params that have an entry in setto_param_defaults - # are intentionally non-schema-driven (the rule pins their value); - # skip them. - if mjspec and "setto_functions" in mjspec: - setto_defaults = rules.get("setto_param_defaults", {}) - for cat_name, cat_rules in categories.items(): - setto_block = cat_rules.get("subtype_setto") or {} - common_attrs = set(schema_attrs( - schema, cat_rules.get("schema_common_block", ""))) - for sub_key, setto_def in setto_block.items(): - if not isinstance(setto_def, dict): - continue - fn_name = setto_def.get("call") - if not fn_name or fn_name not in mjspec["setto_functions"]: - continue - sig = mjspec["setto_functions"][fn_name] - renames = setto_def.get("param_renames", {}) - fn_defaults = set(setto_defaults.get(fn_name, {}).keys()) - sub_attrs = set(schema_subtype_attrs(schema, cat_name, sub_key)) - schema_attr_set = common_attrs | sub_attrs - for p in sig.get("params", []): - pname = p["name"] - ue_prop = renames.get(pname, pname) - if ue_prop in schema_attr_set or pname in fn_defaults: - continue - msgs.append( - f"[diagnostic] {fn_name} param '{pname}' is not " - f"in the {cat_name}.{sub_key} schema attrs and " - f"has no param_renames or setto_param_defaults " - f"entry. Codegen passes the generic sentinel for " - f"it. If MuJoCo added this param, decide whether " - f"to expose it as a UE UPROPERTY (schema attr + " - f"type_mapping) or pin its sentinel." - ) - # 5) Attrs that fall back to default_type. Cosmetic — works but the - # UPROPERTY shape may be wrong (e.g. float for an int). - type_map = rules.get("type_mappings", {}) - default_type = rules.get("default_type", "float") - seen_untyped: set = set() - for cat_name, cat_rules in categories.items(): - block = cat_rules.get("schema_common_block", "") - for attr in schema_attrs(schema, block): - if attr in type_map or attr in seen_untyped: +def _emit_sensor_tag_to_type_block(cat_rules: Dict[str, Any]) -> str: + """One ``{TEXT(""), EMjSensorType::X}`` per subtype. Lives between + ``CODEGEN_SENSOR_TAG_TO_TYPE_*`` markers in MjSensor.cpp. + """ + lines: List[str] = [] + type_enum = cat_rules.get("type_enum_name", "EMjSensorType") + for subtype in cat_rules.get("subtypes", []): + # Some subtype XML keys collide with C++ enum members that diverge + # (e.g. `key=tendonactuatorfrc`, `enum_value=TendonActFrc`, + # mjSENS_TENDONACTFRC). The tag-to-type map uses the XML key + # verbatim so MJCF lookups match. + key = subtype["key"] + enum_value = subtype["enum_value"] + lines.append(f' {{TEXT("{key}"), {type_enum}::{enum_value}}},') + return "\n".join(lines) + "\n" + + +# --------------------------------------------------------------------------- +# Generated enum headers +# --------------------------------------------------------------------------- +# +# Some MuJoCo C enums (mjtIntegrator/mjtCone/mjtSolver/...) map to URLab +# UENUMs that are blueprint-exposed. Hand-written copies diverge from the +# C source over time, so this emitter generates them from the projected +# mjspec dict's ``enums`` table (sourced from the introspect snapshot). +# +# Rule shape (under top-level ``generated_enums`` in codegen_rules.json): +# "MjOptionEnums": { +# "public_header": "MuJoCo/Generated/MjOptionEnums.h", +# "enums": [ +# { +# "ue_name": "EMjIntegrator", +# "from_mj_enum": "mjtIntegrator", +# "underlying_type": "uint8", // optional, defaults uint8 +# "ue_member_from_mj": { +# "mjINT_EULER": "Euler", +# "mjINT_RK4": "RK4", +# ... +# }, +# // Optional: members from C enum to skip in UE (e.g. internal +# // sentinels that aren't blueprint-meaningful). +# "exclude_mj_members": [] +# } +# ] +# } + + +def _emit_generated_enum_file(cat_name: str, def_: Dict[str, Any], + mjspec: Optional[Dict[str, Any]], + public_root: str) -> List["FileWrite"]: + """Emit a single banner-mode .h carrying one or more UENUMs. + + Rule shape (per enum entry): + ``ue_name`` — UE enum class name (e.g. ``EMjGainType``) + ``from_mj_enum`` — MuJoCo source enum (e.g. ``mjtGain``) + ``ue_member_from_mj`` — opt-in mapping mj_const → UE member name + ``exclude_mj_members``— optional skip list within the source enum + ``extra_members`` — list of {"name": ...} URLab-extra + members appended AFTER the mj-derived + ones. Used by Camp B enums that carry + URLab-specific values without a mjt + counterpart (e.g. ``DcMotor`` for + ``EMjGainType``). + + Rule entries with ``"disabled": true`` are skipped entirely — used + while a hand-rolled enum is being staged for migration so the rule + can land in JSON without breaking the build. + """ + if def_.get("disabled"): + return [] + if not mjspec or "enums" not in mjspec: + _diag_add( + f"[diagnostic] generated_enums['{cat_name}'] needs an mjspec " + f"snapshot with an 'enums' key — run build_introspect_snapshot.py.", + source="generated_enums", + ) + return [] + enums = def_.get("enums", []) + if not enums: + return [] + + public_relpath = def_["public_header"] + header_basename = os.path.basename(public_relpath).replace(".h", "") + + enum_blocks: List[str] = [] + for entry in enums: + if entry.get("disabled"): + continue + ue_name = entry["ue_name"] + # ``from_mj_enum`` is optional when the URLab enum has no mjt + # counterpart at all (EMjFluidShape, EMjGeomInertia, etc) — the + # rule populates extra_members and skips the mjspec lookup. + mj_enum_name: Optional[str] = entry.get("from_mj_enum") + underlying = entry.get("underlying_type", "uint8") + ue_member_from_mj: Dict[str, str] = entry.get("ue_member_from_mj", {}) + exclude: set = set(entry.get("exclude_mj_members", [])) + extra_members: List[Dict[str, Any]] = entry.get("extra_members", []) + c_enum: Dict[str, int] = {} + if mj_enum_name: + c_enum = mjspec["enums"].get(mj_enum_name, {}) + if not c_enum: + _diag_add( + f"[diagnostic] generated_enums['{cat_name}']: C enum " + f"'{mj_enum_name}' missing from the introspect snapshot. " + f"Skipping '{ue_name}'.", + source="generated_enums", + ) continue - # Only warn for attrs likely meant to be array/int/bool — the - # heuristic: numeric-shaped names with a plural or ending in - # "count"/"range"/"limit" probably aren't a float scalar. - if any(s in attr for s in ("count", "range", "limit", "coef", - "data", "params", "vert", "elem", - "size", "list", "ids")): - msgs.append( - f"[diagnostic] attr '{attr}' (used by {cat_name}) " - f"falls back to default_type ('{default_type}') — " - f"add it to type_mappings if it should be TArray<...> " - f"or int32." + elif not extra_members: + _diag_add( + f"[diagnostic] generated_enums['{cat_name}']: '{ue_name}' " + f"has neither from_mj_enum nor extra_members; nothing to " + f"emit.", + source="generated_enums", + ) + continue + member_lines: List[str] = [] + used_values: set = set() + # Iterate by (value, mj_const) so the emitted UENUM order is stable + # across libclang scrapes — the snapshot's dict insertion order is + # whatever the AST walk produced, which can drift on header edits. + for mj_const, value in sorted(c_enum.items(), key=lambda kv: (kv[1], kv[0])): + if mj_const in exclude: + continue + ue_member = ue_member_from_mj.get(mj_const) + if not ue_member: + continue # silently skip; rule author opts in per-const + member_lines.append(f" {ue_member} = {value},") + used_values.add(value) + # URLab-extra members run AFTER the mj-derived block. Values + # auto-increment past the highest used mj value so the resulting + # uint8 sequence stays contiguous + reproducible. + next_value = (max(used_values) + 1) if used_values else 0 + for extra in extra_members: + name = extra.get("name") + if not name: + _diag_add( + f"[diagnostic] generated_enums['{cat_name}'] '{ue_name}'" + f" extra_members entry {extra!r} missing 'name'.", + source="generated_enums", ) - seen_untyped.add(attr) + continue + value = extra.get("value", next_value) + member_lines.append(f" {name} = {value},") + next_value = value + 1 + if not member_lines: + continue + # Strip the trailing comma on the last member for cleaner C++. + member_lines[-1] = member_lines[-1].rstrip(",") + # Doc line: only mention the mj source when the rule pinned + # one. Pure-extras enums (no mjt counterpart) get a one-liner + # naming them as URLab-side. + doc = ( + f"/** {ue_name} — mirror of MuJoCo's {mj_enum_name}. */\n" + if mj_enum_name + else f"/** {ue_name} — URLab editorial enum (no mjt counterpart). */\n" + ) + enum_blocks.append( + doc + + f"UENUM(BlueprintType)\n" + f"enum class {ue_name} : {underlying}\n" + f"{{\n" + + "\n".join(member_lines) + "\n" + f"}};\n" + ) - if msgs: - print(f"\n--- codegen diagnostics ({len(msgs)}) ---", file=sys.stderr) - for m in msgs: - print(m, file=sys.stderr) - print( - "(diagnostics are non-fatal; the codegen has emitted what it " - "can — fix the rules to silence them.)", - file=sys.stderr, + if not enum_blocks: + return [] + + content = ( + f"{COPYRIGHT_BLOCK}\n" + f"#pragma once\n\n" + f"#include \"CoreMinimal.h\"\n" + f"#include \"{header_basename}.generated.h\"\n\n" + + "\n".join(enum_blocks) + ) + public_path = os.path.join(public_root, public_relpath.replace("/", os.sep)) + return [FileWrite(path=public_path, content=content)] + + +def _phase_generated_enums(ctx: PhaseContext) -> None: + gen = ctx.rules.get("generated_enums", {}) + for cat_name, def_ in gen.items(): + # _note_* sibling keys document the surrounding entries; they + # appear as strings, not dicts, and must skip the emit path. + if cat_name.startswith("_") or not isinstance(def_, dict): + continue + ctx.writes.extend(_emit_generated_enum_file( + cat_name, def_, ctx.mjspec, ctx.public_root, + )) + + +# --------------------------------------------------------------------------- +# Articulation category registry +# --------------------------------------------------------------------------- +# +# Emits a header with a compile-time table of every URLab-managed MuJoCo +# category, listing the schema element name, UE base class, mjs struct, +# and the layout shape. Consumers (diagnostic dumps, BP iteration, +# test-time category enumeration) can iterate constexpr instead of +# duplicating the category list in C++ source. + +# --------------------------------------------------------------------------- +# Editor option helpers +# --------------------------------------------------------------------------- +# +# Codegens the trivial ``TArray UMjX::GetYOptions() const`` editor +# helpers that just forward to ``UMjComponent::GetSiblingComponentOptions``. +# Wrappers with real per-class logic (UMjActuator::GetTargetNameOptions, +# UMjSensor::Get(Target|Reference)NameOptions, UMjEquality::GetObjOptions) +# stay hand-written in their owning .cpp files. +# +# Emission shape: each host .cpp file has a CODEGEN_EDITOR_OPTIONS_START/END +# marker pair inside its ``#if WITH_EDITOR`` block. The phase injects the +# class's wrappers between those markers — output stays INSIDE the host +# .cpp, not a separate file. (Avoids the ``.gen.cpp`` UHT-collision name.) +# +# Rule shape (top-level ``editor_option_helpers.wrappers``): +# [ +# { +# "class": "UMjActuator", +# "host_cpp": "MuJoCo/Components/Actuators/MjActuator.cpp", +# "method": "GetSliderSiteOptions", +# "filter_class": "UMjSite", +# "include_defaults": false +# }, +# ... +# ] + +def _phase_editor_option_helpers(ctx: PhaseContext) -> None: + def_ = ctx.rules.get("editor_option_helpers") + if not def_: + return + wrappers = def_.get("wrappers", []) + if not wrappers: + return + # Group by host_cpp. + by_host: Dict[str, List[Dict[str, Any]]] = {} + for w in wrappers: + host = w.get("host_cpp") + if not host: + _diag_add( + f"[diagnostic] editor_option_helpers: missing host_cpp on " + f"wrapper {w!r}. Skipping.", + source="editor_option_helpers", + ) + continue + by_host.setdefault(host, []).append(w) + # Inject per-file. + for host_relpath, group in by_host.items(): + host_path = os.path.join(ctx.private_root, host_relpath.replace("/", os.sep)) + if not os.path.exists(host_path): + _diag_add( + f"[diagnostic] editor_option_helpers: host_cpp '{host_relpath}' " + f"not found on disk. Skipping injection.", + source="editor_option_helpers", + ) + continue + with open(host_path, "r", encoding="utf-8") as f: + text = f.read() + lines: List[str] = [] + for w in group: + cls = w["class"] + method = w["method"] + filt = w["filter_class"] + inc_def = bool(w.get("include_defaults", False)) + defaults_arg = ", true" if inc_def else "" + lines.append( + f"TArray {cls}::{method}() const {{ return " + f"UMjComponent::GetSiblingComponentOptions(this, " + f"{filt}::StaticClass(){defaults_arg}); }}" + ) + body = "\n".join(lines) + "\n" + new_text, ok = inject_between_tags(text, "EDITOR_OPTIONS", body) + if not ok: + _diag_add( + f"[diagnostic] editor_option_helpers: host_cpp '{host_relpath}' " + f"missing the CODEGEN_EDITOR_OPTIONS_START/END marker pair. " + f"Add the markers inside the host's #if WITH_EDITOR block " + f"or remove the wrapper entries.", + source="editor_option_helpers", + ) + continue + if new_text != text: + ctx.writes.append(FileWrite(path=host_path, content=new_text)) + + +def _phase_articulation_registry(ctx: PhaseContext) -> None: + cats = ctx.rules.get("categories", {}) + if not cats: + return + out_relpath = "MuJoCo/Generated/MjArticulationRegistry.h" + entries: List[str] = [] + for name in sorted(cats): + cat = cats[name] + base = cat.get("base_class_name", "") + mjs = cat.get("mjs_struct", "") + layout = cat.get("layout", "no_subclasses") + n_subtypes = len(cat.get("subtypes", [])) + entries.append( + f' {{ TEXT("{name}"), TEXT("{base}"), TEXT("{mjs}"), ' + f'TEXT("{layout}"), {n_subtypes} }},' + ) + content = ( + f"{COPYRIGHT_BLOCK}\n" + f"#pragma once\n\n" + f"#include \"CoreMinimal.h\"\n\n" + f"// Compile-time registry of every URLab-managed MuJoCo category.\n" + f"// Codegen-owned — driven by codegen_rules.json[categories].\n" + f"namespace MjArticulationRegistry\n" + f"{{\n" + f" struct CategoryEntry\n" + f" {{\n" + f" const TCHAR* Name; // schema element name, e.g. \"body\"\n" + f" const TCHAR* BaseClassName; // UE base UClass, e.g. \"UMjBody\"\n" + f" const TCHAR* MjsStruct; // MuJoCo spec struct, e.g. \"mjsBody\"\n" + f" const TCHAR* Layout; // \"single_uclass_per_file\" / \"multi_uclass\" / \"no_subclasses\"\n" + f" int NumSubtypes;\n" + f" }};\n\n" + f" inline constexpr CategoryEntry kCategories[] = {{\n" + + "\n".join(entries) + "\n" + f" }};\n" + f" inline constexpr int kNumCategories = sizeof(kCategories) / sizeof(kCategories[0]);\n" + f"}}\n" + ) + out_path = os.path.join(ctx.public_root, out_relpath.replace("/", os.sep)) + ctx.writes.append(FileWrite(path=out_path, content=content)) + + +def _emit_objtype_dispatch_block(cat_rules: Dict[str, Any]) -> Optional[str]: + """Emit a switch on ``cat_rules['objtype_dispatch']`` that assigns + each case's ``expr`` to ``target``. Used by categories where mjs's + objtype field varies by enum value (today: MjEquality).""" + dispatch = cat_rules.get("objtype_dispatch") + if not dispatch: + return None + enum_name = cat_rules.get("type_enum_name") + if not enum_name: + _diag_add( + "[diagnostic] objtype_dispatch on category missing " + "'type_enum_name'; cannot emit case labels.", + source="objtype_dispatch", + ) + return None + discriminator = dispatch["discriminator"] + target = dispatch["target"] + default_expr = dispatch.get("default", "mjOBJ_UNKNOWN") + cases = dispatch.get("cases", []) + if not cases: + _diag_add( + f"[diagnostic] objtype_dispatch '{discriminator}' has no cases; " + f"only the default branch would emit.", + source="objtype_dispatch", + ) + return None + + switch_cases: List[Tuple[Any, str]] = [] + for i, case in enumerate(cases): + keys = case.get("keys", []) + if not keys: + _diag_add( + f"[diagnostic] objtype_dispatch case #{i} has empty " + f"'keys' list; would emit a body with no case label.", + source="objtype_dispatch", + ) + return None + if "expr" not in case: + _diag_add( + f"[diagnostic] objtype_dispatch case #{i} (keys={keys}) " + f"missing 'expr'.", + source="objtype_dispatch", + ) + return None + switch_cases.append((list(keys), f"{target} = {case['expr']}")) + return emit_enum_switch( + discriminator, enum_name, switch_cases, + indent=" ", + default_body=f"{target} = {default_expr}", + ) + + +def _inject_into_category_cpp( + rules: Dict[str, Any], + private_root: str, + writes: List["FileWrite"], + tag: str, + emit_fn, + *, + diag_source: str, +) -> None: + """Shared scaffolding: walk every category, call ``emit_fn(cat_rules)``, + inject the result between ``CODEGEN__START/END`` markers in the + category's base-class .cpp. ``emit_fn`` returns ``None`` to skip + (already diagnosed inside the emit_fn). Missing-file / missing-marker + diagnostics + the brace-balance check come from + ``_inject_tags_into_cpp`` so every injection path shares the same + safety net.""" + for cat_name, cat_rules in rules.get("categories", {}).items(): + body = emit_fn(cat_rules) + if body is None: + continue + base_header = cat_rules.get("base_class_header") + if not base_header: + _diag_add( + f"[diagnostic] category '{cat_name}' has codegen rule for " + f"{diag_source} but no 'base_class_header'; block not emitted.", + source=diag_source, + ) + continue + cpp_path = os.path.join( + private_root, base_header.replace(".h", ".cpp"), + ) + _inject_tags_into_cpp( + cpp_path, [(tag, body)], writes, diag_source=diag_source, + ) + + +def _phase_objtype_dispatch(ctx: PhaseContext) -> None: + """Inject objtype dispatch block; host .cpp must carry + ``CODEGEN_OBJTYPE_DISPATCH_START/END`` markers.""" + _inject_into_category_cpp( + ctx.rules, ctx.private_root, ctx.writes, + tag="OBJTYPE_DISPATCH", + emit_fn=_emit_objtype_dispatch_block, + diag_source="objtype_dispatch", + ) + + +def _emit_geom_final_type_block(cat_rules: Dict[str, Any], + element_rules: Dict[str, Any], + mjspec: Optional[Dict[str, Any]] = None) -> Optional[str]: + """Emit MjGeom's FinalType resolution + mesh-name export. Specific + to geom because the mesh-name write depends on the COMPILE-TIME geom + type (UPROPERTY Type if overridden, else Default's type). + + The value_map is pulled from ``element_rules[xml_enum_ref]`` via + ``_resolve_value_map``. Returns None (with a diagnostic) when the + xml_enum_ref entry is missing — silent failure here would drop the + block from MjGeom.cpp and only surface as a runtime mesh-bind error. + """ + final = cat_rules.get("geom_final_type") + if not final: + return None + xml_enum_attrs = element_rules.get("xml_enum_attrs", {}) + attr_key = final["xml_enum_ref"] + enum_def = xml_enum_attrs.get(attr_key) + if not enum_def: + _diag_add( + f"[diagnostic] geom_final_type references xml_enum '{attr_key}' " + f"that doesn't exist in element_rules; FinalType block will be " + f"empty and mesh-name export will not fire.", + source="geom_final_type", + ) + return None + value_map = _resolve_value_map(attr_key, enum_def) + if not value_map: + _diag_add( + f"[diagnostic] geom_final_type xml_enum '{attr_key}' resolved " + f"to an empty value_map; FinalType switch would have no cases.", + source="geom_final_type", + ) + return None + ue_prop = enum_def["ue_property"] + ue_enum = enum_def["ue_enum_type"] + + override = final["override_field"] + default_lookup = final["default_lookup"] + fallback = final["default_fallback"] + name_field = final["name_field"] + name_for = final["name_export_for"] + name_target = final["name_target"] + name_setter = final["name_setter"] + + # Placeholder for the FinalType init when override=true: any mj_const + # works because the switch below remaps. Pick the value_map's first + # entry for stability. + first_mj = next(iter(value_map.values()))[1] + + switch_cases: List[Tuple[Any, str]] = [ + (mapping[0], f"FinalType = {mapping[1]}") + for mapping in value_map.values() + ] + switch_body = emit_enum_switch( + ue_prop, ue_enum, switch_cases, indent=" ", + ).rstrip("\n") + lines: List[str] = [] + lines.append(f" int FinalType = {override}") + lines.append(f" ? {first_mj} /* placeholder; remapped below */") + lines.append(f" : (Default ? {default_lookup} : {fallback});") + lines.append(f" if ({override})") + lines.append(" {") + lines.append(switch_body) + lines.append(" }") + lines.append(f" if (FinalType == {name_for} && !{name_field}.IsEmpty())") + lines.append(" {") + lines.append(f" {name_setter}({name_target}, {name_field});") + lines.append(" }") + return "\n".join(lines) + "\n" + + +def _phase_geom_final_type(ctx: PhaseContext) -> None: + """Inject geom_final_type block into MjGeom.cpp between the + CODEGEN_GEOM_FINAL_TYPE markers.""" + element_rules_all = ctx.rules.get("element_rules", {}) + + def emit_fn(cat_rules): + # Look up element_rules entry via the category key already used by + # rules.categories. The shared helper passes cat_rules through; + # we recover the category name from the dict identity. + cat_name = next( + (k for k, v in ctx.rules.get("categories", {}).items() + if v is cat_rules), + None, + ) + if cat_name is None: + return None + return _emit_geom_final_type_block( + cat_rules, element_rules_all.get(cat_name, {}), ctx.mjspec, + ) + + _inject_into_category_cpp( + ctx.rules, ctx.private_root, ctx.writes, + tag="GEOM_FINAL_TYPE", + emit_fn=emit_fn, + diag_source="geom_final_type", + ) + + +def _phase_sensor_codegen(ctx: PhaseContext) -> None: + """Inject codegen-emitted sensor switch + TagToType into MjSensor.cpp.""" + sensor_rules = ctx.rules.get("categories", {}).get("sensor") + if not sensor_rules: + return + sensor_per_type = ctx.schema.get("sensor_per_type", {}) + if not sensor_per_type: + _diag_add( + "[diagnostic] sensor_per_type missing from schema snapshot; " + "skipping sensor switch codegen (run " + "build_mjcf_schema_snapshot.py).", + source="sensor_codegen", ) + return + cpp_path = os.path.join( + ctx.private_root, "MuJoCo", "Components", "Sensors", "MjSensor.cpp", + ) + _inject_tags_into_cpp( + cpp_path, + [ + ("SENSOR_TYPE_SWITCH", _emit_sensor_switch_block(sensor_rules, sensor_per_type)), + ("SENSOR_TAG_TO_TYPE", _emit_sensor_tag_to_type_block(sensor_rules)), + ], + ctx.writes, + diag_source="sensor_codegen", + ) + + +_KNOWN_LAYOUTS = {"single_uclass_per_file", "multi_uclass", "no_subclasses"} + + +def _phase_categories(ctx: PhaseContext) -> None: + rules, schema = ctx.rules, ctx.schema + public_root, private_root = ctx.public_root, ctx.private_root + mjspec = ctx.mjspec + categories: Dict[str, Any] = rules.get("categories", {}) + for cat, cat_rules in categories.items(): + layout = cat_rules.get("layout", "no_subclasses") + if layout == "single_uclass_per_file": + ctx.writes.extend(emit_base_class_injection(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) + ctx.writes.extend(emit_subclass_files(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) + elif layout == "multi_uclass": + ctx.writes.extend(emit_multi_uclass(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) + elif layout == "no_subclasses": + ctx.writes.extend(emit_base_class_injection(cat, cat_rules, schema, rules, public_root, private_root, mjspec=mjspec)) + else: + _diag_add( + f"[diagnostic] category '{cat}' has unknown layout " + f"'{layout}'; expected one of {sorted(_KNOWN_LAYOUTS)}. " + f"Category emitted no writes.", + source="category_layout", + ) + + +def _phase_bind_h(ctx: PhaseContext) -> None: + bind_write = emit_bind_h_injection(ctx.rules, ctx.mjxmacro, ctx.bind_h_path) + if bind_write: + ctx.writes.append(bind_write) + + +def _phase_schema_tests(ctx: PhaseContext) -> None: + ctx.writes.append(emit_schema_for_tests(ctx.schema, ctx.rules)) + + +# The 17 drift checks, _emit_drift_diagnostics, the hand-enum regexes, +# _scan_hand_enums, _hand_enums_from_snapshot, _all_schema_attrs, +# _collect_every_schema_attr, and _VALID_APPLY_MODES live in +# _codegen_checks. The orchestrator re-exports them through the import +# block at the top of this file. + + +def _phase_diagnostics(ctx: PhaseContext) -> None: + rules, schema, mjspec, mjxmacro = ctx.rules, ctx.schema, ctx.mjspec, ctx.mjxmacro + _emit_drift_diagnostics(schema, rules, mjspec) + _check_hand_enum_drift(schema, rules, mjspec, ctx.public_root) + _check_type_shape_drift(schema, rules, mjspec) + _check_new_attr_typing(schema, rules) + _check_value_map_stale_mj_consts(rules, mjspec) + _check_orphan_rule_entries(schema, rules) + _check_compiler_attrs_coverage(schema, rules) + _check_mjxmacro_block_coverage(rules, mjxmacro) + _check_property_units_validity(rules) + _check_apply_mode_validity(rules) + _check_embedded_cpp_references(rules, mjspec) + _check_allowlist_staleness(schema, rules, mjspec) + + +# Order matters: emit phases collect writes; diagnostics runs last and +# scans the final rule set. +EMISSION_PHASES: List[EmissionPhase] = [ + EmissionPhase(name="categories", fn=_phase_categories), + EmissionPhase(name="synthetic_categories", fn=_phase_synthetic_categories), + EmissionPhase(name="generated_enums", fn=_phase_generated_enums), + EmissionPhase(name="editor_option_helpers", fn=_phase_editor_option_helpers), + EmissionPhase(name="articulation_registry", fn=_phase_articulation_registry), + EmissionPhase(name="sensor_codegen", fn=_phase_sensor_codegen), + EmissionPhase(name="objtype_dispatch", fn=_phase_objtype_dispatch), + EmissionPhase(name="geom_final_type", fn=_phase_geom_final_type), + EmissionPhase(name="bind_h", fn=_phase_bind_h), + EmissionPhase(name="schema_tests", fn=_phase_schema_tests), + EmissionPhase(name="diagnostics", fn=_phase_diagnostics), +] + + +def collect_all_writes( + schema: Dict[str, Any], + rules: Dict[str, Any], + mjxmacro: Dict[str, Any], + public_root: str, + private_root: str, + bind_h_path: str, + mjspec: Dict[str, Any] | None = None, +) -> List[FileWrite]: + """Drive every phase in ``EMISSION_PHASES`` and return the full set + of file writes the codegen would perform. No I/O side effects on + disk — diagnostics print to stderr at the end.""" + _reset_diags() + writes: List[FileWrite] = [] + ctx = PhaseContext( + schema=schema, rules=rules, mjxmacro=mjxmacro, mjspec=mjspec, + public_root=public_root, private_root=private_root, + bind_h_path=bind_h_path, writes=writes, + ) + for phase in EMISSION_PHASES: + phase.fn(ctx) + _diag_flush() + return writes + + +def _mjspec_from_introspect( + introspect: Dict[str, Any], +) -> Dict[str, Any]: + """Project the libclang-scraped introspect snapshot into the + shape downstream code expects: + + ``structs``: ``{struct_name: [field_name, ...]}`` + ``enums``: ``{enum_name: {member_name: int_value}}`` + ``setto_functions``: ``{fn_name: {"params": [...], "return_type": ...}}`` + ``introspect``: passthrough of the richer per-field tables for + the drift checks that need them. + + Every ``mjs_setTo*`` C signature takes the spec element as its + first arg; the codegen emit path always passes ``Element`` there, + so the projection drops that arg from the param list and the + downstream emitter enumerates only the schema-attr-bound trailing + args.""" + structs_in = introspect.get("structs", {}) or {} + structs_out: Dict[str, List[str]] = {} + for name, entry in structs_in.items(): + if isinstance(entry, dict): + fields = entry.get("fields", []) + structs_out[name] = [ + f["name"] for f in fields + if isinstance(f, dict) and isinstance(f.get("name"), str) + ] + + enums_in = introspect.get("enums", {}) or {} + enums_out: Dict[str, Dict[str, int]] = {} + for name, entry in enums_in.items(): + if isinstance(entry, dict): + members = entry.get("members", {}) + if isinstance(members, dict): + enums_out[name] = dict(members) + + fns_in = introspect.get("functions", {}) or {} + setto_out: Dict[str, Dict[str, Any]] = {} + for name, sig in fns_in.items(): + if not name.startswith("mjs_setTo"): + continue + if isinstance(sig, dict): + params = sig.get("params", []) + setto_out[name] = { + "params": params[1:] if params else [], + "return_type": sig.get("return_type", ""), + } + + return { + "structs": structs_out, + "enums": enums_out, + "setto_functions": setto_out, + "introspect": { + "functions": fns_in, + "structs": structs_in, + "defines": introspect.get("defines", {}), + "hand_enums": introspect.get("hand_enums", {}), + }, + } def apply_writes(writes: List[FileWrite], dry_run: bool, check_only: bool) -> int: - """Either apply, print diff, or check. Returns process exit code.""" + """Either apply, print diff, or check. Returns process exit code. + + Writes use ``newline="\\n"`` and a binary compare so a codegen run on + Windows produces the same bytes as one on Linux — otherwise Python's + default newline translation would silently bake ``\\r\\n`` into the + on-disk artifacts and ``--check`` would still pass because the + matching read would normalize it back.""" changed = 0 for w in writes: - new = w.content - old = None + new_bytes = w.content.encode("utf-8") + old_bytes: Optional[bytes] = None if os.path.exists(w.path): - with open(w.path, "r", encoding="utf-8") as f: - old = f.read() - if old == new: + with open(w.path, "rb") as f: + old_bytes = f.read() + if old_bytes == new_bytes: continue changed += 1 rel = os.path.relpath(w.path, PLUGIN_ROOT) if dry_run or check_only: - print(f"==> WOULD WRITE: {rel} ({len(new)} bytes)") - if old is not None and dry_run: + print(f"==> WOULD WRITE: {rel} ({len(new_bytes)} bytes)") + if old_bytes is not None and dry_run: + old_text = old_bytes.decode("utf-8", errors="replace") diff = difflib.unified_diff( - old.splitlines(keepends=True), - new.splitlines(keepends=True), + old_text.splitlines(keepends=True), + w.content.splitlines(keepends=True), fromfile=rel + " (current)", tofile=rel + " (codegen)", n=2, ) sys.stdout.writelines(diff) else: + # Atomic write: stage to a sibling tmp file, then os.replace. + # Without this, a Ctrl-C between truncate and write leaves a + # zero-/partial-byte file that UBT picks up, producing a UHT + # error far from "I interrupted codegen". os.makedirs(os.path.dirname(w.path), exist_ok=True) - with open(w.path, "w", encoding="utf-8") as f: - f.write(new) + tmp_path = w.path + ".codegen.tmp" + try: + with open(tmp_path, "wb") as f: + f.write(new_bytes) + os.replace(tmp_path, w.path) + except BaseException: + if os.path.exists(tmp_path): + try: + os.remove(tmp_path) + except OSError: + pass + raise print(f"WROTE {rel}") if check_only and changed: return 1 @@ -2368,17 +4033,68 @@ def apply_writes(writes: List[FileWrite], dry_run: bool, check_only: bool) -> in return 0 +# Hand-written companion files that legitimately live in MuJoCo/Generated/ +# (their banner explicitly says "NOT codegen-managed"). Listed here so the +# orphan walk doesn't flag them — anything else in Generated/ that the +# codegen doesn't plan to write IS a real orphan. +_HAND_WRITTEN_IN_GENERATED = { + "MjOptionGeneratedExtras.cpp", +} + + +def find_orphan_generated_files( + writes: List[FileWrite], public_root: str, private_root: str, +) -> List[str]: + """Walk ``MuJoCo/Generated/`` under public + private roots and return + any file the codegen no longer plans to emit. A category removed from + rules leaves a stale ``Generated/MjFoo.h`` that UBT will pick up — the + user sees a confusing UHT error far from the JSON edit.""" + expected = {os.path.normcase(os.path.abspath(w.path)) for w in writes} + orphans: List[str] = [] + for root in (public_root, private_root): + gen_dir = os.path.join(root, "MuJoCo", "Generated") + if not os.path.isdir(gen_dir): + continue + for dirpath, _dirs, files in os.walk(gen_dir): + for fname in files: + if not (fname.endswith(".h") or fname.endswith(".cpp")): + continue + if fname in _HAND_WRITTEN_IN_GENERATED: + continue + p = os.path.normcase(os.path.abspath(os.path.join(dirpath, fname))) + if p not in expected: + orphans.append(os.path.join(dirpath, fname)) + return sorted(orphans) + + def main() -> int: parser = argparse.ArgumentParser(description="URLab UE component codegen.") parser.add_argument("--schema", default=DEFAULT_SCHEMA) parser.add_argument("--mjxmacro", default=DEFAULT_MJXMACRO) - parser.add_argument("--mjspec", default=DEFAULT_MJSPEC) + parser.add_argument("--introspect", default=DEFAULT_INTROSPECT, + help="Clang-AST scrape carrying mjsX struct fields, " + "mjt* enums, mjs_setTo* signatures, and EMj* " + "hand-enum members. Built by " + "build_introspect_snapshot.py (requires libclang).") parser.add_argument("--rules", default=DEFAULT_RULES) parser.add_argument("--public-root", default=DEFAULT_PUBLIC_ROOT) parser.add_argument("--private-root", default=DEFAULT_PRIVATE_ROOT) parser.add_argument("--bind-h", default=DEFAULT_BIND_H) - parser.add_argument("--dry-run", action="store_true", help="print diffs, write nothing") - parser.add_argument("--check", action="store_true", help="non-zero exit if writes would change anything") + parser.add_argument("--dry-run", action="store_true", + help="print diffs, write nothing") + parser.add_argument("--check", action="store_true", + help="non-zero exit if writes would change anything") + parser.add_argument("--strict", dest="strict", + action=argparse.BooleanOptionalAction, default=True, + help="treat drift diagnostics as fatal (exit 2). " + "Default on; --no-strict makes diagnostics " + "print but not fail the run.") + parser.add_argument("--require-introspect", dest="require_introspect", + action=argparse.BooleanOptionalAction, default=True, + help="hard-fail when the clang-AST introspect " + "snapshot is missing. Default on; " + "--no-require-introspect lets the codegen run " + "against an existing (possibly stale) snapshot.") args = parser.parse_args() with open(args.schema, "r", encoding="utf-8") as f: @@ -2387,13 +4103,90 @@ def main() -> int: mjxmacro = json.load(f) with open(args.rules, "r", encoding="utf-8") as f: rules = json.load(f) + mjspec: Dict[str, Any] | None = None - if os.path.exists(args.mjspec): - with open(args.mjspec, "r", encoding="utf-8") as f: - mjspec = json.load(f) + if not os.path.exists(args.introspect): + msg = ( + f"[codegen] introspect snapshot missing at {args.introspect}. " + f"Run `python Scripts/codegen/build_introspect_snapshot.py` " + f"(requires libclang). Pass --no-require-introspect to bypass." + ) + if args.require_introspect: + print(msg, file=sys.stderr) + return 3 + print(f"[codegen] warning: {msg}", file=sys.stderr) + else: + with open(args.introspect, "r", encoding="utf-8") as f: + introspect = json.load(f) + mjspec = _mjspec_from_introspect(introspect) + # Post-projection invariants: a libclang scrape shape change can + # silently empty the projection, which would neuter the type-shape + # drift check and drop TArray array-cap clamps from emitted code. + # Fail loud rather than ship a degraded but green-on---check run. + if args.require_introspect: + for key in ("enums", "structs", "setto_functions"): + if not mjspec.get(key): + print( + f"[codegen] introspect projection produced empty " + f"'{key}'. The libclang scrape shape may have " + f"drifted — rebuild the snapshot or fix " + f"_mjspec_from_introspect.", + file=sys.stderr, + ) + return 3 - writes = collect_all_writes(schema, rules, mjxmacro, args.public_root, args.private_root, args.bind_h, mjspec=mjspec) - return apply_writes(writes, args.dry_run, args.check) + writes = collect_all_writes( + schema, rules, mjxmacro, + args.public_root, args.private_root, args.bind_h, mjspec=mjspec, + ) + + orphans = find_orphan_generated_files( + writes, args.public_root, args.private_root, + ) + for orphan in orphans: + rel = os.path.relpath(orphan, PLUGIN_ROOT) + _diag_add( + f"[diagnostic] orphan generated file: {rel}. The codegen no " + f"longer plans to emit this path — a category or subtype was " + f"likely removed from codegen_rules.json. Delete the file " + f"(UBT will otherwise pick it up).", + source="orphan_generated_file", + ) + # Snapshot the diag SOURCE tags before flushing, so we can detect + # destructive-overwrite warnings (banner_overwrite) and refuse to + # write under --strict — otherwise apply_writes would destroy the + # hand edits before the strict check fires. + banner_overwrite_pending = any( + d.source == "banner_overwrite" for d in _DIAGS_BUFFER.pending + ) + _diag_flush() + + fired = _DIAGS_BUFFER.fired_count + is_destructive_run = not args.dry_run and not args.check + if is_destructive_run and args.strict and banner_overwrite_pending: + print( + f"[codegen] --strict: banner_overwrite diagnostic fired — " + f"refusing to write (would destroy hand-edited content). " + f"Re-run with --no-strict to proceed, or run the audit " + f"helper at Scripts/codegen/_audit_banner_candidates.py.", + file=sys.stderr, + ) + return 2 + + rc = apply_writes(writes, args.dry_run, args.check) + if args.check and orphans: + print( + f"[codegen] --check: {len(orphans)} orphan generated file(s); " + f"exiting non-zero.", file=sys.stderr, + ) + return 1 + if args.strict and fired: + print( + f"[codegen] --strict: {fired} diagnostic(s) flushed; " + f"exiting non-zero.", file=sys.stderr, + ) + return 2 + return rc if __name__ == "__main__": diff --git a/Scripts/codegen/regen_all.py b/Scripts/codegen/regen_all.py index 2d5c9e9..ab3c622 100644 --- a/Scripts/codegen/regen_all.py +++ b/Scripts/codegen/regen_all.py @@ -4,12 +4,16 @@ Runs every codegen step in order: 1. Rebuild snapshots from the installed MuJoCo headers + submodule source: - - Scripts/mjspec_snapshot.json (mjsX struct fields + mjs_setTo* sigs) - - Scripts/mjxmacro_snapshot.json (model/data array layouts) - - Scripts/mjcf_schema_snapshot.json (MJCF schema, per element) + - Scripts/codegen/snapshots/mjxmacro_snapshot.json (model/data array layouts) + - Scripts/codegen/snapshots/mjcf_schema_snapshot.json (MJCF schema + per-sensor objtype scrape) + - Scripts/codegen/snapshots/introspect_snapshot.json (clang-AST scrape — mjsX struct fields, mjt* enums, mjs_setTo* sigs, EMj* hand enums) 2. Run the C++ generator (generate_ue_components.py) against the fresh snapshots. Emits / updates the per-component .h/.cpp files in Source/. +The clang-AST introspect snapshot now supersedes the old +``mjspec_snapshot.json`` — the runtime projects introspect into the +legacy mjspec shape, so build_mjspec_snapshot.py is retired. + Day-to-day this is the script developers run after either: - bumping the third_party/MuJoCo submodule pointer + rebuilding the install (build_all.ps1 / build_all.sh), OR @@ -58,13 +62,22 @@ def main(argv: list[str] | None = None) -> int: py = sys.executable steps: list[tuple[str, list[str]]] = [ - ("mjspec snapshot", - [py, os.path.join(HERE, "build_mjspec_snapshot.py")]), ("mjxmacro snapshot", [py, os.path.join(HERE, "build_mjxmacro_snapshot.py")]), ("MJCF schema snapshot", [py, os.path.join(HERE, "build_mjcf_schema_snapshot.py")]), ] + # Introspect snapshot needs libclang and now also supplies the data + # build_mjspec_snapshot.py used to scrape via regex (mjsX struct + # fields, mjt* enums, mjs_setTo* sigs). Optional only in the sense + # that a stale on-disk snapshot still drives the codegen — the + # --require-introspect default in generate_ue_components.py makes + # the gate fatal at next run if the snapshot really is missing. + introspect_step = ( + "introspect snapshot (clang AST — supersedes mjspec snapshot)", + [py, os.path.join(HERE, "build_introspect_snapshot.py")], + ) + steps.append(introspect_step) if not args.skip_codegen: steps.append(("UE component codegen", [py, os.path.join(HERE, "generate_ue_components.py")])) @@ -72,6 +85,16 @@ def main(argv: list[str] | None = None) -> int: for label, cmd in steps: rc = _run(label, cmd) if rc != 0: + # Introspect is optional — warn but continue when it's the + # one that failed (most commonly: libclang not on PATH). + if label.startswith("introspect snapshot"): + print( + " (introspect is optional; codegen will use the " + "existing snapshot — type-shape drift may be stale " + "until you install libclang.)", + flush=True, + ) + continue return rc print("\nAll regen steps completed.", flush=True) diff --git a/Scripts/codegen/snapshots/introspect_snapshot.json b/Scripts/codegen/snapshots/introspect_snapshot.json new file mode 100644 index 0000000..4ff937b --- /dev/null +++ b/Scripts/codegen/snapshots/introspect_snapshot.json @@ -0,0 +1,26735 @@ +{ + "_meta": { + "snapshot_version": 1, + "header_hash": "e4e41be1f2a1615ec30345189a81a6dc7c58c113a262d2478167f67a4d117311" + }, + "functions": { + "mj_defaultVFS": { + "name": "mj_defaultVFS", + "return_type": "void", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 79 + }, + "mj_mountVFS": { + "name": "mj_mountVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "filepath", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "provider", + "c_type": "const mjpResourceProvider *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 83 + }, + "mj_unmountVFS": { + "name": "mj_unmountVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 86 + }, + "mj_addFileVFS": { + "name": "mj_addFileVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "directory", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 89 + }, + "mj_addBufferVFS": { + "name": "mj_addBufferVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "buffer", + "c_type": "const void *", + "array_dim": null + }, + { + "name": "nbuffer", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 92 + }, + "mj_deleteFileVFS": { + "name": "mj_deleteFileVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 95 + }, + "mj_containsBufferVFS": { + "name": "mj_containsBufferVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 98 + }, + "mj_containsFileVFS": { + "name": "mj_containsFileVFS", + "return_type": "int", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + }, + { + "name": "directory", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 101 + }, + "mj_deleteVFS": { + "name": "mj_deleteVFS", + "return_type": "void", + "params": [ + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 104 + }, + "mj_getCacheSize": { + "name": "mj_getCacheSize", + "return_type": "size_t", + "params": [ + { + "name": "cache", + "c_type": "const mjCache *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 109 + }, + "mj_getCacheCapacity": { + "name": "mj_getCacheCapacity", + "return_type": "size_t", + "params": [ + { + "name": "cache", + "c_type": "const mjCache *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 112 + }, + "mj_setCacheCapacity": { + "name": "mj_setCacheCapacity", + "return_type": "size_t", + "params": [ + { + "name": "cache", + "c_type": "mjCache *", + "array_dim": null + }, + { + "name": "size", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 115 + }, + "mj_getCache": { + "name": "mj_getCache", + "return_type": "mjCache *", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 118 + }, + "mj_clearCache": { + "name": "mj_clearCache", + "return_type": "void", + "params": [ + { + "name": "cache", + "c_type": "mjCache *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 121 + }, + "mj_loadXML": { + "name": "mj_loadXML", + "return_type": "mjModel *", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 129 + }, + "mj_parseXML": { + "name": "mj_parseXML", + "return_type": "mjSpec *", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 133 + }, + "mj_parseXMLString": { + "name": "mj_parseXMLString", + "return_type": "mjSpec *", + "params": [ + { + "name": "xml", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 137 + }, + "mj_parse": { + "name": "mj_parse", + "return_type": "mjSpec *", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 141 + }, + "mj_encode": { + "name": "mj_encode", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 147 + }, + "mj_compile": { + "name": "mj_compile", + "return_type": "mjModel *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 153 + }, + "mj_copyBack": { + "name": "mj_copyBack", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 156 + }, + "mj_recompile": { + "name": "mj_recompile", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "m", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 160 + }, + "mj_saveLastXML": { + "name": "mj_saveLastXML", + "return_type": "int", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 165 + }, + "mj_freeLastXML": { + "name": "mj_freeLastXML", + "return_type": "void", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 168 + }, + "mj_saveXMLString": { + "name": "mj_saveXMLString", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "xml", + "c_type": "char *", + "array_dim": null + }, + { + "name": "xml_sz", + "c_type": "int", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 173 + }, + "mj_saveXML": { + "name": "mj_saveXML", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 177 + }, + "mju_getXMLDependencies": { + "name": "mju_getXMLDependencies", + "return_type": "void", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "dependencies", + "c_type": "mjStringVec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 181 + }, + "mj_step": { + "name": "mj_step", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 186 + }, + "mj_step1": { + "name": "mj_step1", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 189 + }, + "mj_step2": { + "name": "mj_step2", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 192 + }, + "mj_forward": { + "name": "mj_forward", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 195 + }, + "mj_inverse": { + "name": "mj_inverse", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 198 + }, + "mj_forwardSkip": { + "name": "mj_forwardSkip", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "skipstage", + "c_type": "int", + "array_dim": null + }, + { + "name": "skipsensor", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 201 + }, + "mj_inverseSkip": { + "name": "mj_inverseSkip", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "skipstage", + "c_type": "int", + "array_dim": null + }, + { + "name": "skipsensor", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 204 + }, + "mj_defaultLROpt": { + "name": "mj_defaultLROpt", + "return_type": "void", + "params": [ + { + "name": "opt", + "c_type": "mjLROpt *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 210 + }, + "mj_defaultSolRefImp": { + "name": "mj_defaultSolRefImp", + "return_type": "void", + "params": [ + { + "name": "solref", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "solimp", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 214 + }, + "mj_defaultOption": { + "name": "mj_defaultOption", + "return_type": "void", + "params": [ + { + "name": "opt", + "c_type": "mjOption *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 217 + }, + "mj_defaultVisual": { + "name": "mj_defaultVisual", + "return_type": "void", + "params": [ + { + "name": "vis", + "c_type": "mjVisual *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 220 + }, + "mj_copyModel": { + "name": "mj_copyModel", + "return_type": "mjModel *", + "params": [ + { + "name": "dest", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 224 + }, + "mj_saveModel": { + "name": "mj_saveModel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "buffer", + "c_type": "void *", + "array_dim": null + }, + { + "name": "buffer_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 228 + }, + "mj_loadModel": { + "name": "mj_loadModel", + "return_type": "mjModel *", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 233 + }, + "mj_loadModelBuffer": { + "name": "mj_loadModelBuffer", + "return_type": "mjModel *", + "params": [ + { + "name": "buffer", + "c_type": "const void *", + "array_dim": null + }, + { + "name": "buffer_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 236 + }, + "mj_deleteModel": { + "name": "mj_deleteModel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 239 + }, + "mj_sizeModel": { + "name": "mj_sizeModel", + "return_type": "mjtSize", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 242 + }, + "mj_makeData": { + "name": "mj_makeData", + "return_type": "mjData *", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 246 + }, + "mj_copyData": { + "name": "mj_copyData", + "return_type": "mjData *", + "params": [ + { + "name": "dest", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 250 + }, + "mjv_copyData": { + "name": "mjv_copyData", + "return_type": "mjData *", + "params": [ + { + "name": "dest", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 253 + }, + "mj_resetData": { + "name": "mj_resetData", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 256 + }, + "mj_resetDataDebug": { + "name": "mj_resetDataDebug", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "debug_value", + "c_type": "unsigned char", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 259 + }, + "mj_resetDataKeyframe": { + "name": "mj_resetDataKeyframe", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "key", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 262 + }, + "mj_markStack": { + "name": "mj_markStack", + "return_type": "void", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 267 + }, + "mj_freeStack": { + "name": "mj_freeStack", + "return_type": "void", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 271 + }, + "mj_stackAllocByte": { + "name": "mj_stackAllocByte", + "return_type": "void *", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "bytes", + "c_type": "size_t", + "array_dim": null + }, + { + "name": "alignment", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 277 + }, + "mj_stackAllocNum": { + "name": "mj_stackAllocNum", + "return_type": "mjtNum *", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "size", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 280 + }, + "mj_stackAllocInt": { + "name": "mj_stackAllocInt", + "return_type": "int *", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "size", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 283 + }, + "mj_deleteData": { + "name": "mj_deleteData", + "return_type": "void", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 286 + }, + "mj_resetCallbacks": { + "name": "mj_resetCallbacks", + "return_type": "void", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 289 + }, + "mj_setConst": { + "name": "mj_setConst", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 292 + }, + "mj_setLengthRange": { + "name": "mj_setLengthRange", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "index", + "c_type": "int", + "array_dim": null + }, + { + "name": "opt", + "c_type": "const mjLROpt *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "error_sz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 296 + }, + "mj_makeSpec": { + "name": "mj_makeSpec", + "return_type": "mjSpec *", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 300 + }, + "mj_copySpec": { + "name": "mj_copySpec", + "return_type": "mjSpec *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 303 + }, + "mj_deleteSpec": { + "name": "mj_deleteSpec", + "return_type": "void", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 306 + }, + "mjs_activatePlugin": { + "name": "mjs_activatePlugin", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 309 + }, + "mjs_setDeepCopy": { + "name": "mjs_setDeepCopy", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "deepcopy", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 312 + }, + "mj_printFormattedModel": { + "name": "mj_printFormattedModel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "float_format", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 319 + }, + "mj_printModel": { + "name": "mj_printModel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 322 + }, + "mj_printFormattedData": { + "name": "mj_printFormattedData", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "float_format", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 326 + }, + "mj_printData": { + "name": "mj_printData", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 330 + }, + "mju_printMat": { + "name": "mju_printMat", + "return_type": "void", + "params": [ + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 333 + }, + "mju_printMatSparse": { + "name": "mju_printMatSparse", + "return_type": "void", + "params": [ + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "rownnz", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "rowadr", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "colind", + "c_type": "const int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 336 + }, + "mj_printSchema": { + "name": "mj_printSchema", + "return_type": "int", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "buffer", + "c_type": "char *", + "array_dim": null + }, + { + "name": "buffer_sz", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_html", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_pad", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 340 + }, + "mj_printScene": { + "name": "mj_printScene", + "return_type": "void", + "params": [ + { + "name": "s", + "c_type": "const mjvScene *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 344 + }, + "mj_printFormattedScene": { + "name": "mj_printFormattedScene", + "return_type": "void", + "params": [ + { + "name": "s", + "c_type": "const mjvScene *", + "array_dim": null + }, + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "float_format", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 348 + }, + "mj_fwdKinematics": { + "name": "mj_fwdKinematics", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 355 + }, + "mj_fwdPosition": { + "name": "mj_fwdPosition", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 358 + }, + "mj_fwdVelocity": { + "name": "mj_fwdVelocity", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 361 + }, + "mj_fwdActuation": { + "name": "mj_fwdActuation", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 364 + }, + "mj_fwdAcceleration": { + "name": "mj_fwdAcceleration", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 367 + }, + "mj_fwdConstraint": { + "name": "mj_fwdConstraint", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 370 + }, + "mj_Euler": { + "name": "mj_Euler", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 373 + }, + "mj_RungeKutta": { + "name": "mj_RungeKutta", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "N", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 376 + }, + "mj_implicit": { + "name": "mj_implicit", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 379 + }, + "mj_invPosition": { + "name": "mj_invPosition", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 382 + }, + "mj_invVelocity": { + "name": "mj_invVelocity", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 385 + }, + "mj_invConstraint": { + "name": "mj_invConstraint", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 388 + }, + "mj_compareFwdInv": { + "name": "mj_compareFwdInv", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 391 + }, + "mj_sensorPos": { + "name": "mj_sensorPos", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 397 + }, + "mj_sensorVel": { + "name": "mj_sensorVel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 400 + }, + "mj_sensorAcc": { + "name": "mj_sensorAcc", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 403 + }, + "mj_energyPos": { + "name": "mj_energyPos", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 406 + }, + "mj_energyVel": { + "name": "mj_energyVel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 409 + }, + "mj_checkPos": { + "name": "mj_checkPos", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 412 + }, + "mj_checkVel": { + "name": "mj_checkVel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 415 + }, + "mj_checkAcc": { + "name": "mj_checkAcc", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 418 + }, + "mj_kinematics": { + "name": "mj_kinematics", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 421 + }, + "mj_comPos": { + "name": "mj_comPos", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 424 + }, + "mj_camlight": { + "name": "mj_camlight", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 427 + }, + "mj_flex": { + "name": "mj_flex", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 430 + }, + "mj_tendon": { + "name": "mj_tendon", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 433 + }, + "mj_transmission": { + "name": "mj_transmission", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 436 + }, + "mj_crb": { + "name": "mj_crb", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 439 + }, + "mj_makeM": { + "name": "mj_makeM", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 442 + }, + "mj_factorM": { + "name": "mj_factorM", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 445 + }, + "mj_solveM": { + "name": "mj_solveM", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "x", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "y", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 448 + }, + "mj_solveM2": { + "name": "mj_solveM2", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "x", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "y", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "sqrtInvD", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 451 + }, + "mj_comVel": { + "name": "mj_comVel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 455 + }, + "mj_passive": { + "name": "mj_passive", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 458 + }, + "mj_subtreeVel": { + "name": "mj_subtreeVel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 461 + }, + "mj_rne": { + "name": "mj_rne", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "flg_acc", + "c_type": "int", + "array_dim": null + }, + { + "name": "result", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 464 + }, + "mj_rnePostConstraint": { + "name": "mj_rnePostConstraint", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 467 + }, + "mj_maxContact": { + "name": "mj_maxContact", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "g1", + "c_type": "int", + "array_dim": null + }, + { + "name": "g2", + "c_type": "int", + "array_dim": null + }, + { + "name": "has_margin", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 472 + }, + "mj_collision": { + "name": "mj_collision", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 475 + }, + "mj_makeConstraint": { + "name": "mj_makeConstraint", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 478 + }, + "mj_island": { + "name": "mj_island", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 481 + }, + "mj_projectConstraint": { + "name": "mj_projectConstraint", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 484 + }, + "mj_referenceConstraint": { + "name": "mj_referenceConstraint", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 487 + }, + "mj_constraintUpdate": { + "name": "mj_constraintUpdate", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "jar", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "cost", + "c_type": "mjtNum [1]", + "array_dim": 1 + }, + { + "name": "flg_coneHessian", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 492 + }, + "mj_stateSize": { + "name": "mj_stateSize", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "sig", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 499 + }, + "mj_getState": { + "name": "mj_getState", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "state", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "sig", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 502 + }, + "mj_extractState": { + "name": "mj_extractState", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "srcsig", + "c_type": "int", + "array_dim": null + }, + { + "name": "dst", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "dstsig", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 505 + }, + "mj_setState": { + "name": "mj_setState", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "state", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "sig", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 509 + }, + "mj_copyState": { + "name": "mj_copyState", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "dst", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "sig", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 512 + }, + "mj_readCtrl": { + "name": "mj_readCtrl", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + }, + { + "name": "time", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "interp", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 517 + }, + "mj_readSensor": { + "name": "mj_readSensor", + "return_type": "const mjtNum *", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + }, + { + "name": "time", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "result", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "interp", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 523 + }, + "mj_initCtrlHistory": { + "name": "mj_initCtrlHistory", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + }, + { + "name": "times", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "values", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 528 + }, + "mj_initSensorHistory": { + "name": "mj_initSensorHistory", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + }, + { + "name": "times", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "values", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "phase", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 534 + }, + "mj_setKeyframe": { + "name": "mj_setKeyframe", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "k", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 538 + }, + "mj_addContact": { + "name": "mj_addContact", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjContact *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 541 + }, + "mj_isPyramidal": { + "name": "mj_isPyramidal", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 544 + }, + "mj_isSparse": { + "name": "mj_isSparse", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 547 + }, + "mj_isDual": { + "name": "mj_isDual", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 550 + }, + "mj_mulJacVec": { + "name": "mj_mulJacVec", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 553 + }, + "mj_mulJacTVec": { + "name": "mj_mulJacTVec", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 556 + }, + "mj_jac": { + "name": "mj_jac", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacr", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "point", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 560 + }, + "mj_jacBody": { + "name": "mj_jacBody", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacr", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 565 + }, + "mj_jacBodyCom": { + "name": "mj_jacBodyCom", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacr", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 569 + }, + "mj_jacSubtreeCom": { + "name": "mj_jacSubtreeCom", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 572 + }, + "mj_jacGeom": { + "name": "mj_jacGeom", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacr", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "geom", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 576 + }, + "mj_jacSite": { + "name": "mj_jacSite", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacr", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "site", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 580 + }, + "mj_jacPointAxis": { + "name": "mj_jacPointAxis", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "jacPoint", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacAxis", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "point", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "axis", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 584 + }, + "mj_jacDot": { + "name": "mj_jacDot", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "jacp", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "jacr", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "point", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 589 + }, + "mj_angmomMat": { + "name": "mj_angmomMat", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 593 + }, + "mj_name2id": { + "name": "mj_name2id", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "type", + "c_type": "int", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 596 + }, + "mj_id2name": { + "name": "mj_id2name", + "return_type": "const char *", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "type", + "c_type": "int", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 599 + }, + "mj_fullM": { + "name": "mj_fullM", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "dst", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "M", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 602 + }, + "mj_mulM": { + "name": "mj_mulM", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 605 + }, + "mj_mulM2": { + "name": "mj_mulM2", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 608 + }, + "mj_addM": { + "name": "mj_addM", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "dst", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "rownnz", + "c_type": "int *", + "array_dim": null + }, + { + "name": "rowadr", + "c_type": "int *", + "array_dim": null + }, + { + "name": "colind", + "c_type": "int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 613 + }, + "mj_applyFT": { + "name": "mj_applyFT", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "force", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "torque", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "point", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + }, + { + "name": "qfrc_target", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 617 + }, + "mj_objectVelocity": { + "name": "mj_objectVelocity", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "objtype", + "c_type": "int", + "array_dim": null + }, + { + "name": "objid", + "c_type": "int", + "array_dim": null + }, + { + "name": "res", + "c_type": "mjtNum [6]", + "array_dim": 6 + }, + { + "name": "flg_local", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 621 + }, + "mj_objectAcceleration": { + "name": "mj_objectAcceleration", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "objtype", + "c_type": "int", + "array_dim": null + }, + { + "name": "objid", + "c_type": "int", + "array_dim": null + }, + { + "name": "res", + "c_type": "mjtNum [6]", + "array_dim": 6 + }, + { + "name": "flg_local", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 625 + }, + "mj_geomDistance": { + "name": "mj_geomDistance", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "geom1", + "c_type": "int", + "array_dim": null + }, + { + "name": "geom2", + "c_type": "int", + "array_dim": null + }, + { + "name": "distmax", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "fromto", + "c_type": "mjtNum [6]", + "array_dim": 6 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 630 + }, + "mj_contactForce": { + "name": "mj_contactForce", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + }, + { + "name": "result", + "c_type": "mjtNum [6]", + "array_dim": 6 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 634 + }, + "mj_differentiatePos": { + "name": "mj_differentiatePos", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "qvel", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "dt", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "qpos1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "qpos2", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 637 + }, + "mj_integratePos": { + "name": "mj_integratePos", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "qpos", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "qvel", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "dt", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 641 + }, + "mj_normalizeQuat": { + "name": "mj_normalizeQuat", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "qpos", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 644 + }, + "mj_local2Global": { + "name": "mj_local2Global", + "return_type": "void", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "xpos", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "xmat", + "c_type": "mjtNum [9]", + "array_dim": 9 + }, + { + "name": "pos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "body", + "c_type": "int", + "array_dim": null + }, + { + "name": "sameframe", + "c_type": "mjtByte", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 647 + }, + "mj_getTotalmass": { + "name": "mj_getTotalmass", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 651 + }, + "mj_setTotalmass": { + "name": "mj_setTotalmass", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "newmass", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 654 + }, + "mj_getPluginConfig": { + "name": "mj_getPluginConfig", + "return_type": "const char *", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "plugin_id", + "c_type": "int", + "array_dim": null + }, + { + "name": "attrib", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 658 + }, + "mj_loadPluginLibrary": { + "name": "mj_loadPluginLibrary", + "return_type": "void", + "params": [ + { + "name": "path", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 661 + }, + "mj_loadAllPluginLibraries": { + "name": "mj_loadAllPluginLibraries", + "return_type": "void", + "params": [ + { + "name": "directory", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "callback", + "c_type": "mjfPluginLibraryLoadCallback", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 666 + }, + "mj_version": { + "name": "mj_version", + "return_type": "int", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 669 + }, + "mj_versionString": { + "name": "mj_versionString", + "return_type": "const char *", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 672 + }, + "mj_ray": { + "name": "mj_ray", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "geomgroup", + "c_type": "const mjtByte *", + "array_dim": null + }, + { + "name": "flg_static", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "bodyexclude", + "c_type": "int", + "array_dim": null + }, + { + "name": "geomid", + "c_type": "int [1]", + "array_dim": 1 + }, + { + "name": "normal", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 681 + }, + "mj_multiRay": { + "name": "mj_multiRay", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "geomgroup", + "c_type": "const mjtByte *", + "array_dim": null + }, + { + "name": "flg_static", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "bodyexclude", + "c_type": "int", + "array_dim": null + }, + { + "name": "geomid", + "c_type": "int *", + "array_dim": null + }, + { + "name": "dist", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "normal", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "nray", + "c_type": "int", + "array_dim": null + }, + { + "name": "cutoff", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 689 + }, + "mj_rayHfield": { + "name": "mj_rayHfield", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "geomid", + "c_type": "int", + "array_dim": null + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "normal", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 695 + }, + "mj_rayMesh": { + "name": "mj_rayMesh", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "geomid", + "c_type": "int", + "array_dim": null + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "normal", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 700 + }, + "mju_rayGeom": { + "name": "mju_rayGeom", + "return_type": "mjtNum", + "params": [ + { + "name": "pos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + }, + { + "name": "size", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "geomtype", + "c_type": "int", + "array_dim": null + }, + { + "name": "normal", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 705 + }, + "mj_rayFlex": { + "name": "mj_rayFlex", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "flex_layer", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_vert", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "flg_edge", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "flg_face", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "flg_skin", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "flexid", + "c_type": "int", + "array_dim": null + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vertid", + "c_type": "int [1]", + "array_dim": 1 + }, + { + "name": "normal", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 712 + }, + "mju_raySkin": { + "name": "mju_raySkin", + "return_type": "mjtNum", + "params": [ + { + "name": "nface", + "c_type": "int", + "array_dim": null + }, + { + "name": "nvert", + "c_type": "int", + "array_dim": null + }, + { + "name": "face", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "vert", + "c_type": "const float *", + "array_dim": null + }, + { + "name": "pnt", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vertid", + "c_type": "int [1]", + "array_dim": 1 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 720 + }, + "mjv_defaultCamera": { + "name": "mjv_defaultCamera", + "return_type": "void", + "params": [ + { + "name": "cam", + "c_type": "mjvCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 726 + }, + "mjv_defaultFreeCamera": { + "name": "mjv_defaultFreeCamera", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "cam", + "c_type": "mjvCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 729 + }, + "mjv_defaultPerturb": { + "name": "mjv_defaultPerturb", + "return_type": "void", + "params": [ + { + "name": "pert", + "c_type": "mjvPerturb *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 732 + }, + "mjv_room2model": { + "name": "mjv_room2model", + "return_type": "void", + "params": [ + { + "name": "modelpos", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "modelquat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "roompos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "roomquat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 735 + }, + "mjv_model2room": { + "name": "mjv_model2room", + "return_type": "void", + "params": [ + { + "name": "roompos", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "roomquat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "modelpos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "modelquat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 739 + }, + "mjv_cameraInModel": { + "name": "mjv_cameraInModel", + "return_type": "void", + "params": [ + { + "name": "headpos", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "forward", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "up", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 743 + }, + "mjv_cameraInRoom": { + "name": "mjv_cameraInRoom", + "return_type": "void", + "params": [ + { + "name": "headpos", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "forward", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "up", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 747 + }, + "mjv_frustumHeight": { + "name": "mjv_frustumHeight", + "return_type": "mjtNum", + "params": [ + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 751 + }, + "mjv_alignToCamera": { + "name": "mjv_alignToCamera", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "forward", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 754 + }, + "mjv_moveCamera": { + "name": "mjv_moveCamera", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "action", + "c_type": "int", + "array_dim": null + }, + { + "name": "reldx", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "reldy", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + }, + { + "name": "cam", + "c_type": "mjvCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 757 + }, + "mjv_movePerturb": { + "name": "mjv_movePerturb", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "action", + "c_type": "int", + "array_dim": null + }, + { + "name": "reldx", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "reldy", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + }, + { + "name": "pert", + "c_type": "mjvPerturb *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 761 + }, + "mjv_moveModel": { + "name": "mjv_moveModel", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "action", + "c_type": "int", + "array_dim": null + }, + { + "name": "reldx", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "reldy", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "roomup", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 765 + }, + "mjv_initPerturb": { + "name": "mjv_initPerturb", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + }, + { + "name": "pert", + "c_type": "mjvPerturb *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 769 + }, + "mjv_applyPerturbPose": { + "name": "mjv_applyPerturbPose", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "pert", + "c_type": "const mjvPerturb *", + "array_dim": null + }, + { + "name": "flg_paused", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 773 + }, + "mjv_applyPerturbForce": { + "name": "mjv_applyPerturbForce", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "pert", + "c_type": "const mjvPerturb *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 777 + }, + "mjv_averageCamera": { + "name": "mjv_averageCamera", + "return_type": "mjvGLCamera", + "params": [ + { + "name": "cam1", + "c_type": "const mjvGLCamera *", + "array_dim": null + }, + { + "name": "cam2", + "c_type": "const mjvGLCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 780 + }, + "mjv_select": { + "name": "mjv_select", + "return_type": "int", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "vopt", + "c_type": "const mjvOption *", + "array_dim": null + }, + { + "name": "aspectratio", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "relx", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "rely", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "scn", + "c_type": "const mjvScene *", + "array_dim": null + }, + { + "name": "selpnt", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "geomid", + "c_type": "int [1]", + "array_dim": 1 + }, + { + "name": "flexid", + "c_type": "int [1]", + "array_dim": 1 + }, + { + "name": "skinid", + "c_type": "int [1]", + "array_dim": 1 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 784 + }, + "mjv_defaultOption": { + "name": "mjv_defaultOption", + "return_type": "void", + "params": [ + { + "name": "opt", + "c_type": "mjvOption *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 793 + }, + "mjv_defaultFigure": { + "name": "mjv_defaultFigure", + "return_type": "void", + "params": [ + { + "name": "fig", + "c_type": "mjvFigure *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 796 + }, + "mjv_initGeom": { + "name": "mjv_initGeom", + "return_type": "void", + "params": [ + { + "name": "geom", + "c_type": "mjvGeom *", + "array_dim": null + }, + { + "name": "type", + "c_type": "int", + "array_dim": null + }, + { + "name": "size", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "pos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + }, + { + "name": "rgba", + "c_type": "const float [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 800 + }, + "mjv_connector": { + "name": "mjv_connector", + "return_type": "void", + "params": [ + { + "name": "geom", + "c_type": "mjvGeom *", + "array_dim": null + }, + { + "name": "type", + "c_type": "int", + "array_dim": null + }, + { + "name": "width", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "from", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "to", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 806 + }, + "mjv_defaultScene": { + "name": "mjv_defaultScene", + "return_type": "void", + "params": [ + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 810 + }, + "mjv_makeScene": { + "name": "mjv_makeScene", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + }, + { + "name": "maxgeom", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 813 + }, + "mjv_freeScene": { + "name": "mjv_freeScene", + "return_type": "void", + "params": [ + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 816 + }, + "mjv_updateScene": { + "name": "mjv_updateScene", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "opt", + "c_type": "const mjvOption *", + "array_dim": null + }, + { + "name": "pert", + "c_type": "const mjvPerturb *", + "array_dim": null + }, + { + "name": "cam", + "c_type": "mjvCamera *", + "array_dim": null + }, + { + "name": "catmask", + "c_type": "int", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 819 + }, + "mjv_copyModel": { + "name": "mjv_copyModel", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjModel *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const mjModel *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 824 + }, + "mjv_addGeoms": { + "name": "mjv_addGeoms", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "opt", + "c_type": "const mjvOption *", + "array_dim": null + }, + { + "name": "pert", + "c_type": "const mjvPerturb *", + "array_dim": null + }, + { + "name": "catmask", + "c_type": "int", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 827 + }, + "mjv_makeLights": { + "name": "mjv_makeLights", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 831 + }, + "mjv_updateCamera": { + "name": "mjv_updateCamera", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "cam", + "c_type": "mjvCamera *", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 834 + }, + "mjv_updateSkin": { + "name": "mjv_updateSkin", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 837 + }, + "mjv_cameraFrame": { + "name": "mjv_cameraFrame", + "return_type": "void", + "params": [ + { + "name": "headpos", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "forward", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "up", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "right", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "cam", + "c_type": "const mjvCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 841 + }, + "mjv_cameraFrustum": { + "name": "mjv_cameraFrustum", + "return_type": "void", + "params": [ + { + "name": "zver", + "c_type": "float [2]", + "array_dim": 2 + }, + { + "name": "zhor", + "c_type": "float [2]", + "array_dim": 2 + }, + { + "name": "zclip", + "c_type": "float [2]", + "array_dim": 2 + }, + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "cam", + "c_type": "const mjvCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 846 + }, + "mjr_defaultContext": { + "name": "mjr_defaultContext", + "return_type": "void", + "params": [ + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 853 + }, + "mjr_makeContext": { + "name": "mjr_makeContext", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + }, + { + "name": "fontscale", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 856 + }, + "mjr_changeFont": { + "name": "mjr_changeFont", + "return_type": "void", + "params": [ + { + "name": "fontscale", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 859 + }, + "mjr_addAux": { + "name": "mjr_addAux", + "return_type": "void", + "params": [ + { + "name": "index", + "c_type": "int", + "array_dim": null + }, + { + "name": "width", + "c_type": "int", + "array_dim": null + }, + { + "name": "height", + "c_type": "int", + "array_dim": null + }, + { + "name": "samples", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 862 + }, + "mjr_freeContext": { + "name": "mjr_freeContext", + "return_type": "void", + "params": [ + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 865 + }, + "mjr_resizeOffscreen": { + "name": "mjr_resizeOffscreen", + "return_type": "void", + "params": [ + { + "name": "width", + "c_type": "int", + "array_dim": null + }, + { + "name": "height", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 868 + }, + "mjr_uploadTexture": { + "name": "mjr_uploadTexture", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + }, + { + "name": "texid", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 871 + }, + "mjr_uploadMesh": { + "name": "mjr_uploadMesh", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + }, + { + "name": "meshid", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 874 + }, + "mjr_uploadHField": { + "name": "mjr_uploadHField", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + }, + { + "name": "hfieldid", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 877 + }, + "mjr_restoreBuffer": { + "name": "mjr_restoreBuffer", + "return_type": "void", + "params": [ + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 880 + }, + "mjr_setBuffer": { + "name": "mjr_setBuffer", + "return_type": "void", + "params": [ + { + "name": "framebuffer", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 884 + }, + "mjr_readPixels": { + "name": "mjr_readPixels", + "return_type": "void", + "params": [ + { + "name": "rgb", + "c_type": "unsigned char *", + "array_dim": null + }, + { + "name": "depth", + "c_type": "float *", + "array_dim": null + }, + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 888 + }, + "mjr_drawPixels": { + "name": "mjr_drawPixels", + "return_type": "void", + "params": [ + { + "name": "rgb", + "c_type": "const unsigned char *", + "array_dim": null + }, + { + "name": "depth", + "c_type": "const float *", + "array_dim": null + }, + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 893 + }, + "mjr_blitBuffer": { + "name": "mjr_blitBuffer", + "return_type": "void", + "params": [ + { + "name": "src", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "dst", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "flg_color", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_depth", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 898 + }, + "mjr_setAux": { + "name": "mjr_setAux", + "return_type": "void", + "params": [ + { + "name": "index", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 902 + }, + "mjr_blitAux": { + "name": "mjr_blitAux", + "return_type": "void", + "params": [ + { + "name": "index", + "c_type": "int", + "array_dim": null + }, + { + "name": "src", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "left", + "c_type": "int", + "array_dim": null + }, + { + "name": "bottom", + "c_type": "int", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 905 + }, + "mjr_text": { + "name": "mjr_text", + "return_type": "void", + "params": [ + { + "name": "font", + "c_type": "int", + "array_dim": null + }, + { + "name": "txt", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + }, + { + "name": "x", + "c_type": "float", + "array_dim": null + }, + { + "name": "y", + "c_type": "float", + "array_dim": null + }, + { + "name": "r", + "c_type": "float", + "array_dim": null + }, + { + "name": "g", + "c_type": "float", + "array_dim": null + }, + { + "name": "b", + "c_type": "float", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 908 + }, + "mjr_overlay": { + "name": "mjr_overlay", + "return_type": "void", + "params": [ + { + "name": "font", + "c_type": "int", + "array_dim": null + }, + { + "name": "gridpos", + "c_type": "int", + "array_dim": null + }, + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "overlay", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "overlay2", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 912 + }, + "mjr_maxViewport": { + "name": "mjr_maxViewport", + "return_type": "mjrRect", + "params": [ + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 916 + }, + "mjr_rectangle": { + "name": "mjr_rectangle", + "return_type": "void", + "params": [ + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "r", + "c_type": "float", + "array_dim": null + }, + { + "name": "g", + "c_type": "float", + "array_dim": null + }, + { + "name": "b", + "c_type": "float", + "array_dim": null + }, + { + "name": "a", + "c_type": "float", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 919 + }, + "mjr_label": { + "name": "mjr_label", + "return_type": "void", + "params": [ + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "font", + "c_type": "int", + "array_dim": null + }, + { + "name": "txt", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "r", + "c_type": "float", + "array_dim": null + }, + { + "name": "g", + "c_type": "float", + "array_dim": null + }, + { + "name": "b", + "c_type": "float", + "array_dim": null + }, + { + "name": "a", + "c_type": "float", + "array_dim": null + }, + { + "name": "rt", + "c_type": "float", + "array_dim": null + }, + { + "name": "gt", + "c_type": "float", + "array_dim": null + }, + { + "name": "bt", + "c_type": "float", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 922 + }, + "mjr_figure": { + "name": "mjr_figure", + "return_type": "void", + "params": [ + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "fig", + "c_type": "mjvFigure *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 927 + }, + "mjr_render": { + "name": "mjr_render", + "return_type": "void", + "params": [ + { + "name": "viewport", + "c_type": "mjrRect", + "array_dim": null + }, + { + "name": "scn", + "c_type": "mjvScene *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 930 + }, + "mjr_finish": { + "name": "mjr_finish", + "return_type": "void", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 933 + }, + "mjr_getError": { + "name": "mjr_getError", + "return_type": "int", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 936 + }, + "mjr_findRect": { + "name": "mjr_findRect", + "return_type": "int", + "params": [ + { + "name": "x", + "c_type": "int", + "array_dim": null + }, + { + "name": "y", + "c_type": "int", + "array_dim": null + }, + { + "name": "nrect", + "c_type": "int", + "array_dim": null + }, + { + "name": "rect", + "c_type": "const mjrRect *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 939 + }, + "mjui_themeSpacing": { + "name": "mjui_themeSpacing", + "return_type": "mjuiThemeSpacing", + "params": [ + { + "name": "ind", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 945 + }, + "mjui_themeColor": { + "name": "mjui_themeColor", + "return_type": "mjuiThemeColor", + "params": [ + { + "name": "ind", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 948 + }, + "mjui_add": { + "name": "mjui_add", + "return_type": "void", + "params": [ + { + "name": "ui", + "c_type": "mjUI *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjuiDef *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 951 + }, + "mjui_addToSection": { + "name": "mjui_addToSection", + "return_type": "void", + "params": [ + { + "name": "ui", + "c_type": "mjUI *", + "array_dim": null + }, + { + "name": "sect", + "c_type": "int", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjuiDef *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 954 + }, + "mjui_resize": { + "name": "mjui_resize", + "return_type": "void", + "params": [ + { + "name": "ui", + "c_type": "mjUI *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 957 + }, + "mjui_update": { + "name": "mjui_update", + "return_type": "void", + "params": [ + { + "name": "section", + "c_type": "int", + "array_dim": null + }, + { + "name": "item", + "c_type": "int", + "array_dim": null + }, + { + "name": "ui", + "c_type": "const mjUI *", + "array_dim": null + }, + { + "name": "state", + "c_type": "const mjuiState *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 960 + }, + "mjui_event": { + "name": "mjui_event", + "return_type": "mjuiItem *", + "params": [ + { + "name": "ui", + "c_type": "mjUI *", + "array_dim": null + }, + { + "name": "state", + "c_type": "mjuiState *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 964 + }, + "mjui_render": { + "name": "mjui_render", + "return_type": "void", + "params": [ + { + "name": "ui", + "c_type": "mjUI *", + "array_dim": null + }, + { + "name": "state", + "c_type": "const mjuiState *", + "array_dim": null + }, + { + "name": "con", + "c_type": "const mjrContext *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 967 + }, + "mju_error": { + "name": "mju_error", + "return_type": "void", + "params": [ + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 973 + }, + "mju_error_i": { + "name": "mju_error_i", + "return_type": "void", + "params": [ + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "i", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 976 + }, + "mju_error_s": { + "name": "mju_error_s", + "return_type": "void", + "params": [ + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "text", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 979 + }, + "mju_warning": { + "name": "mju_warning", + "return_type": "void", + "params": [ + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 982 + }, + "mju_warning_i": { + "name": "mju_warning_i", + "return_type": "void", + "params": [ + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "i", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 985 + }, + "mju_warning_s": { + "name": "mju_warning_s", + "return_type": "void", + "params": [ + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "text", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 988 + }, + "mju_clearHandlers": { + "name": "mju_clearHandlers", + "return_type": "void", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 991 + }, + "mju_malloc": { + "name": "mju_malloc", + "return_type": "void *", + "params": [ + { + "name": "size", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 994 + }, + "mju_free": { + "name": "mju_free", + "return_type": "void", + "params": [ + { + "name": "ptr", + "c_type": "void *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 997 + }, + "mj_warning": { + "name": "mj_warning", + "return_type": "void", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "warning", + "c_type": "int", + "array_dim": null + }, + { + "name": "info", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1000 + }, + "mju_writeLog": { + "name": "mju_writeLog", + "return_type": "void", + "params": [ + { + "name": "type", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "msg", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1003 + }, + "mjs_getError": { + "name": "mjs_getError", + "return_type": "const char *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1006 + }, + "mjs_isWarning": { + "name": "mjs_isWarning", + "return_type": "int", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1009 + }, + "mju_zero3": { + "name": "mju_zero3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1053 + }, + "mju_copy3": { + "name": "mju_copy3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "data", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1056 + }, + "mju_scl3": { + "name": "mju_scl3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scl", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1059 + }, + "mju_add3": { + "name": "mju_add3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec1", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec2", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1062 + }, + "mju_sub3": { + "name": "mju_sub3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec1", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec2", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1065 + }, + "mju_addTo3": { + "name": "mju_addTo3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1068 + }, + "mju_subFrom3": { + "name": "mju_subFrom3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1071 + }, + "mju_addToScl3": { + "name": "mju_addToScl3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scl", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1074 + }, + "mju_addScl3": { + "name": "mju_addScl3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec1", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec2", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scl", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1077 + }, + "mju_normalize3": { + "name": "mju_normalize3", + "return_type": "mjtNum", + "params": [ + { + "name": "vec", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1080 + }, + "mju_norm3": { + "name": "mju_norm3", + "return_type": "mjtNum", + "params": [ + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1083 + }, + "mju_dot3": { + "name": "mju_dot3", + "return_type": "mjtNum", + "params": [ + { + "name": "vec1", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec2", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1086 + }, + "mju_dist3": { + "name": "mju_dist3", + "return_type": "mjtNum", + "params": [ + { + "name": "pos1", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "pos2", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1089 + }, + "mju_mulMatVec3": { + "name": "mju_mulMatVec3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1092 + }, + "mju_mulMatTVec3": { + "name": "mju_mulMatTVec3", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1095 + }, + "mju_cross": { + "name": "mju_cross", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "a", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "b", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1098 + }, + "mju_zero4": { + "name": "mju_zero4", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1101 + }, + "mju_unit4": { + "name": "mju_unit4", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1104 + }, + "mju_copy4": { + "name": "mju_copy4", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "data", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1107 + }, + "mju_normalize4": { + "name": "mju_normalize4", + "return_type": "mjtNum", + "params": [ + { + "name": "vec", + "c_type": "mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1110 + }, + "mju_zero": { + "name": "mju_zero", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1113 + }, + "mju_fill": { + "name": "mju_fill", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "val", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1116 + }, + "mju_copy": { + "name": "mju_copy", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1119 + }, + "mju_sum": { + "name": "mju_sum", + "return_type": "mjtNum", + "params": [ + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1122 + }, + "mju_L1": { + "name": "mju_L1", + "return_type": "mjtNum", + "params": [ + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1125 + }, + "mju_scl": { + "name": "mju_scl", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "scl", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1128 + }, + "mju_add": { + "name": "mju_add", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1131 + }, + "mju_sub": { + "name": "mju_sub", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1134 + }, + "mju_addTo": { + "name": "mju_addTo", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1137 + }, + "mju_subFrom": { + "name": "mju_subFrom", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1140 + }, + "mju_addToScl": { + "name": "mju_addToScl", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "scl", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1143 + }, + "mju_addScl": { + "name": "mju_addScl", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "scl", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1146 + }, + "mju_normalize": { + "name": "mju_normalize", + "return_type": "mjtNum", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1149 + }, + "mju_norm": { + "name": "mju_norm", + "return_type": "mjtNum", + "params": [ + { + "name": "res", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1152 + }, + "mju_dot": { + "name": "mju_dot", + "return_type": "mjtNum", + "params": [ + { + "name": "vec1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1155 + }, + "mju_mulMatVec": { + "name": "mju_mulMatVec", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1158 + }, + "mju_mulMatTVec": { + "name": "mju_mulMatTVec", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1161 + }, + "mju_mulVecMatVec": { + "name": "mju_mulVecMatVec", + "return_type": "mjtNum", + "params": [ + { + "name": "vec1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1164 + }, + "mju_transpose": { + "name": "mju_transpose", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1167 + }, + "mju_symmetrize": { + "name": "mju_symmetrize", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1170 + }, + "mju_eye": { + "name": "mju_eye", + "return_type": "void", + "params": [ + { + "name": "mat", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1173 + }, + "mju_mulMatMat": { + "name": "mju_mulMatMat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "mat2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "r1", + "c_type": "int", + "array_dim": null + }, + { + "name": "c1", + "c_type": "int", + "array_dim": null + }, + { + "name": "c2", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1176 + }, + "mju_mulMatMatT": { + "name": "mju_mulMatMatT", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "mat2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "r1", + "c_type": "int", + "array_dim": null + }, + { + "name": "c1", + "c_type": "int", + "array_dim": null + }, + { + "name": "r2", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1180 + }, + "mju_mulMatTMat": { + "name": "mju_mulMatTMat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat1", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "mat2", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "r1", + "c_type": "int", + "array_dim": null + }, + { + "name": "c1", + "c_type": "int", + "array_dim": null + }, + { + "name": "c2", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1184 + }, + "mju_sqrMatTD": { + "name": "mju_sqrMatTD", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "diag", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1188 + }, + "mju_transformSpatial": { + "name": "mju_transformSpatial", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [6]", + "array_dim": 6 + }, + { + "name": "vec", + "c_type": "const mjtNum [6]", + "array_dim": 6 + }, + { + "name": "flg_force", + "c_type": "int", + "array_dim": null + }, + { + "name": "newpos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "oldpos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "rotnew2old", + "c_type": "const mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1193 + }, + "mju_dense2sparse": { + "name": "mju_dense2sparse", + "return_type": "int", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + }, + { + "name": "rownnz", + "c_type": "int *", + "array_dim": null + }, + { + "name": "rowadr", + "c_type": "int *", + "array_dim": null + }, + { + "name": "colind", + "c_type": "int *", + "array_dim": null + }, + { + "name": "nnz", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1202 + }, + "mju_sparse2dense": { + "name": "mju_sparse2dense", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "nr", + "c_type": "int", + "array_dim": null + }, + { + "name": "nc", + "c_type": "int", + "array_dim": null + }, + { + "name": "rownnz", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "rowadr", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "colind", + "c_type": "const int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1206 + }, + "mju_sym2dense": { + "name": "mju_sym2dense", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + }, + { + "name": "rownnz", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "rowadr", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "colind", + "c_type": "const int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1210 + }, + "mju_rotVecQuat": { + "name": "mju_rotVecQuat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1217 + }, + "mju_negQuat": { + "name": "mju_negQuat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1220 + }, + "mju_mulQuat": { + "name": "mju_mulQuat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "quat1", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "quat2", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1223 + }, + "mju_mulQuatAxis": { + "name": "mju_mulQuatAxis", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "axis", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1226 + }, + "mju_axisAngle2Quat": { + "name": "mju_axisAngle2Quat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "axis", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "angle", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1229 + }, + "mju_quat2Vel": { + "name": "mju_quat2Vel", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "dt", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1232 + }, + "mju_subQuat": { + "name": "mju_subQuat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "qa", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "qb", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1235 + }, + "mju_quat2Mat": { + "name": "mju_quat2Mat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [9]", + "array_dim": 9 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1238 + }, + "mju_mat2Quat": { + "name": "mju_mat2Quat", + "return_type": "void", + "params": [ + { + "name": "quat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1241 + }, + "mju_derivQuat": { + "name": "mju_derivQuat", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "vel", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1244 + }, + "mju_quatIntegrate": { + "name": "mju_quatIntegrate", + "return_type": "void", + "params": [ + { + "name": "quat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "vel", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scale", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1247 + }, + "mju_quatZ2Vec": { + "name": "mju_quatZ2Vec", + "return_type": "void", + "params": [ + { + "name": "quat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1250 + }, + "mju_mat2Rot": { + "name": "mju_mat2Rot", + "return_type": "int", + "params": [ + { + "name": "quat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1254 + }, + "mju_euler2Quat": { + "name": "mju_euler2Quat", + "return_type": "void", + "params": [ + { + "name": "quat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "euler", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "seq", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1258 + }, + "mju_mulPose": { + "name": "mju_mulPose", + "return_type": "void", + "params": [ + { + "name": "posres", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quatres", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "pos1", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat1", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "pos2", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat2", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1264 + }, + "mju_negPose": { + "name": "mju_negPose", + "return_type": "void", + "params": [ + { + "name": "posres", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quatres", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "pos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1269 + }, + "mju_trnVecPose": { + "name": "mju_trnVecPose", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "pos", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "quat", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "vec", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1273 + }, + "mju_cholFactor": { + "name": "mju_cholFactor", + "return_type": "int", + "params": [ + { + "name": "mat", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + }, + { + "name": "mindiag", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1280 + }, + "mju_cholSolve": { + "name": "mju_cholSolve", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1283 + }, + "mju_cholUpdate": { + "name": "mju_cholUpdate", + "return_type": "int", + "params": [ + { + "name": "mat", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "x", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_plus", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1286 + }, + "mju_cholFactorBand": { + "name": "mju_cholFactorBand", + "return_type": "mjtNum", + "params": [ + { + "name": "mat", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "ntotal", + "c_type": "int", + "array_dim": null + }, + { + "name": "nband", + "c_type": "int", + "array_dim": null + }, + { + "name": "ndense", + "c_type": "int", + "array_dim": null + }, + { + "name": "diagadd", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "diagmul", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1294 + }, + "mju_cholSolveBand": { + "name": "mju_cholSolveBand", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "ntotal", + "c_type": "int", + "array_dim": null + }, + { + "name": "nband", + "c_type": "int", + "array_dim": null + }, + { + "name": "ndense", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1298 + }, + "mju_band2Dense": { + "name": "mju_band2Dense", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "ntotal", + "c_type": "int", + "array_dim": null + }, + { + "name": "nband", + "c_type": "int", + "array_dim": null + }, + { + "name": "ndense", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_sym", + "c_type": "mjtByte", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1302 + }, + "mju_dense2Band": { + "name": "mju_dense2Band", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "ntotal", + "c_type": "int", + "array_dim": null + }, + { + "name": "nband", + "c_type": "int", + "array_dim": null + }, + { + "name": "ndense", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1306 + }, + "mju_bandMulMatVec": { + "name": "mju_bandMulMatVec", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "mat", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "ntotal", + "c_type": "int", + "array_dim": null + }, + { + "name": "nband", + "c_type": "int", + "array_dim": null + }, + { + "name": "ndense", + "c_type": "int", + "array_dim": null + }, + { + "name": "nvec", + "c_type": "int", + "array_dim": null + }, + { + "name": "flg_sym", + "c_type": "mjtByte", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1309 + }, + "mju_bandDiag": { + "name": "mju_bandDiag", + "return_type": "int", + "params": [ + { + "name": "i", + "c_type": "int", + "array_dim": null + }, + { + "name": "ntotal", + "c_type": "int", + "array_dim": null + }, + { + "name": "nband", + "c_type": "int", + "array_dim": null + }, + { + "name": "ndense", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1313 + }, + "mju_eig3": { + "name": "mju_eig3", + "return_type": "int", + "params": [ + { + "name": "eigval", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "eigvec", + "c_type": "mjtNum [9]", + "array_dim": 9 + }, + { + "name": "quat", + "c_type": "mjtNum [4]", + "array_dim": 4 + }, + { + "name": "mat", + "c_type": "const mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1316 + }, + "mju_boxQP": { + "name": "mju_boxQP", + "return_type": "int", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "R", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "index", + "c_type": "int *", + "array_dim": null + }, + { + "name": "H", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "g", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + }, + { + "name": "lower", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "upper", + "c_type": "const mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1340 + }, + "mju_boxQPmalloc": { + "name": "mju_boxQPmalloc", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum **", + "array_dim": null + }, + { + "name": "R", + "c_type": "mjtNum **", + "array_dim": null + }, + { + "name": "index", + "c_type": "int **", + "array_dim": null + }, + { + "name": "H", + "c_type": "mjtNum **", + "array_dim": null + }, + { + "name": "g", + "c_type": "mjtNum **", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + }, + { + "name": "lower", + "c_type": "mjtNum **", + "array_dim": null + }, + { + "name": "upper", + "c_type": "mjtNum **", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1346 + }, + "mju_muscleGain": { + "name": "mju_muscleGain", + "return_type": "mjtNum", + "params": [ + { + "name": "len", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "vel", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "lengthrange", + "c_type": "const mjtNum [2]", + "array_dim": 2 + }, + { + "name": "acc0", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "prm", + "c_type": "const mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1353 + }, + "mju_muscleBias": { + "name": "mju_muscleBias", + "return_type": "mjtNum", + "params": [ + { + "name": "len", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "lengthrange", + "c_type": "const mjtNum [2]", + "array_dim": 2 + }, + { + "name": "acc0", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "prm", + "c_type": "const mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1357 + }, + "mju_muscleDynamics": { + "name": "mju_muscleDynamics", + "return_type": "mjtNum", + "params": [ + { + "name": "ctrl", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "act", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "prm", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1361 + }, + "mju_encodePyramid": { + "name": "mju_encodePyramid", + "return_type": "void", + "params": [ + { + "name": "pyramid", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "force", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "mu", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "dim", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1364 + }, + "mju_decodePyramid": { + "name": "mju_decodePyramid", + "return_type": "void", + "params": [ + { + "name": "force", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "pyramid", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "mu", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "dim", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1367 + }, + "mju_springDamper": { + "name": "mju_springDamper", + "return_type": "mjtNum", + "params": [ + { + "name": "pos0", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "vel0", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "Kp", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "Kv", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "dt", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1370 + }, + "mju_min": { + "name": "mju_min", + "return_type": "mjtNum", + "params": [ + { + "name": "a", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "b", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1373 + }, + "mju_max": { + "name": "mju_max", + "return_type": "mjtNum", + "params": [ + { + "name": "a", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "b", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1376 + }, + "mju_clip": { + "name": "mju_clip", + "return_type": "mjtNum", + "params": [ + { + "name": "x", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "min", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "max", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1379 + }, + "mju_sign": { + "name": "mju_sign", + "return_type": "mjtNum", + "params": [ + { + "name": "x", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1382 + }, + "mju_round": { + "name": "mju_round", + "return_type": "int", + "params": [ + { + "name": "x", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1385 + }, + "mju_type2Str": { + "name": "mju_type2Str", + "return_type": "const char *", + "params": [ + { + "name": "type", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1388 + }, + "mju_str2Type": { + "name": "mju_str2Type", + "return_type": "int", + "params": [ + { + "name": "str", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1391 + }, + "mju_writeNumBytes": { + "name": "mju_writeNumBytes", + "return_type": "const char *", + "params": [ + { + "name": "nbytes", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1394 + }, + "mju_warningText": { + "name": "mju_warningText", + "return_type": "const char *", + "params": [ + { + "name": "warning", + "c_type": "int", + "array_dim": null + }, + { + "name": "info", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1397 + }, + "mju_isBad": { + "name": "mju_isBad", + "return_type": "int", + "params": [ + { + "name": "x", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1400 + }, + "mju_isZero": { + "name": "mju_isZero", + "return_type": "int", + "params": [ + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1403 + }, + "mju_standardNormal": { + "name": "mju_standardNormal", + "return_type": "mjtNum", + "params": [ + { + "name": "num2", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1406 + }, + "mju_f2n": { + "name": "mju_f2n", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const float *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1409 + }, + "mju_n2f": { + "name": "mju_n2f", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "float *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1412 + }, + "mju_d2n": { + "name": "mju_d2n", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const double *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1415 + }, + "mju_n2d": { + "name": "mju_n2d", + "return_type": "void", + "params": [ + { + "name": "res", + "c_type": "double *", + "array_dim": null + }, + { + "name": "vec", + "c_type": "const mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1418 + }, + "mju_insertionSort": { + "name": "mju_insertionSort", + "return_type": "void", + "params": [ + { + "name": "list", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1421 + }, + "mju_insertionSortInt": { + "name": "mju_insertionSortInt", + "return_type": "void", + "params": [ + { + "name": "list", + "c_type": "int *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1424 + }, + "mju_Halton": { + "name": "mju_Halton", + "return_type": "mjtNum", + "params": [ + { + "name": "index", + "c_type": "int", + "array_dim": null + }, + { + "name": "base", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1427 + }, + "mju_strncpy": { + "name": "mju_strncpy", + "return_type": "char *", + "params": [ + { + "name": "dst", + "c_type": "char *", + "array_dim": null + }, + { + "name": "src", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "n", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1430 + }, + "mju_sigmoid": { + "name": "mju_sigmoid", + "return_type": "mjtNum", + "params": [ + { + "name": "x", + "c_type": "mjtNum", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1433 + }, + "mjc_getSDF": { + "name": "mjc_getSDF", + "return_type": "const mjpPlugin *", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "id", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1439 + }, + "mjc_distance": { + "name": "mjc_distance", + "return_type": "mjtNum", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "s", + "c_type": "const mjSDF *", + "array_dim": null + }, + { + "name": "x", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1442 + }, + "mjc_gradient": { + "name": "mjc_gradient", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "const mjData *", + "array_dim": null + }, + { + "name": "s", + "c_type": "const mjSDF *", + "array_dim": null + }, + { + "name": "gradient", + "c_type": "mjtNum [3]", + "array_dim": 3 + }, + { + "name": "x", + "c_type": "const mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1445 + }, + "mjd_transitionFD": { + "name": "mjd_transitionFD", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "eps", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "flg_centered", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "A", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "B", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "C", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "D", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1460 + }, + "mjd_inverseFD": { + "name": "mjd_inverseFD", + "return_type": "void", + "params": [ + { + "name": "m", + "c_type": "const mjModel *", + "array_dim": null + }, + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "eps", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "flg_actuation", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "DfDq", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "DfDv", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "DfDa", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "DsDq", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "DsDv", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "DsDa", + "c_type": "mjtNum *", + "array_dim": null + }, + { + "name": "DmDq", + "c_type": "mjtNum *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1479 + }, + "mjd_subQuat": { + "name": "mjd_subQuat", + "return_type": "void", + "params": [ + { + "name": "qa", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "qb", + "c_type": "const mjtNum [4]", + "array_dim": 4 + }, + { + "name": "Da", + "c_type": "mjtNum [9]", + "array_dim": 9 + }, + { + "name": "Db", + "c_type": "mjtNum [9]", + "array_dim": 9 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1486 + }, + "mjd_quatIntegrate": { + "name": "mjd_quatIntegrate", + "return_type": "void", + "params": [ + { + "name": "vel", + "c_type": "const mjtNum [3]", + "array_dim": 3 + }, + { + "name": "scale", + "c_type": "mjtNum", + "array_dim": null + }, + { + "name": "Dquat", + "c_type": "mjtNum [9]", + "array_dim": 9 + }, + { + "name": "Dvel", + "c_type": "mjtNum [9]", + "array_dim": 9 + }, + { + "name": "Dscale", + "c_type": "mjtNum [3]", + "array_dim": 3 + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1490 + }, + "mjp_defaultPlugin": { + "name": "mjp_defaultPlugin", + "return_type": "void", + "params": [ + { + "name": "plugin", + "c_type": "mjpPlugin *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1497 + }, + "mjp_registerPlugin": { + "name": "mjp_registerPlugin", + "return_type": "int", + "params": [ + { + "name": "plugin", + "c_type": "const mjpPlugin *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1505 + }, + "mjp_pluginCount": { + "name": "mjp_pluginCount", + "return_type": "int", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1508 + }, + "mjp_getPlugin": { + "name": "mjp_getPlugin", + "return_type": "const mjpPlugin *", + "params": [ + { + "name": "name", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "slot", + "c_type": "int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1511 + }, + "mjp_getPluginAtSlot": { + "name": "mjp_getPluginAtSlot", + "return_type": "const mjpPlugin *", + "params": [ + { + "name": "slot", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1514 + }, + "mjp_defaultResourceProvider": { + "name": "mjp_defaultResourceProvider", + "return_type": "void", + "params": [ + { + "name": "provider", + "c_type": "mjpResourceProvider *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1517 + }, + "mjp_registerResourceProvider": { + "name": "mjp_registerResourceProvider", + "return_type": "int", + "params": [ + { + "name": "provider", + "c_type": "const mjpResourceProvider *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1522 + }, + "mjp_resourceProviderCount": { + "name": "mjp_resourceProviderCount", + "return_type": "int", + "params": [], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1525 + }, + "mjp_getResourceProvider": { + "name": "mjp_getResourceProvider", + "return_type": "const mjpResourceProvider *", + "params": [ + { + "name": "resource_name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1529 + }, + "mjp_getResourceProviderAtSlot": { + "name": "mjp_getResourceProviderAtSlot", + "return_type": "const mjpResourceProvider *", + "params": [ + { + "name": "slot", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1533 + }, + "mjp_registerDecoder": { + "name": "mjp_registerDecoder", + "return_type": "void", + "params": [ + { + "name": "decoder", + "c_type": "const mjpDecoder *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1538 + }, + "mjp_defaultDecoder": { + "name": "mjp_defaultDecoder", + "return_type": "void", + "params": [ + { + "name": "decoder", + "c_type": "mjpDecoder *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1541 + }, + "mjp_findDecoder": { + "name": "mjp_findDecoder", + "return_type": "const mjpDecoder *", + "params": [ + { + "name": "resource", + "c_type": "const mjResource *", + "array_dim": null + }, + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1545 + }, + "mjp_registerEncoder": { + "name": "mjp_registerEncoder", + "return_type": "void", + "params": [ + { + "name": "encoder", + "c_type": "const mjpEncoder *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1550 + }, + "mjp_defaultEncoder": { + "name": "mjp_defaultEncoder", + "return_type": "void", + "params": [ + { + "name": "encoder", + "c_type": "mjpEncoder *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1553 + }, + "mjp_findEncoder": { + "name": "mjp_findEncoder", + "return_type": "const mjpEncoder *", + "params": [ + { + "name": "filename", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1557 + }, + "mju_openResource": { + "name": "mju_openResource", + "return_type": "mjResource *", + "params": [ + { + "name": "dir", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + }, + { + "name": "error", + "c_type": "char *", + "array_dim": null + }, + { + "name": "nerror", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1566 + }, + "mju_closeResource": { + "name": "mju_closeResource", + "return_type": "void", + "params": [ + { + "name": "resource", + "c_type": "mjResource *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1570 + }, + "mju_readResource": { + "name": "mju_readResource", + "return_type": "int", + "params": [ + { + "name": "resource", + "c_type": "mjResource *", + "array_dim": null + }, + { + "name": "buffer", + "c_type": "const void **", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1574 + }, + "mju_getResourceDir": { + "name": "mju_getResourceDir", + "return_type": "void", + "params": [ + { + "name": "resource", + "c_type": "mjResource *", + "array_dim": null + }, + { + "name": "dir", + "c_type": "const char **", + "array_dim": null + }, + { + "name": "ndir", + "c_type": "int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1577 + }, + "mju_isModifiedResource": { + "name": "mju_isModifiedResource", + "return_type": "int", + "params": [ + { + "name": "resource", + "c_type": "const mjResource *", + "array_dim": null + }, + { + "name": "timestamp", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1581 + }, + "mju_decodeResource": { + "name": "mju_decodeResource", + "return_type": "mjSpec *", + "params": [ + { + "name": "resource", + "c_type": "mjResource *", + "array_dim": null + }, + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "vfs", + "c_type": "const mjVFS *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1586 + }, + "mju_threadPoolCreate": { + "name": "mju_threadPoolCreate", + "return_type": "mjThreadPool *", + "params": [ + { + "name": "number_of_threads", + "c_type": "size_t", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1593 + }, + "mju_bindThreadPool": { + "name": "mju_bindThreadPool", + "return_type": "void", + "params": [ + { + "name": "d", + "c_type": "mjData *", + "array_dim": null + }, + { + "name": "thread_pool", + "c_type": "void *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1596 + }, + "mju_threadPoolEnqueue": { + "name": "mju_threadPoolEnqueue", + "return_type": "void", + "params": [ + { + "name": "thread_pool", + "c_type": "mjThreadPool *", + "array_dim": null + }, + { + "name": "task", + "c_type": "mjTask *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1599 + }, + "mju_threadPoolDestroy": { + "name": "mju_threadPoolDestroy", + "return_type": "void", + "params": [ + { + "name": "thread_pool", + "c_type": "mjThreadPool *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1602 + }, + "mju_defaultTask": { + "name": "mju_defaultTask", + "return_type": "void", + "params": [ + { + "name": "task", + "c_type": "mjTask *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1605 + }, + "mju_taskJoin": { + "name": "mju_taskJoin", + "return_type": "void", + "params": [ + { + "name": "task", + "c_type": "mjTask *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1608 + }, + "mjs_attach": { + "name": "mjs_attach", + "return_type": "mjsElement *", + "params": [ + { + "name": "parent", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "child", + "c_type": "const mjsElement *", + "array_dim": null + }, + { + "name": "prefix", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "suffix", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1614 + }, + "mjs_addBody": { + "name": "mjs_addBody", + "return_type": "mjsBody *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1622 + }, + "mjs_addSite": { + "name": "mjs_addSite", + "return_type": "mjsSite *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1626 + }, + "mjs_addJoint": { + "name": "mjs_addJoint", + "return_type": "mjsJoint *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1630 + }, + "mjs_addFreeJoint": { + "name": "mjs_addFreeJoint", + "return_type": "mjsJoint *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1633 + }, + "mjs_addGeom": { + "name": "mjs_addGeom", + "return_type": "mjsGeom *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1637 + }, + "mjs_addCamera": { + "name": "mjs_addCamera", + "return_type": "mjsCamera *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1641 + }, + "mjs_addLight": { + "name": "mjs_addLight", + "return_type": "mjsLight *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1645 + }, + "mjs_addFrame": { + "name": "mjs_addFrame", + "return_type": "mjsFrame *", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + }, + { + "name": "parentframe", + "c_type": "mjsFrame *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1648 + }, + "mjs_delete": { + "name": "mjs_delete", + "return_type": "int", + "params": [ + { + "name": "spec", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1651 + }, + "mjs_addActuator": { + "name": "mjs_addActuator", + "return_type": "mjsActuator *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1658 + }, + "mjs_addSensor": { + "name": "mjs_addSensor", + "return_type": "mjsSensor *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1661 + }, + "mjs_addFlex": { + "name": "mjs_addFlex", + "return_type": "mjsFlex *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1664 + }, + "mjs_addPair": { + "name": "mjs_addPair", + "return_type": "mjsPair *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1668 + }, + "mjs_addExclude": { + "name": "mjs_addExclude", + "return_type": "mjsExclude *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1671 + }, + "mjs_addEquality": { + "name": "mjs_addEquality", + "return_type": "mjsEquality *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1675 + }, + "mjs_addTendon": { + "name": "mjs_addTendon", + "return_type": "mjsTendon *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1679 + }, + "mjs_wrapSite": { + "name": "mjs_wrapSite", + "return_type": "mjsWrap *", + "params": [ + { + "name": "tendon", + "c_type": "mjsTendon *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1682 + }, + "mjs_wrapGeom": { + "name": "mjs_wrapGeom", + "return_type": "mjsWrap *", + "params": [ + { + "name": "tendon", + "c_type": "mjsTendon *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "sidesite", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1685 + }, + "mjs_wrapJoint": { + "name": "mjs_wrapJoint", + "return_type": "mjsWrap *", + "params": [ + { + "name": "tendon", + "c_type": "mjsTendon *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "coef", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1688 + }, + "mjs_wrapPulley": { + "name": "mjs_wrapPulley", + "return_type": "mjsWrap *", + "params": [ + { + "name": "tendon", + "c_type": "mjsTendon *", + "array_dim": null + }, + { + "name": "divisor", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1691 + }, + "mjs_addNumeric": { + "name": "mjs_addNumeric", + "return_type": "mjsNumeric *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1694 + }, + "mjs_addText": { + "name": "mjs_addText", + "return_type": "mjsText *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1697 + }, + "mjs_addTuple": { + "name": "mjs_addTuple", + "return_type": "mjsTuple *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1700 + }, + "mjs_addKey": { + "name": "mjs_addKey", + "return_type": "mjsKey *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1703 + }, + "mjs_addPlugin": { + "name": "mjs_addPlugin", + "return_type": "mjsPlugin *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1706 + }, + "mjs_addDefault": { + "name": "mjs_addDefault", + "return_type": "mjsDefault *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "classname", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "parent", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1710 + }, + "mjs_setToMotor": { + "name": "mjs_setToMotor", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1716 + }, + "mjs_setToPosition": { + "name": "mjs_setToPosition", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "kp", + "c_type": "double", + "array_dim": null + }, + { + "name": "kv", + "c_type": "double [1]", + "array_dim": 1 + }, + { + "name": "dampratio", + "c_type": "double [1]", + "array_dim": 1 + }, + { + "name": "timeconst", + "c_type": "double [1]", + "array_dim": 1 + }, + { + "name": "inheritrange", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1719 + }, + "mjs_setToIntVelocity": { + "name": "mjs_setToIntVelocity", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "kp", + "c_type": "double", + "array_dim": null + }, + { + "name": "kv", + "c_type": "double [1]", + "array_dim": 1 + }, + { + "name": "dampratio", + "c_type": "double [1]", + "array_dim": 1 + }, + { + "name": "timeconst", + "c_type": "double [1]", + "array_dim": 1 + }, + { + "name": "inheritrange", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1723 + }, + "mjs_setToVelocity": { + "name": "mjs_setToVelocity", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "kv", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1727 + }, + "mjs_setToDamper": { + "name": "mjs_setToDamper", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "kv", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1730 + }, + "mjs_setToCylinder": { + "name": "mjs_setToCylinder", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "timeconst", + "c_type": "double", + "array_dim": null + }, + { + "name": "bias", + "c_type": "double", + "array_dim": null + }, + { + "name": "area", + "c_type": "double", + "array_dim": null + }, + { + "name": "diameter", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1733 + }, + "mjs_setToMuscle": { + "name": "mjs_setToMuscle", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "timeconst", + "c_type": "double [2]", + "array_dim": 2 + }, + { + "name": "tausmooth", + "c_type": "double", + "array_dim": null + }, + { + "name": "range", + "c_type": "double [2]", + "array_dim": 2 + }, + { + "name": "force", + "c_type": "double", + "array_dim": null + }, + { + "name": "scale", + "c_type": "double", + "array_dim": null + }, + { + "name": "lmin", + "c_type": "double", + "array_dim": null + }, + { + "name": "lmax", + "c_type": "double", + "array_dim": null + }, + { + "name": "vmax", + "c_type": "double", + "array_dim": null + }, + { + "name": "fpmax", + "c_type": "double", + "array_dim": null + }, + { + "name": "fvmax", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1737 + }, + "mjs_setToAdhesion": { + "name": "mjs_setToAdhesion", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "gain", + "c_type": "double", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1742 + }, + "mjs_setToDCMotor": { + "name": "mjs_setToDCMotor", + "return_type": "const char *", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + }, + { + "name": "motorconst", + "c_type": "double [2]", + "array_dim": 2 + }, + { + "name": "resistance", + "c_type": "double", + "array_dim": null + }, + { + "name": "nominal", + "c_type": "double [3]", + "array_dim": 3 + }, + { + "name": "saturation", + "c_type": "double [3]", + "array_dim": 3 + }, + { + "name": "inductance", + "c_type": "double [2]", + "array_dim": 2 + }, + { + "name": "cogging", + "c_type": "double [3]", + "array_dim": 3 + }, + { + "name": "controller", + "c_type": "double [6]", + "array_dim": 6 + }, + { + "name": "thermal", + "c_type": "double [6]", + "array_dim": 6 + }, + { + "name": "lugre", + "c_type": "double [5]", + "array_dim": 5 + }, + { + "name": "input_mode", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1746 + }, + "mjs_addMesh": { + "name": "mjs_addMesh", + "return_type": "mjsMesh *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1756 + }, + "mjs_addHField": { + "name": "mjs_addHField", + "return_type": "mjsHField *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1759 + }, + "mjs_addSkin": { + "name": "mjs_addSkin", + "return_type": "mjsSkin *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1762 + }, + "mjs_addTexture": { + "name": "mjs_addTexture", + "return_type": "mjsTexture *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1765 + }, + "mjs_addMaterial": { + "name": "mjs_addMaterial", + "return_type": "mjsMaterial *", + "params": [ + { + "name": "s", + "c_type": "mjSpec *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1769 + }, + "mjs_makeMesh": { + "name": "mjs_makeMesh", + "return_type": "int", + "params": [ + { + "name": "mesh", + "c_type": "mjsMesh *", + "array_dim": null + }, + { + "name": "builtin", + "c_type": "mjtMeshBuiltin", + "array_dim": null + }, + { + "name": "params", + "c_type": "double *", + "array_dim": null + }, + { + "name": "nparams", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1772 + }, + "mjs_getSpec": { + "name": "mjs_getSpec", + "return_type": "mjSpec *", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1777 + }, + "mjs_getOriginSpec": { + "name": "mjs_getOriginSpec", + "return_type": "mjSpec *", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1781 + }, + "mjs_getCompiler": { + "name": "mjs_getCompiler", + "return_type": "mjsCompiler *", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1784 + }, + "mjs_findSpec": { + "name": "mjs_findSpec", + "return_type": "mjSpec *", + "params": [ + { + "name": "spec", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1787 + }, + "mjs_findBody": { + "name": "mjs_findBody", + "return_type": "mjsBody *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1790 + }, + "mjs_findElement": { + "name": "mjs_findElement", + "return_type": "mjsElement *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "type", + "c_type": "mjtObj", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1793 + }, + "mjs_findChild": { + "name": "mjs_findChild", + "return_type": "mjsBody *", + "params": [ + { + "name": "body", + "c_type": "const mjsBody *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1796 + }, + "mjs_getParent": { + "name": "mjs_getParent", + "return_type": "mjsBody *", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1799 + }, + "mjs_getFrame": { + "name": "mjs_getFrame", + "return_type": "mjsFrame *", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1802 + }, + "mjs_findFrame": { + "name": "mjs_findFrame", + "return_type": "mjsFrame *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1805 + }, + "mjs_getDefault": { + "name": "mjs_getDefault", + "return_type": "mjsDefault *", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1808 + }, + "mjs_findDefault": { + "name": "mjs_findDefault", + "return_type": "mjsDefault *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "classname", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1811 + }, + "mjs_getSpecDefault": { + "name": "mjs_getSpecDefault", + "return_type": "mjsDefault *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1814 + }, + "mjs_getId": { + "name": "mjs_getId", + "return_type": "int", + "params": [ + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1817 + }, + "mjs_firstChild": { + "name": "mjs_firstChild", + "return_type": "mjsElement *", + "params": [ + { + "name": "body", + "c_type": "const mjsBody *", + "array_dim": null + }, + { + "name": "type", + "c_type": "mjtObj", + "array_dim": null + }, + { + "name": "recurse", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1820 + }, + "mjs_nextChild": { + "name": "mjs_nextChild", + "return_type": "mjsElement *", + "params": [ + { + "name": "body", + "c_type": "const mjsBody *", + "array_dim": null + }, + { + "name": "child", + "c_type": "const mjsElement *", + "array_dim": null + }, + { + "name": "recurse", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1824 + }, + "mjs_firstElement": { + "name": "mjs_firstElement", + "return_type": "mjsElement *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "type", + "c_type": "mjtObj", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1827 + }, + "mjs_nextElement": { + "name": "mjs_nextElement", + "return_type": "mjsElement *", + "params": [ + { + "name": "s", + "c_type": "const mjSpec *", + "array_dim": null + }, + { + "name": "element", + "c_type": "const mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1830 + }, + "mjs_getWrapTarget": { + "name": "mjs_getWrapTarget", + "return_type": "mjsElement *", + "params": [ + { + "name": "wrap", + "c_type": "const mjsWrap *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1833 + }, + "mjs_getWrapSideSite": { + "name": "mjs_getWrapSideSite", + "return_type": "mjsSite *", + "params": [ + { + "name": "wrap", + "c_type": "const mjsWrap *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1836 + }, + "mjs_getWrapDivisor": { + "name": "mjs_getWrapDivisor", + "return_type": "double", + "params": [ + { + "name": "wrap", + "c_type": "const mjsWrap *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1839 + }, + "mjs_getWrapCoef": { + "name": "mjs_getWrapCoef", + "return_type": "double", + "params": [ + { + "name": "wrap", + "c_type": "const mjsWrap *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1842 + }, + "mjs_setName": { + "name": "mjs_setName", + "return_type": "int", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "name", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1847 + }, + "mjs_setBuffer": { + "name": "mjs_setBuffer", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjByteVec *", + "array_dim": null + }, + { + "name": "array", + "c_type": "const void *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1850 + }, + "mjs_setString": { + "name": "mjs_setString", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjString *", + "array_dim": null + }, + { + "name": "text", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1853 + }, + "mjs_setStringVec": { + "name": "mjs_setStringVec", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjStringVec *", + "array_dim": null + }, + { + "name": "text", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1856 + }, + "mjs_setInStringVec": { + "name": "mjs_setInStringVec", + "return_type": "mjtByte", + "params": [ + { + "name": "dest", + "c_type": "mjStringVec *", + "array_dim": null + }, + { + "name": "i", + "c_type": "int", + "array_dim": null + }, + { + "name": "text", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1859 + }, + "mjs_appendString": { + "name": "mjs_appendString", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjStringVec *", + "array_dim": null + }, + { + "name": "text", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1862 + }, + "mjs_setInt": { + "name": "mjs_setInt", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjIntVec *", + "array_dim": null + }, + { + "name": "array", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1865 + }, + "mjs_appendIntVec": { + "name": "mjs_appendIntVec", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjIntVecVec *", + "array_dim": null + }, + { + "name": "array", + "c_type": "const int *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1868 + }, + "mjs_setFloat": { + "name": "mjs_setFloat", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjFloatVec *", + "array_dim": null + }, + { + "name": "array", + "c_type": "const float *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1871 + }, + "mjs_appendFloatVec": { + "name": "mjs_appendFloatVec", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjFloatVecVec *", + "array_dim": null + }, + { + "name": "array", + "c_type": "const float *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1874 + }, + "mjs_setDouble": { + "name": "mjs_setDouble", + "return_type": "void", + "params": [ + { + "name": "dest", + "c_type": "mjDoubleVec *", + "array_dim": null + }, + { + "name": "array", + "c_type": "const double *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1877 + }, + "mjs_setPluginAttributes": { + "name": "mjs_setPluginAttributes", + "return_type": "void", + "params": [ + { + "name": "plugin", + "c_type": "mjsPlugin *", + "array_dim": null + }, + { + "name": "attributes", + "c_type": "void *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1880 + }, + "mjs_getName": { + "name": "mjs_getName", + "return_type": "mjString *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1886 + }, + "mjs_getString": { + "name": "mjs_getString", + "return_type": "const char *", + "params": [ + { + "name": "source", + "c_type": "const mjString *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1889 + }, + "mjs_getDouble": { + "name": "mjs_getDouble", + "return_type": "const double *", + "params": [ + { + "name": "source", + "c_type": "const mjDoubleVec *", + "array_dim": null + }, + { + "name": "size", + "c_type": "int *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1893 + }, + "mjs_getWrapNum": { + "name": "mjs_getWrapNum", + "return_type": "int", + "params": [ + { + "name": "tendonspec", + "c_type": "const mjsTendon *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1896 + }, + "mjs_getWrap": { + "name": "mjs_getWrap", + "return_type": "mjsWrap *", + "params": [ + { + "name": "tendonspec", + "c_type": "const mjsTendon *", + "array_dim": null + }, + { + "name": "i", + "c_type": "int", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1899 + }, + "mjs_getPluginAttributes": { + "name": "mjs_getPluginAttributes", + "return_type": "const void *", + "params": [ + { + "name": "plugin", + "c_type": "const mjsPlugin *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1902 + }, + "mjs_setDefault": { + "name": "mjs_setDefault", + "return_type": "void", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "def", + "c_type": "const mjsDefault *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1908 + }, + "mjs_setFrame": { + "name": "mjs_setFrame", + "return_type": "int", + "params": [ + { + "name": "dest", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "frame", + "c_type": "mjsFrame *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1911 + }, + "mjs_resolveOrientation": { + "name": "mjs_resolveOrientation", + "return_type": "const char *", + "params": [ + { + "name": "quat", + "c_type": "double [4]", + "array_dim": 4 + }, + { + "name": "degree", + "c_type": "mjtByte", + "array_dim": null + }, + { + "name": "sequence", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "orientation", + "c_type": "const mjsOrientation *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1914 + }, + "mjs_bodyToFrame": { + "name": "mjs_bodyToFrame", + "return_type": "mjsFrame *", + "params": [ + { + "name": "body", + "c_type": "mjsBody **", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1918 + }, + "mjs_setUserValue": { + "name": "mjs_setUserValue", + "return_type": "void", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "key", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "data", + "c_type": "const void *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1921 + }, + "mjs_setUserValueWithCleanup": { + "name": "mjs_setUserValueWithCleanup", + "return_type": "void", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "key", + "c_type": "const char *", + "array_dim": null + }, + { + "name": "data", + "c_type": "const void *", + "array_dim": null + }, + { + "name": "cleanup", + "c_type": "void (*)(const void *)", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1926 + }, + "mjs_getUserValue": { + "name": "mjs_getUserValue", + "return_type": "const void *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "key", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1931 + }, + "mjs_deleteUserValue": { + "name": "mjs_deleteUserValue", + "return_type": "void", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + }, + { + "name": "key", + "c_type": "const char *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1934 + }, + "mjs_sensorDim": { + "name": "mjs_sensorDim", + "return_type": "int", + "params": [ + { + "name": "sensor", + "c_type": "const mjsSensor *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1937 + }, + "mjs_defaultSpec": { + "name": "mjs_defaultSpec", + "return_type": "void", + "params": [ + { + "name": "spec", + "c_type": "mjSpec *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1942 + }, + "mjs_defaultOrientation": { + "name": "mjs_defaultOrientation", + "return_type": "void", + "params": [ + { + "name": "orient", + "c_type": "mjsOrientation *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1945 + }, + "mjs_defaultBody": { + "name": "mjs_defaultBody", + "return_type": "void", + "params": [ + { + "name": "body", + "c_type": "mjsBody *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1948 + }, + "mjs_defaultFrame": { + "name": "mjs_defaultFrame", + "return_type": "void", + "params": [ + { + "name": "frame", + "c_type": "mjsFrame *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1951 + }, + "mjs_defaultJoint": { + "name": "mjs_defaultJoint", + "return_type": "void", + "params": [ + { + "name": "joint", + "c_type": "mjsJoint *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1954 + }, + "mjs_defaultGeom": { + "name": "mjs_defaultGeom", + "return_type": "void", + "params": [ + { + "name": "geom", + "c_type": "mjsGeom *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1957 + }, + "mjs_defaultSite": { + "name": "mjs_defaultSite", + "return_type": "void", + "params": [ + { + "name": "site", + "c_type": "mjsSite *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1960 + }, + "mjs_defaultCamera": { + "name": "mjs_defaultCamera", + "return_type": "void", + "params": [ + { + "name": "camera", + "c_type": "mjsCamera *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1963 + }, + "mjs_defaultLight": { + "name": "mjs_defaultLight", + "return_type": "void", + "params": [ + { + "name": "light", + "c_type": "mjsLight *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1966 + }, + "mjs_defaultFlex": { + "name": "mjs_defaultFlex", + "return_type": "void", + "params": [ + { + "name": "flex", + "c_type": "mjsFlex *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1969 + }, + "mjs_defaultMesh": { + "name": "mjs_defaultMesh", + "return_type": "void", + "params": [ + { + "name": "mesh", + "c_type": "mjsMesh *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1972 + }, + "mjs_defaultHField": { + "name": "mjs_defaultHField", + "return_type": "void", + "params": [ + { + "name": "hfield", + "c_type": "mjsHField *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1975 + }, + "mjs_defaultSkin": { + "name": "mjs_defaultSkin", + "return_type": "void", + "params": [ + { + "name": "skin", + "c_type": "mjsSkin *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1978 + }, + "mjs_defaultTexture": { + "name": "mjs_defaultTexture", + "return_type": "void", + "params": [ + { + "name": "texture", + "c_type": "mjsTexture *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1981 + }, + "mjs_defaultMaterial": { + "name": "mjs_defaultMaterial", + "return_type": "void", + "params": [ + { + "name": "material", + "c_type": "mjsMaterial *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1984 + }, + "mjs_defaultPair": { + "name": "mjs_defaultPair", + "return_type": "void", + "params": [ + { + "name": "pair", + "c_type": "mjsPair *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1987 + }, + "mjs_defaultEquality": { + "name": "mjs_defaultEquality", + "return_type": "void", + "params": [ + { + "name": "equality", + "c_type": "mjsEquality *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1990 + }, + "mjs_defaultTendon": { + "name": "mjs_defaultTendon", + "return_type": "void", + "params": [ + { + "name": "tendon", + "c_type": "mjsTendon *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1993 + }, + "mjs_defaultActuator": { + "name": "mjs_defaultActuator", + "return_type": "void", + "params": [ + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1996 + }, + "mjs_defaultSensor": { + "name": "mjs_defaultSensor", + "return_type": "void", + "params": [ + { + "name": "sensor", + "c_type": "mjsSensor *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1999 + }, + "mjs_defaultNumeric": { + "name": "mjs_defaultNumeric", + "return_type": "void", + "params": [ + { + "name": "numeric", + "c_type": "mjsNumeric *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2002 + }, + "mjs_defaultText": { + "name": "mjs_defaultText", + "return_type": "void", + "params": [ + { + "name": "text", + "c_type": "mjsText *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2005 + }, + "mjs_defaultTuple": { + "name": "mjs_defaultTuple", + "return_type": "void", + "params": [ + { + "name": "tuple", + "c_type": "mjsTuple *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2008 + }, + "mjs_defaultKey": { + "name": "mjs_defaultKey", + "return_type": "void", + "params": [ + { + "name": "key", + "c_type": "mjsKey *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2011 + }, + "mjs_defaultPlugin": { + "name": "mjs_defaultPlugin", + "return_type": "void", + "params": [ + { + "name": "plugin", + "c_type": "mjsPlugin *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2014 + }, + "mjs_asBody": { + "name": "mjs_asBody", + "return_type": "mjsBody *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2020 + }, + "mjs_asGeom": { + "name": "mjs_asGeom", + "return_type": "mjsGeom *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2023 + }, + "mjs_asJoint": { + "name": "mjs_asJoint", + "return_type": "mjsJoint *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2026 + }, + "mjs_asSite": { + "name": "mjs_asSite", + "return_type": "mjsSite *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2029 + }, + "mjs_asCamera": { + "name": "mjs_asCamera", + "return_type": "mjsCamera *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2032 + }, + "mjs_asLight": { + "name": "mjs_asLight", + "return_type": "mjsLight *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2035 + }, + "mjs_asFrame": { + "name": "mjs_asFrame", + "return_type": "mjsFrame *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2038 + }, + "mjs_asActuator": { + "name": "mjs_asActuator", + "return_type": "mjsActuator *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2041 + }, + "mjs_asSensor": { + "name": "mjs_asSensor", + "return_type": "mjsSensor *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2044 + }, + "mjs_asFlex": { + "name": "mjs_asFlex", + "return_type": "mjsFlex *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2047 + }, + "mjs_asPair": { + "name": "mjs_asPair", + "return_type": "mjsPair *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2050 + }, + "mjs_asEquality": { + "name": "mjs_asEquality", + "return_type": "mjsEquality *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2053 + }, + "mjs_asExclude": { + "name": "mjs_asExclude", + "return_type": "mjsExclude *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2056 + }, + "mjs_asTendon": { + "name": "mjs_asTendon", + "return_type": "mjsTendon *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2059 + }, + "mjs_asNumeric": { + "name": "mjs_asNumeric", + "return_type": "mjsNumeric *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2062 + }, + "mjs_asText": { + "name": "mjs_asText", + "return_type": "mjsText *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2065 + }, + "mjs_asTuple": { + "name": "mjs_asTuple", + "return_type": "mjsTuple *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2068 + }, + "mjs_asKey": { + "name": "mjs_asKey", + "return_type": "mjsKey *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2071 + }, + "mjs_asMesh": { + "name": "mjs_asMesh", + "return_type": "mjsMesh *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2074 + }, + "mjs_asHField": { + "name": "mjs_asHField", + "return_type": "mjsHField *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2077 + }, + "mjs_asSkin": { + "name": "mjs_asSkin", + "return_type": "mjsSkin *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2080 + }, + "mjs_asTexture": { + "name": "mjs_asTexture", + "return_type": "mjsTexture *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2083 + }, + "mjs_asMaterial": { + "name": "mjs_asMaterial", + "return_type": "mjsMaterial *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2086 + }, + "mjs_asPlugin": { + "name": "mjs_asPlugin", + "return_type": "mjsPlugin *", + "params": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 2089 + } + }, + "enums": { + "mjtDisableBit": { + "name": "mjtDisableBit", + "members": { + "mjDSBL_CONSTRAINT": 1, + "mjDSBL_EQUALITY": 2, + "mjDSBL_FRICTIONLOSS": 4, + "mjDSBL_LIMIT": 8, + "mjDSBL_CONTACT": 16, + "mjDSBL_SPRING": 32, + "mjDSBL_DAMPER": 64, + "mjDSBL_GRAVITY": 128, + "mjDSBL_CLAMPCTRL": 256, + "mjDSBL_WARMSTART": 512, + "mjDSBL_FILTERPARENT": 1024, + "mjDSBL_ACTUATION": 2048, + "mjDSBL_REFSAFE": 4096, + "mjDSBL_SENSOR": 8192, + "mjDSBL_MIDPHASE": 16384, + "mjDSBL_EULERDAMP": 32768, + "mjDSBL_AUTORESET": 65536, + "mjDSBL_NATIVECCD": 131072, + "mjDSBL_ISLAND": 262144, + "mjDSBL_MULTICCD": 524288, + "mjNDISABLE": 20 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 53 + }, + "mjtEnableBit": { + "name": "mjtEnableBit", + "members": { + "mjENBL_OVERRIDE": 1, + "mjENBL_ENERGY": 2, + "mjENBL_FWDINV": 4, + "mjENBL_INVDISCRETE": 8, + "mjENBL_SLEEP": 16, + "mjNENABLE": 5 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 79 + }, + "mjtJoint": { + "name": "mjtJoint", + "members": { + "mjJNT_FREE": 0, + "mjJNT_BALL": 1, + "mjJNT_SLIDE": 2, + "mjJNT_HINGE": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 91 + }, + "mjtGeom": { + "name": "mjtGeom", + "members": { + "mjGEOM_PLANE": 0, + "mjGEOM_HFIELD": 1, + "mjGEOM_SPHERE": 2, + "mjGEOM_CAPSULE": 3, + "mjGEOM_ELLIPSOID": 4, + "mjGEOM_CYLINDER": 5, + "mjGEOM_BOX": 6, + "mjGEOM_MESH": 7, + "mjGEOM_SDF": 8, + "mjNGEOMTYPES": 9, + "mjGEOM_ARROW": 100, + "mjGEOM_ARROW1": 101, + "mjGEOM_ARROW2": 102, + "mjGEOM_LINE": 103, + "mjGEOM_LINEBOX": 104, + "mjGEOM_FLEX": 105, + "mjGEOM_SKIN": 106, + "mjGEOM_LABEL": 107, + "mjGEOM_TRIANGLE": 108, + "mjGEOM_NONE": 1001 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 99 + }, + "mjtProjection": { + "name": "mjtProjection", + "members": { + "mjPROJ_PERSPECTIVE": 0, + "mjPROJ_ORTHOGRAPHIC": 1 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 128 + }, + "mjtCamLight": { + "name": "mjtCamLight", + "members": { + "mjCAMLIGHT_FIXED": 0, + "mjCAMLIGHT_TRACK": 1, + "mjCAMLIGHT_TRACKCOM": 2, + "mjCAMLIGHT_TARGETBODY": 3, + "mjCAMLIGHT_TARGETBODYCOM": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 134 + }, + "mjtLightType": { + "name": "mjtLightType", + "members": { + "mjLIGHT_SPOT": 0, + "mjLIGHT_DIRECTIONAL": 1, + "mjLIGHT_POINT": 2, + "mjLIGHT_IMAGE": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 143 + }, + "mjtTexture": { + "name": "mjtTexture", + "members": { + "mjTEXTURE_2D": 0, + "mjTEXTURE_CUBE": 1, + "mjTEXTURE_SKYBOX": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 151 + }, + "mjtTextureRole": { + "name": "mjtTextureRole", + "members": { + "mjTEXROLE_USER": 0, + "mjTEXROLE_RGB": 1, + "mjTEXROLE_OCCLUSION": 2, + "mjTEXROLE_ROUGHNESS": 3, + "mjTEXROLE_METALLIC": 4, + "mjTEXROLE_NORMAL": 5, + "mjTEXROLE_OPACITY": 6, + "mjTEXROLE_EMISSIVE": 7, + "mjTEXROLE_RGBA": 8, + "mjTEXROLE_ORM": 9, + "mjNTEXROLE": 10 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 158 + }, + "mjtColorSpace": { + "name": "mjtColorSpace", + "members": { + "mjCOLORSPACE_AUTO": 0, + "mjCOLORSPACE_LINEAR": 1, + "mjCOLORSPACE_SRGB": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 173 + }, + "mjtIntegrator": { + "name": "mjtIntegrator", + "members": { + "mjINT_EULER": 0, + "mjINT_RK4": 1, + "mjINT_IMPLICIT": 2, + "mjINT_IMPLICITFAST": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 180 + }, + "mjtCone": { + "name": "mjtCone", + "members": { + "mjCONE_PYRAMIDAL": 0, + "mjCONE_ELLIPTIC": 1 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 188 + }, + "mjtJacobian": { + "name": "mjtJacobian", + "members": { + "mjJAC_DENSE": 0, + "mjJAC_SPARSE": 1, + "mjJAC_AUTO": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 194 + }, + "mjtSolver": { + "name": "mjtSolver", + "members": { + "mjSOL_PGS": 0, + "mjSOL_CG": 1, + "mjSOL_NEWTON": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 201 + }, + "mjtEq": { + "name": "mjtEq", + "members": { + "mjEQ_CONNECT": 0, + "mjEQ_WELD": 1, + "mjEQ_JOINT": 2, + "mjEQ_TENDON": 3, + "mjEQ_FLEX": 4, + "mjEQ_FLEXVERT": 5, + "mjEQ_FLEXSTRAIN": 6, + "mjEQ_DISTANCE": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 208 + }, + "mjtWrap": { + "name": "mjtWrap", + "members": { + "mjWRAP_NONE": 0, + "mjWRAP_JOINT": 1, + "mjWRAP_PULLEY": 2, + "mjWRAP_SITE": 3, + "mjWRAP_SPHERE": 4, + "mjWRAP_CYLINDER": 5 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 220 + }, + "mjtTrn": { + "name": "mjtTrn", + "members": { + "mjTRN_JOINT": 0, + "mjTRN_JOINTINPARENT": 1, + "mjTRN_SLIDERCRANK": 2, + "mjTRN_TENDON": 3, + "mjTRN_SITE": 4, + "mjTRN_BODY": 5, + "mjTRN_UNDEFINED": 1000 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 230 + }, + "mjtDyn": { + "name": "mjtDyn", + "members": { + "mjDYN_NONE": 0, + "mjDYN_INTEGRATOR": 1, + "mjDYN_FILTER": 2, + "mjDYN_FILTEREXACT": 3, + "mjDYN_MUSCLE": 4, + "mjDYN_DCMOTOR": 5, + "mjDYN_USER": 6 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 242 + }, + "mjtGain": { + "name": "mjtGain", + "members": { + "mjGAIN_FIXED": 0, + "mjGAIN_AFFINE": 1, + "mjGAIN_MUSCLE": 2, + "mjGAIN_DCMOTOR": 3, + "mjGAIN_USER": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 253 + }, + "mjtBias": { + "name": "mjtBias", + "members": { + "mjBIAS_NONE": 0, + "mjBIAS_AFFINE": 1, + "mjBIAS_MUSCLE": 2, + "mjBIAS_DCMOTOR": 3, + "mjBIAS_USER": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 262 + }, + "mjtObj": { + "name": "mjtObj", + "members": { + "mjOBJ_UNKNOWN": 0, + "mjOBJ_BODY": 1, + "mjOBJ_XBODY": 2, + "mjOBJ_JOINT": 3, + "mjOBJ_DOF": 4, + "mjOBJ_GEOM": 5, + "mjOBJ_SITE": 6, + "mjOBJ_CAMERA": 7, + "mjOBJ_LIGHT": 8, + "mjOBJ_FLEX": 9, + "mjOBJ_MESH": 10, + "mjOBJ_SKIN": 11, + "mjOBJ_HFIELD": 12, + "mjOBJ_TEXTURE": 13, + "mjOBJ_MATERIAL": 14, + "mjOBJ_PAIR": 15, + "mjOBJ_EXCLUDE": 16, + "mjOBJ_EQUALITY": 17, + "mjOBJ_TENDON": 18, + "mjOBJ_ACTUATOR": 19, + "mjOBJ_SENSOR": 20, + "mjOBJ_NUMERIC": 21, + "mjOBJ_TEXT": 22, + "mjOBJ_TUPLE": 23, + "mjOBJ_KEY": 24, + "mjOBJ_PLUGIN": 25, + "mjNOBJECT": 26, + "mjOBJ_FRAME": 100, + "mjOBJ_DEFAULT": 101, + "mjOBJ_MODEL": 102 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 271 + }, + "mjtSensor": { + "name": "mjtSensor", + "members": { + "mjSENS_TOUCH": 0, + "mjSENS_ACCELEROMETER": 1, + "mjSENS_VELOCIMETER": 2, + "mjSENS_GYRO": 3, + "mjSENS_FORCE": 4, + "mjSENS_TORQUE": 5, + "mjSENS_MAGNETOMETER": 6, + "mjSENS_RANGEFINDER": 7, + "mjSENS_CAMPROJECTION": 8, + "mjSENS_JOINTPOS": 9, + "mjSENS_JOINTVEL": 10, + "mjSENS_TENDONPOS": 11, + "mjSENS_TENDONVEL": 12, + "mjSENS_ACTUATORPOS": 13, + "mjSENS_ACTUATORVEL": 14, + "mjSENS_ACTUATORFRC": 15, + "mjSENS_JOINTACTFRC": 16, + "mjSENS_TENDONACTFRC": 17, + "mjSENS_BALLQUAT": 18, + "mjSENS_BALLANGVEL": 19, + "mjSENS_JOINTLIMITPOS": 20, + "mjSENS_JOINTLIMITVEL": 21, + "mjSENS_JOINTLIMITFRC": 22, + "mjSENS_TENDONLIMITPOS": 23, + "mjSENS_TENDONLIMITVEL": 24, + "mjSENS_TENDONLIMITFRC": 25, + "mjSENS_FRAMEPOS": 26, + "mjSENS_FRAMEQUAT": 27, + "mjSENS_FRAMEXAXIS": 28, + "mjSENS_FRAMEYAXIS": 29, + "mjSENS_FRAMEZAXIS": 30, + "mjSENS_FRAMELINVEL": 31, + "mjSENS_FRAMEANGVEL": 32, + "mjSENS_FRAMELINACC": 33, + "mjSENS_FRAMEANGACC": 34, + "mjSENS_SUBTREECOM": 35, + "mjSENS_SUBTREELINVEL": 36, + "mjSENS_SUBTREEANGMOM": 37, + "mjSENS_INSIDESITE": 38, + "mjSENS_GEOMDIST": 39, + "mjSENS_GEOMNORMAL": 40, + "mjSENS_GEOMFROMTO": 41, + "mjSENS_CONTACT": 42, + "mjSENS_E_POTENTIAL": 43, + "mjSENS_E_KINETIC": 44, + "mjSENS_CLOCK": 45, + "mjSENS_TACTILE": 46, + "mjSENS_PLUGIN": 47, + "mjSENS_USER": 48 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 308 + }, + "mjtStage": { + "name": "mjtStage", + "members": { + "mjSTAGE_NONE": 0, + "mjSTAGE_POS": 1, + "mjSTAGE_VEL": 2, + "mjSTAGE_ACC": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 384 + }, + "mjtDataType": { + "name": "mjtDataType", + "members": { + "mjDATATYPE_REAL": 0, + "mjDATATYPE_POSITIVE": 1, + "mjDATATYPE_AXIS": 2, + "mjDATATYPE_QUATERNION": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 392 + }, + "mjtConDataField": { + "name": "mjtConDataField", + "members": { + "mjCONDATA_FOUND": 0, + "mjCONDATA_FORCE": 1, + "mjCONDATA_TORQUE": 2, + "mjCONDATA_DIST": 3, + "mjCONDATA_POS": 4, + "mjCONDATA_NORMAL": 5, + "mjCONDATA_TANGENT": 6, + "mjNCONDATA": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 400 + }, + "mjtRayDataField": { + "name": "mjtRayDataField", + "members": { + "mjRAYDATA_DIST": 0, + "mjRAYDATA_DIR": 1, + "mjRAYDATA_ORIGIN": 2, + "mjRAYDATA_POINT": 3, + "mjRAYDATA_NORMAL": 4, + "mjRAYDATA_DEPTH": 5, + "mjNRAYDATA": 6 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 413 + }, + "mjtCamOutBit": { + "name": "mjtCamOutBit", + "members": { + "mjCAMOUT_RGB": 1, + "mjCAMOUT_DEPTH": 2, + "mjCAMOUT_DIST": 4, + "mjCAMOUT_NORMAL": 8, + "mjCAMOUT_SEG": 16, + "mjNCAMOUT": 5 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 425 + }, + "mjtSameFrame": { + "name": "mjtSameFrame", + "members": { + "mjSAMEFRAME_NONE": 0, + "mjSAMEFRAME_BODY": 1, + "mjSAMEFRAME_INERTIA": 2, + "mjSAMEFRAME_BODYROT": 3, + "mjSAMEFRAME_INERTIAROT": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 436 + }, + "mjtSleepPolicy": { + "name": "mjtSleepPolicy", + "members": { + "mjSLEEP_AUTO": 0, + "mjSLEEP_AUTO_NEVER": 1, + "mjSLEEP_AUTO_ALLOWED": 2, + "mjSLEEP_NEVER": 3, + "mjSLEEP_ALLOWED": 4, + "mjSLEEP_INIT": 5 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 445 + }, + "mjtLRMode": { + "name": "mjtLRMode", + "members": { + "mjLRMODE_NONE": 0, + "mjLRMODE_MUSCLE": 1, + "mjLRMODE_MUSCLEUSER": 2, + "mjLRMODE_ALL": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 455 + }, + "mjtFlexSelf": { + "name": "mjtFlexSelf", + "members": { + "mjFLEXSELF_NONE": 0, + "mjFLEXSELF_NARROW": 1, + "mjFLEXSELF_BVH": 2, + "mjFLEXSELF_SAP": 3, + "mjFLEXSELF_AUTO": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 463 + }, + "mjtSDFType": { + "name": "mjtSDFType", + "members": { + "mjSDFTYPE_SINGLE": 0, + "mjSDFTYPE_INTERSECTION": 1, + "mjSDFTYPE_MIDSURFACE": 2, + "mjSDFTYPE_COLLISION": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 472 + }, + "mjtGeomInertia": { + "name": "mjtGeomInertia", + "members": { + "mjINERTIA_VOLUME": 0, + "mjINERTIA_SHELL": 1 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 60 + }, + "mjtMeshInertia": { + "name": "mjtMeshInertia", + "members": { + "mjMESH_INERTIA_CONVEX": 0, + "mjMESH_INERTIA_EXACT": 1, + "mjMESH_INERTIA_LEGACY": 2, + "mjMESH_INERTIA_SHELL": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 66 + }, + "mjtMeshBuiltin": { + "name": "mjtMeshBuiltin", + "members": { + "mjMESH_BUILTIN_NONE": 0, + "mjMESH_BUILTIN_SPHERE": 1, + "mjMESH_BUILTIN_HEMISPHERE": 2, + "mjMESH_BUILTIN_CONE": 3, + "mjMESH_BUILTIN_SUPERSPHERE": 4, + "mjMESH_BUILTIN_SUPERTORUS": 5, + "mjMESH_BUILTIN_WEDGE": 6, + "mjMESH_BUILTIN_PLATE": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 74 + }, + "mjtBuiltin": { + "name": "mjtBuiltin", + "members": { + "mjBUILTIN_NONE": 0, + "mjBUILTIN_GRADIENT": 1, + "mjBUILTIN_CHECKER": 2, + "mjBUILTIN_FLAT": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 86 + }, + "mjtMark": { + "name": "mjtMark", + "members": { + "mjMARK_NONE": 0, + "mjMARK_EDGE": 1, + "mjMARK_CROSS": 2, + "mjMARK_RANDOM": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 94 + }, + "mjtLimited": { + "name": "mjtLimited", + "members": { + "mjLIMITED_FALSE": 0, + "mjLIMITED_TRUE": 1, + "mjLIMITED_AUTO": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 102 + }, + "mjtAlignFree": { + "name": "mjtAlignFree", + "members": { + "mjALIGNFREE_FALSE": 0, + "mjALIGNFREE_TRUE": 1, + "mjALIGNFREE_AUTO": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 109 + }, + "mjtInertiaFromGeom": { + "name": "mjtInertiaFromGeom", + "members": { + "mjINERTIAFROMGEOM_FALSE": 0, + "mjINERTIAFROMGEOM_TRUE": 1, + "mjINERTIAFROMGEOM_AUTO": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 116 + }, + "mjtOrientation": { + "name": "mjtOrientation", + "members": { + "mjORIENTATION_QUAT": 0, + "mjORIENTATION_AXISANGLE": 1, + "mjORIENTATION_XYAXES": 2, + "mjORIENTATION_ZAXIS": 3, + "mjORIENTATION_EULER": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 123 + }, + "mjtTaskStatus": { + "name": "mjtTaskStatus", + "members": { + "mjTASK_NEW": 0, + "mjTASK_QUEUED": 1, + "mjTASK_COMPLETED": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjthread.h", + "line": 20 + }, + "mjtState": { + "name": "mjtState", + "members": { + "mjSTATE_TIME": 1, + "mjSTATE_QPOS": 2, + "mjSTATE_QVEL": 4, + "mjSTATE_ACT": 8, + "mjSTATE_HISTORY": 16, + "mjSTATE_WARMSTART": 32, + "mjSTATE_CTRL": 64, + "mjSTATE_QFRC_APPLIED": 128, + "mjSTATE_XFRC_APPLIED": 256, + "mjSTATE_EQ_ACTIVE": 512, + "mjSTATE_MOCAP_POS": 1024, + "mjSTATE_MOCAP_QUAT": 2048, + "mjSTATE_USERDATA": 4096, + "mjSTATE_PLUGIN": 8192, + "mjNSTATE": 14, + "mjSTATE_PHYSICS": 30, + "mjSTATE_FULLPHYSICS": 8223, + "mjSTATE_USER": 8128, + "mjSTATE_INTEGRATION": 16383 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 27 + }, + "mjtConstraint": { + "name": "mjtConstraint", + "members": { + "mjCNSTR_EQUALITY": 0, + "mjCNSTR_FRICTION_DOF": 1, + "mjCNSTR_FRICTION_TENDON": 2, + "mjCNSTR_LIMIT_JOINT": 3, + "mjCNSTR_LIMIT_TENDON": 4, + "mjCNSTR_CONTACT_FRICTIONLESS": 5, + "mjCNSTR_CONTACT_PYRAMIDAL": 6, + "mjCNSTR_CONTACT_ELLIPTIC": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 55 + }, + "mjtConstraintState": { + "name": "mjtConstraintState", + "members": { + "mjCNSTRSTATE_SATISFIED": 0, + "mjCNSTRSTATE_QUADRATIC": 1, + "mjCNSTRSTATE_LINEARNEG": 2, + "mjCNSTRSTATE_LINEARPOS": 3, + "mjCNSTRSTATE_CONE": 4 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 67 + }, + "mjtWarning": { + "name": "mjtWarning", + "members": { + "mjWARN_INERTIA": 0, + "mjWARN_CONTACTFULL": 1, + "mjWARN_CNSTRFULL": 2, + "mjWARN_BADQPOS": 3, + "mjWARN_BADQVEL": 4, + "mjWARN_BADQACC": 5, + "mjWARN_BADCTRL": 6, + "mjNWARNING": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 76 + }, + "mjtTimer": { + "name": "mjtTimer", + "members": { + "mjTIMER_STEP": 0, + "mjTIMER_FORWARD": 1, + "mjTIMER_INVERSE": 2, + "mjTIMER_POSITION": 3, + "mjTIMER_VELOCITY": 4, + "mjTIMER_ACTUATION": 5, + "mjTIMER_CONSTRAINT": 6, + "mjTIMER_ADVANCE": 7, + "mjTIMER_POS_KINEMATICS": 8, + "mjTIMER_POS_INERTIA": 9, + "mjTIMER_POS_COLLISION": 10, + "mjTIMER_POS_MAKE": 11, + "mjTIMER_POS_PROJECT": 12, + "mjTIMER_COL_BROAD": 13, + "mjTIMER_COL_NARROW": 14, + "mjNTIMER": 15 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 89 + }, + "mjtSleepState": { + "name": "mjtSleepState", + "members": { + "mjS_STATIC": -1, + "mjS_ASLEEP": 0, + "mjS_AWAKE": 1 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 117 + }, + "mjtCatBit": { + "name": "mjtCatBit", + "members": { + "mjCAT_STATIC": 1, + "mjCAT_DYNAMIC": 2, + "mjCAT_DECOR": 4, + "mjCAT_ALL": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 33 + }, + "mjtMouse": { + "name": "mjtMouse", + "members": { + "mjMOUSE_NONE": 0, + "mjMOUSE_ROTATE_V": 1, + "mjMOUSE_ROTATE_H": 2, + "mjMOUSE_MOVE_V": 3, + "mjMOUSE_MOVE_H": 4, + "mjMOUSE_ZOOM": 5, + "mjMOUSE_MOVE_V_REL": 6, + "mjMOUSE_MOVE_H_REL": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 41 + }, + "mjtPertBit": { + "name": "mjtPertBit", + "members": { + "mjPERT_TRANSLATE": 1, + "mjPERT_ROTATE": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 53 + }, + "mjtCamera": { + "name": "mjtCamera", + "members": { + "mjCAMERA_FREE": 0, + "mjCAMERA_TRACKING": 1, + "mjCAMERA_FIXED": 2, + "mjCAMERA_USER": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 59 + }, + "mjtLabel": { + "name": "mjtLabel", + "members": { + "mjLABEL_NONE": 0, + "mjLABEL_BODY": 1, + "mjLABEL_JOINT": 2, + "mjLABEL_GEOM": 3, + "mjLABEL_SITE": 4, + "mjLABEL_CAMERA": 5, + "mjLABEL_LIGHT": 6, + "mjLABEL_TENDON": 7, + "mjLABEL_ACTUATOR": 8, + "mjLABEL_CONSTRAINT": 9, + "mjLABEL_FLEX": 10, + "mjLABEL_SKIN": 11, + "mjLABEL_SELECTION": 12, + "mjLABEL_SELPNT": 13, + "mjLABEL_CONTACTPOINT": 14, + "mjLABEL_CONTACTFORCE": 15, + "mjLABEL_ISLAND": 16, + "mjNLABEL": 17 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 67 + }, + "mjtFrame": { + "name": "mjtFrame", + "members": { + "mjFRAME_NONE": 0, + "mjFRAME_BODY": 1, + "mjFRAME_GEOM": 2, + "mjFRAME_SITE": 3, + "mjFRAME_CAMERA": 4, + "mjFRAME_LIGHT": 5, + "mjFRAME_CONTACT": 6, + "mjFRAME_WORLD": 7, + "mjNFRAME": 8 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 90 + }, + "mjtVisFlag": { + "name": "mjtVisFlag", + "members": { + "mjVIS_CONVEXHULL": 0, + "mjVIS_TEXTURE": 1, + "mjVIS_JOINT": 2, + "mjVIS_CAMERA": 3, + "mjVIS_ACTUATOR": 4, + "mjVIS_ACTIVATION": 5, + "mjVIS_LIGHT": 6, + "mjVIS_TENDON": 7, + "mjVIS_RANGEFINDER": 8, + "mjVIS_CONSTRAINT": 9, + "mjVIS_INERTIA": 10, + "mjVIS_SCLINERTIA": 11, + "mjVIS_PERTFORCE": 12, + "mjVIS_PERTOBJ": 13, + "mjVIS_CONTACTPOINT": 14, + "mjVIS_ISLAND": 15, + "mjVIS_CONTACTFORCE": 16, + "mjVIS_CONTACTSPLIT": 17, + "mjVIS_TRANSPARENT": 18, + "mjVIS_AUTOCONNECT": 19, + "mjVIS_COM": 20, + "mjVIS_SELECT": 21, + "mjVIS_STATIC": 22, + "mjVIS_SKIN": 23, + "mjVIS_FLEXVERT": 24, + "mjVIS_FLEXEDGE": 25, + "mjVIS_FLEXFACE": 26, + "mjVIS_FLEXSKIN": 27, + "mjVIS_BODYBVH": 28, + "mjVIS_MESHBVH": 29, + "mjVIS_SDFITER": 30, + "mjNVISFLAG": 31 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 104 + }, + "mjtRndFlag": { + "name": "mjtRndFlag", + "members": { + "mjRND_SHADOW": 0, + "mjRND_WIREFRAME": 1, + "mjRND_REFLECTION": 2, + "mjRND_ADDITIVE": 3, + "mjRND_SKYBOX": 4, + "mjRND_FOG": 5, + "mjRND_HAZE": 6, + "mjRND_DEPTH": 7, + "mjRND_SEGMENT": 8, + "mjRND_IDCOLOR": 9, + "mjRND_CULL_FACE": 10, + "mjNRNDFLAG": 11 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 141 + }, + "mjtStereo": { + "name": "mjtStereo", + "members": { + "mjSTEREO_NONE": 0, + "mjSTEREO_QUADBUFFERED": 1, + "mjSTEREO_SIDEBYSIDE": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 158 + }, + "mjtPluginCapabilityBit": { + "name": "mjtPluginCapabilityBit", + "members": { + "mjPLUGIN_ACTUATOR": 1, + "mjPLUGIN_SENSOR": 2, + "mjPLUGIN_PASSIVE": 4, + "mjPLUGIN_SDF": 8 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 107 + }, + "mjtGridPos": { + "name": "mjtGridPos", + "members": { + "mjGRID_TOPLEFT": 0, + "mjGRID_TOPRIGHT": 1, + "mjGRID_BOTTOMLEFT": 2, + "mjGRID_BOTTOMRIGHT": 3, + "mjGRID_TOP": 4, + "mjGRID_BOTTOM": 5, + "mjGRID_LEFT": 6, + "mjGRID_RIGHT": 7 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 30 + }, + "mjtFramebuffer": { + "name": "mjtFramebuffer", + "members": { + "mjFB_WINDOW": 0, + "mjFB_OFFSCREEN": 1 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 42 + }, + "mjtDepthMap": { + "name": "mjtDepthMap", + "members": { + "mjDEPTH_ZERONEAR": 0, + "mjDEPTH_ZEROFAR": 1 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 47 + }, + "mjtFontScale": { + "name": "mjtFontScale", + "members": { + "mjFONTSCALE_50": 50, + "mjFONTSCALE_100": 100, + "mjFONTSCALE_150": 150, + "mjFONTSCALE_200": 200, + "mjFONTSCALE_250": 250, + "mjFONTSCALE_300": 300 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 52 + }, + "mjtFont": { + "name": "mjtFont", + "members": { + "mjFONT_NORMAL": 0, + "mjFONT_SHADOW": 1, + "mjFONT_BIG": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 62 + }, + "mjtButton": { + "name": "mjtButton", + "members": { + "mjBUTTON_NONE": 0, + "mjBUTTON_LEFT": 1, + "mjBUTTON_RIGHT": 2, + "mjBUTTON_MIDDLE": 3 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 65 + }, + "mjtEvent": { + "name": "mjtEvent", + "members": { + "mjEVENT_NONE": 0, + "mjEVENT_MOVE": 1, + "mjEVENT_PRESS": 2, + "mjEVENT_RELEASE": 3, + "mjEVENT_SCROLL": 4, + "mjEVENT_KEY": 5, + "mjEVENT_RESIZE": 6, + "mjEVENT_REDRAW": 7, + "mjEVENT_FILESDROP": 8 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 73 + }, + "mjtItem": { + "name": "mjtItem", + "members": { + "mjITEM_END": -2, + "mjITEM_SECTION": -1, + "mjITEM_SEPARATOR": 0, + "mjITEM_STATIC": 1, + "mjITEM_BUTTON": 2, + "mjITEM_CHECKINT": 3, + "mjITEM_CHECKBYTE": 4, + "mjITEM_RADIO": 5, + "mjITEM_RADIOLINE": 6, + "mjITEM_SELECT": 7, + "mjITEM_SLIDERINT": 8, + "mjITEM_SLIDERNUM": 9, + "mjITEM_EDITINT": 10, + "mjITEM_EDITNUM": 11, + "mjITEM_EDITFLOAT": 12, + "mjITEM_EDITTXT": 13, + "mjNITEM": 14 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 86 + }, + "mjtSection": { + "name": "mjtSection", + "members": { + "mjSECT_CLOSED": 0, + "mjSECT_OPEN": 1, + "mjSECT_FIXED": 2 + }, + "member_docs": {}, + "underlying_type": "int", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 110 + } + }, + "structs": { + "mjLROpt": { + "name": "mjLROpt", + "fields": [ + { + "name": "mode", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "useexisting", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "uselimit", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "accel", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxforce", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "timeconst", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "timestep", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "inttotal", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "interval", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "tolrange", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 482 + }, + "mjCache": { + "name": "mjCache", + "fields": [ + { + "name": "impl_", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 501 + }, + "mjVFS": { + "name": "mjVFS", + "fields": [ + { + "name": "impl_", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 508 + }, + "mjOption": { + "name": "mjOption", + "fields": [ + { + "name": "timestep", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "impratio", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "tolerance", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ls_tolerance", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "noslip_tolerance", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ccd_tolerance", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sleep_tolerance", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gravity", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "wind", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "magnetic", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "density", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "viscosity", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "o_margin", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "o_solref", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "o_solimp", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "o_friction", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "integrator", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "cone", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "jacobian", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solver", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "iterations", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ls_iterations", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "noslip_iterations", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ccd_iterations", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "disableflags", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "enableflags", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "disableactuator", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sdf_initpoints", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sdf_iterations", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 515 + }, + "mjVisual": { + "name": "mjVisual", + "fields": [ + { + "name": "global", + "c_type": "struct (anonymous struct at C:\\Users\\jonat\\Documents\\Unreal Projects\\url_proj\\Plugins\\UnrealRoboticsLab\\third_party\\install\\MuJoCo\\include\\mujoco/mjmodel.h:565:3)", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "quality", + "c_type": "struct (anonymous struct at C:\\Users\\jonat\\Documents\\Unreal Projects\\url_proj\\Plugins\\UnrealRoboticsLab\\third_party\\install\\MuJoCo\\include\\mujoco/mjmodel.h:581:3)", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "headlight", + "c_type": "struct (anonymous struct at C:\\Users\\jonat\\Documents\\Unreal Projects\\url_proj\\Plugins\\UnrealRoboticsLab\\third_party\\install\\MuJoCo\\include\\mujoco/mjmodel.h:589:3)", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "map", + "c_type": "struct (anonymous struct at C:\\Users\\jonat\\Documents\\Unreal Projects\\url_proj\\Plugins\\UnrealRoboticsLab\\third_party\\install\\MuJoCo\\include\\mujoco/mjmodel.h:596:3)", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "scale", + "c_type": "struct (anonymous struct at C:\\Users\\jonat\\Documents\\Unreal Projects\\url_proj\\Plugins\\UnrealRoboticsLab\\third_party\\install\\MuJoCo\\include\\mujoco/mjmodel.h:612:3)", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgba", + "c_type": "struct (anonymous struct at C:\\Users\\jonat\\Documents\\Unreal Projects\\url_proj\\Plugins\\UnrealRoboticsLab\\third_party\\install\\MuJoCo\\include\\mujoco/mjmodel.h:632:3)", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 564 + }, + "mjStatistic": { + "name": "mjStatistic", + "fields": [ + { + "name": "meaninertia", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "meanmass", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "meansize", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "extent", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "center", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 665 + }, + "mjModel": { + "name": "mjModel", + "fields": [ + { + "name": "nq", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nv", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nu", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "na", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbody", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbvh", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbvhstatic", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbvhdynamic", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "noct", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "njnt", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntree", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nM", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nB", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nC", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nD", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ngeom", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nsite", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ncam", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nlight", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflex", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexnode", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexvert", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexedge", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexelem", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexelemdata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexstiffness", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexbending", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexelemedge", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexshelldata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflexevpair", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nflextexcoord", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nJfe", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nJfv", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmesh", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshvert", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshnormal", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshtexcoord", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshface", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshgraph", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshpoly", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshpolyvert", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmeshpolymap", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskin", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskinvert", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskintexvert", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskinface", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskinbone", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskinbonevert", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nhfield", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nhfielddata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntex", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntexdata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmat", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "npair", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nexclude", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "neq", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntendon", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nJten", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nwrap", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nsensor", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nnumeric", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nnumericdata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntext", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntextdata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntuple", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntupledata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nkey", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nmocap", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nplugin", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "npluginattr", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_body", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_jnt", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_geom", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_site", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_cam", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_tendon", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_actuator", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_sensor", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nnames", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "npaths", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nnames_map", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nJmom", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ngravcomp", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nemax", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "njmax", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nconmax", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuserdata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nsensordata", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "npluginstate", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nhistory", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "narena", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbuffer", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "opt", + "c_type": "mjOption", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "vis", + "c_type": "mjVisual", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "stat", + "c_type": "mjStatistic", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "buffer", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qpos0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qpos_spring", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_parentid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_rootid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_weldid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_mocapid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_jntnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_jntadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_dofnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_dofadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_treeid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_geomnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_geomadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_simple", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_sameframe", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_quat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_ipos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_iquat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_mass", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_subtreemass", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_inertia", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_invweight0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_gravcomp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_plugin", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_contype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_conaffinity", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_bvhadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_bvhnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bvh_depth", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bvh_child", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bvh_nodeid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bvh_aabb", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "oct_depth", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "oct_child", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "oct_aabb", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "oct_coeff", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_qposadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_dofadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_bodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_actuatorid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_limited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_actfrclimited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_actgravcomp", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_solref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_solimp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_axis", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_stiffness", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_stiffnesspoly", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_range", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_actfrcrange", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "jnt_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_bodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_jntid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_parentid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_treeid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_Madr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_simplenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_solref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_solimp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_frictionloss", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_armature", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_damping", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_dampingpoly", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_invweight0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_M0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_length", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_bodyadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_bodynum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_dofadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_dofnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_sleep_policy", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_contype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_conaffinity", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_condim", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_bodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_dataid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_matid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_priority", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_plugin", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_sameframe", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_solmix", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_solref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_solimp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_size", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_aabb", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_rbound", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_quat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_friction", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_gap", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_fluid", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_rgba", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_bodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_matid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_sameframe", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_size", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_quat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_rgba", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_mode", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_bodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_targetbodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_quat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_poscom0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_pos0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_mat0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_projection", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_fovy", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_ipd", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_resolution", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_output", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_sensorsize", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_intrinsic", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_mode", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_bodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_targetbodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_texid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_castshadow", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_bulbradius", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_intensity", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_range", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_active", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_dir", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_poscom0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_pos0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_dir0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_attenuation", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_cutoff", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_exponent", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_ambient", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_diffuse", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_specular", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_contype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_conaffinity", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_condim", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_priority", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_solmix", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_solref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_solimp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_friction", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_gap", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_internal", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_selfcollide", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_activelayers", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_passive", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_dim", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_matid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_interp", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_bandwidth", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_cellnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_nodeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_nodenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edgeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edgenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemdataadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_stiffnessadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemedgeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_bendingadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_shellnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_shelldataadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_evpairadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_evpairnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_texcoordadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_nodebodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertbodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertedgeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertedgenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertedge", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edge", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edgeflap", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elem", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemtexcoord", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemedge", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_elemlayer", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_shell", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_evpair", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vert", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vert0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_vertmetric", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_node", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_node0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_length0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_invweight0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_radius", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_size", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_stiffness", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_bending", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_damping", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edgestiffness", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edgedamping", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_edgeequality", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_rigid", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_rigid", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_centered", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_flatskin", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_bvhadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_bvhnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_J_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_J_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_J_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert_J_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert_J_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert_J_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_rgba", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex_texcoord", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_vertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_vertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_faceadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_facenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_bvhadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_bvhnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_octadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_octnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_normaladr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_normalnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_texcoordadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_texcoordnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_graphadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_vert", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_normal", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_texcoord", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_face", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_facenormal", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_facetexcoord", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_graph", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_scale", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_quat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_pathadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polynum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polyadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polynormal", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polyvertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polyvertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polyvert", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polymapadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polymapnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh_polymap", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_matid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_rgba", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_inflate", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_vertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_vertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_texcoordadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_faceadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_facenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_boneadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_vert", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_texcoord", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_face", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonevertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonevertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonebindpos", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonebindquat", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonebodyid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonevertid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_bonevertweight", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skin_pathadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hfield_size", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hfield_nrow", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hfield_ncol", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hfield_adr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hfield_data", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hfield_pathadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_colorspace", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_height", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_width", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_nchannel", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_adr", + "c_type": "mjtSize *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_data", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tex_pathadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_texid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_texuniform", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_texrepeat", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_emission", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_specular", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_shininess", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_reflectance", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_metallic", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_roughness", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mat_rgba", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_dim", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_geom1", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_geom2", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_signature", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_solref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_solreffriction", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_solimp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_gap", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair_friction", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "exclude_signature", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_obj1id", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_obj2id", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_objtype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_active0", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_solref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_solimp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_data", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_adr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_num", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_matid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_actuatorid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_treenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_treeid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_J_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_J_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_J_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_limited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_actfrclimited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_width", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_solref_lim", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_solimp_lim", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_solref_fri", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_solimp_fri", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_range", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_actfrcrange", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_stiffness", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_stiffnesspoly", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_damping", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_dampingpoly", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_armature", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_frictionloss", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_lengthspring", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_length0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_invweight0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_rgba", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "wrap_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "wrap_objid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "wrap_prm", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_trntype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_dyntype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_gaintype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_biastype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_trnid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_damping", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_dampingpoly", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_armature", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_actadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_actnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_group", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_history", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_historyadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_delay", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_ctrllimited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_forcelimited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_actlimited", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_dynprm", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_gainprm", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_biasprm", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_actearly", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_ctrlrange", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_forcerange", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_actrange", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_gear", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_cranklength", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_acc0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_length0", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_lengthrange", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_plugin", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_datatype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_needstage", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_objtype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_objid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_reftype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_refid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_intprm", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_dim", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_adr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_cutoff", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_noise", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_history", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_historyadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_delay", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_interval", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_user", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensor_plugin", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_stateadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_statenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_attr", + "c_type": "char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_attradr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "numeric_adr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "numeric_size", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "numeric_data", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "text_adr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "text_size", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "text_data", + "c_type": "char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tuple_adr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tuple_size", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tuple_objtype", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tuple_objid", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tuple_objprm", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_time", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_qpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_qvel", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_act", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_mpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_mquat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "key_ctrl", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_bodyadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_jntadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_geomadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_siteadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_camadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_lightadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_flexadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_meshadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_skinadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_hfieldadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_texadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_matadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_pairadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_excludeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_eqadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_tendonadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_actuatoradr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_sensoradr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_numericadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_textadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_tupleadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_keyadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name_pluginadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "names", + "c_type": "char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "names_map", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "paths", + "c_type": "char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "B_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "B_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "B_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "M_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "M_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "M_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mapM2M", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "D_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "D_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "D_diag", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "D_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mapM2D", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mapD2M", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "signature", + "c_type": "uint64_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 677 + }, + "mjsElement": { + "name": "mjsElement", + "fields": [ + { + "name": "elemtype", + "c_type": "mjtObj", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "signature", + "c_type": "uint64_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 134 + }, + "mjsCompiler": { + "name": "mjsCompiler", + "fields": [ + { + "name": "autolimits", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "boundmass", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "boundinertia", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "settotalmass", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "balanceinertia", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fitaabb", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "degree", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "eulerseq", + "c_type": "char [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "discardvisual", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "usethread", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fusestatic", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "inertiafromgeom", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "inertiagrouprange", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "saveinertial", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "alignfree", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "LRopt", + "c_type": "mjLROpt", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "meshdir", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "texturedir", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 140 + }, + "mjSpec": { + "name": "mjSpec", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "modelname", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "compiler", + "c_type": "mjsCompiler", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "strippath", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "option", + "c_type": "mjOption", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "visual", + "c_type": "mjVisual", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "stat", + "c_type": "mjStatistic", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "memory", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nemax", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuserdata", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_body", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_jnt", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_geom", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_site", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_cam", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_tendon", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_actuator", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nuser_sensor", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nkey", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "njmax", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nconmax", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nstack", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "comment", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "modelfiledir", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hasImplicitPluginElem", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 162 + }, + "mjsOrientation": { + "name": "mjsOrientation", + "fields": [ + { + "name": "type", + "c_type": "mjtOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "axisangle", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "xyaxes", + "c_type": "double [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "zaxis", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "euler", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 201 + }, + "mjsPlugin": { + "name": "mjsPlugin", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_name", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "active", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 210 + }, + "mjsBody": { + "name": "mjsBody", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "childclass", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "quat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "alt", + "c_type": "mjsOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mass", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ipos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "iquat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "inertia", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "ialt", + "c_type": "mjsOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fullinertia", + "c_type": "double [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "mocap", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gravcomp", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sleep", + "c_type": "mjtSleepPolicy", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "explicitinertial", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "plugin", + "c_type": "mjsPlugin", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 219 + }, + "mjsFrame": { + "name": "mjsFrame", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "childclass", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "quat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "alt", + "c_type": "mjsOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 247 + }, + "mjsJoint": { + "name": "mjsJoint", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtJoint", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "axis", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "ref", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "align", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "stiffness", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "springref", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "springdamper", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "limited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "range", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "margin", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref_limit", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp_limit", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "actfrclimited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "actfrcrange", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "armature", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "damping", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "frictionloss", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref_friction", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp_friction", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "actgravcomp", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 257 + }, + "mjsGeom": { + "name": "mjsGeom", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtGeom", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "quat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "alt", + "c_type": "mjsOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fromto", + "c_type": "double [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "size", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "contype", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "conaffinity", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "condim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "priority", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "friction", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "solmix", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "margin", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gap", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mass", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "density", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "typeinertia", + "c_type": "mjtGeomInertia", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fluid_ellipsoid", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fluid_coefs", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "material", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "hfieldname", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "meshname", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "fitscale", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin", + "c_type": "mjsPlugin", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 296 + }, + "mjsSite": { + "name": "mjsSite", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "quat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "alt", + "c_type": "mjsOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fromto", + "c_type": "double [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "size", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtGeom", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "material", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 343 + }, + "mjsCamera": { + "name": "mjsCamera", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "quat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "alt", + "c_type": "mjsOrientation", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mode", + "c_type": "mjtCamLight", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "targetbody", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "proj", + "c_type": "mjtProjection", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "resolution", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "output", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fovy", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ipd", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "intrinsic", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "sensor_size", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "focal_length", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "focal_pixel", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "principal_length", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "principal_pixel", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 365 + }, + "mjsLight": { + "name": "mjsLight", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "dir", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "mode", + "c_type": "mjtCamLight", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "targetbody", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "active", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtLightType", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "texture", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "castshadow", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "bulbradius", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "intensity", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "range", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "attenuation", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "cutoff", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "exponent", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ambient", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "diffuse", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "specular", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 394 + }, + "mjsFlex": { + "name": "mjsFlex", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "contype", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "conaffinity", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "condim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "priority", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "friction", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "solmix", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "margin", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gap", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "radius", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "size", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "internal", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flatskin", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "selfcollide", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "passive", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "activelayers", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "edgestiffness", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "edgedamping", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "material", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "young", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "poisson", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "damping", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "thickness", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "elastic2d", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "cellcount", + "c_type": "int [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "order", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nodebody", + "c_type": "mjStringVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "vertbody", + "c_type": "mjStringVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "node", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "vert", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "elem", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "texcoord", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "elemtexcoord", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 423 + }, + "mjsMesh": { + "name": "mjsMesh", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "content_type", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "file", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "refpos", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "refquat", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "scale", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "inertia", + "c_type": "mjtMeshInertia", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "smoothnormal", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "needsdf", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxhullvert", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "uservert", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "usernormal", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "usertexcoord", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "userface", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "userfacenormal", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "userfacetexcoord", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin", + "c_type": "mjsPlugin", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "material", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "octree_maxdepth", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 474 + }, + "mjsHField": { + "name": "mjsHField", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "content_type", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "file", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "size", + "c_type": "double [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "nrow", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ncol", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 498 + }, + "mjsSkin": { + "name": "mjsSkin", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "file", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "material", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "inflate", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "vert", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "texcoord", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "face", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bodyname", + "c_type": "mjStringVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bindpos", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bindquat", + "c_type": "mjFloatVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "vertid", + "c_type": "mjIntVecVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "vertweight", + "c_type": "mjFloatVecVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 511 + }, + "mjsTexture": { + "name": "mjsTexture", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtTexture", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "colorspace", + "c_type": "mjtColorSpace", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "builtin", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mark", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgb1", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgb2", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "markrgb", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "random", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "height", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "width", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nchannel", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "content_type", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "file", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "gridsize", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "gridlayout", + "c_type": "char [12]", + "array_dim": 12, + "is_pointer": false, + "doc": "" + }, + { + "name": "cubefiles", + "c_type": "mjStringVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "data", + "c_type": "mjByteVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "hflip", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "vflip", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 536 + }, + "mjsMaterial": { + "name": "mjsMaterial", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "textures", + "c_type": "mjStringVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "texuniform", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "texrepeat", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "emission", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "specular", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shininess", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "reflectance", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "metallic", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "roughness", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 573 + }, + "mjsPair": { + "name": "mjsPair", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geomname1", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geomname2", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "condim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solreffriction", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "margin", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gap", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "friction", + "c_type": "double [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 589 + }, + "mjsExclude": { + "name": "mjsExclude", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bodyname1", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bodyname2", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 606 + }, + "mjsEquality": { + "name": "mjsEquality", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtEq", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "data", + "c_type": "double [11]", + "array_dim": 11, + "is_pointer": false, + "doc": "" + }, + { + "name": "active", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "name1", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "name2", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "objtype", + "c_type": "mjtObj", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 614 + }, + "mjsTendon": { + "name": "mjsTendon", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "stiffness", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "springlength", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "damping", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "frictionloss", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref_friction", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp_friction", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "armature", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "limited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "actfrclimited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "range", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "actfrcrange", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "margin", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref_limit", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp_limit", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "material", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "width", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 628 + }, + "mjsWrap": { + "name": "mjsWrap", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtWrap", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 661 + }, + "mjsActuator": { + "name": "mjsActuator", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "gaintype", + "c_type": "mjtGain", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gainprm", + "c_type": "double [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "biastype", + "c_type": "mjtBias", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "biasprm", + "c_type": "double [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "dyntype", + "c_type": "mjtDyn", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dynprm", + "c_type": "double [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "actdim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "actearly", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "trntype", + "c_type": "mjtTrn", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gear", + "c_type": "double [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "target", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "refsite", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "slidersite", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cranklength", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "lengthrange", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "inheritrange", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "damping", + "c_type": "double [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "armature", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ctrllimited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ctrlrange", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "forcelimited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "forcerange", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "actlimited", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "actrange", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "group", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nsample", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "interp", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "delay", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin", + "c_type": "mjsPlugin", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 668 + }, + "mjsSensor": { + "name": "mjsSensor", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtSensor", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "objtype", + "c_type": "mjtObj", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "objname", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "reftype", + "c_type": "mjtObj", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "refname", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "intprm", + "c_type": "int [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "datatype", + "c_type": "mjtDataType", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "needstage", + "c_type": "mjtStage", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "cutoff", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "noise", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nsample", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "interp", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "delay", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "interval", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin", + "c_type": "mjsPlugin", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 714 + }, + "mjsNumeric": { + "name": "mjsNumeric", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "data", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "size", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 747 + }, + "mjsText": { + "name": "mjsText", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "data", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 755 + }, + "mjsTuple": { + "name": "mjsTuple", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "objtype", + "c_type": "mjIntVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "objname", + "c_type": "mjStringVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "objprm", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 762 + }, + "mjsKey": { + "name": "mjsKey", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "time", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "qpos", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qvel", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "act", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mpos", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mquat", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ctrl", + "c_type": "mjDoubleVec *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "info", + "c_type": "mjString *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 771 + }, + "mjsDefault": { + "name": "mjsDefault", + "fields": [ + { + "name": "element", + "c_type": "mjsElement *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "joint", + "c_type": "mjsJoint *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom", + "c_type": "mjsGeom *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site", + "c_type": "mjsSite *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "camera", + "c_type": "mjsCamera *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light", + "c_type": "mjsLight *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flex", + "c_type": "mjsFlex *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mesh", + "c_type": "mjsMesh *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "material", + "c_type": "mjsMaterial *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "pair", + "c_type": "mjsPair *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "equality", + "c_type": "mjsEquality *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon", + "c_type": "mjsTendon *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator", + "c_type": "mjsActuator *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjspec.h", + "line": 784 + }, + "mjThreadPool": { + "name": "mjThreadPool", + "fields": [ + { + "name": "nworker", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjthread.h", + "line": 30 + }, + "mjTask": { + "name": "mjTask", + "fields": [ + { + "name": "func", + "c_type": "mjfTask", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "args", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "status", + "c_type": "volatile int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjthread.h", + "line": 35 + }, + "mjContact": { + "name": "mjContact", + "fields": [ + { + "name": "dist", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pos", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "frame", + "c_type": "mjtNum [9]", + "array_dim": 9, + "is_pointer": false, + "doc": "" + }, + { + "name": "includemargin", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "friction", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "solref", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solreffriction", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "solimp", + "c_type": "mjtNum [5]", + "array_dim": 5, + "is_pointer": false, + "doc": "" + }, + { + "name": "mu", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "H", + "c_type": "mjtNum [36]", + "array_dim": 36, + "is_pointer": false, + "doc": "" + }, + { + "name": "dim", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "geom1", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "geom2", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "geom", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "flex", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "elem", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "vert", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "exclude", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "efc_address", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 126 + }, + "mjWarningStat": { + "name": "mjWarningStat", + "fields": [ + { + "name": "lastinfo", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "number", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 163 + }, + "mjTimerStat": { + "name": "mjTimerStat", + "fields": [ + { + "name": "duration", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "number", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 170 + }, + "mjSolverStat": { + "name": "mjSolverStat", + "fields": [ + { + "name": "improvement", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gradient", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "lineslope", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nactive", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nchange", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "neval", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nupdate", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 177 + }, + "mjData": { + "name": "mjData", + "fields": [ + { + "name": "narena", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbuffer", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nplugin", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pstack", + "c_type": "size_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pbase", + "c_type": "size_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "parena", + "c_type": "size_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxuse_stack", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxuse_threadstack", + "c_type": "mjtSize [128]", + "array_dim": 128, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxuse_arena", + "c_type": "mjtSize", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxuse_con", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxuse_efc", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "solver", + "c_type": "mjSolverStat [4000]", + "array_dim": 4000, + "is_pointer": false, + "doc": "" + }, + { + "name": "solver_niter", + "c_type": "int [20]", + "array_dim": 20, + "is_pointer": false, + "doc": "" + }, + { + "name": "solver_nnz", + "c_type": "int [20]", + "array_dim": 20, + "is_pointer": false, + "doc": "" + }, + { + "name": "solver_fwdinv", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "warning", + "c_type": "mjWarningStat [7]", + "array_dim": 7, + "is_pointer": false, + "doc": "" + }, + { + "name": "timer", + "c_type": "mjTimerStat [15]", + "array_dim": 15, + "is_pointer": false, + "doc": "" + }, + { + "name": "ncon", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ne", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nf", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nl", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nefc", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nJ", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nA", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nisland", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nidof", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntree_awake", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nbody_awake", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nparent_awake", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nv_awake", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_energypos", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_energyvel", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_subtreevel", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_rnepost", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "time", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "energy", + "c_type": "mjtNum [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "buffer", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "arena", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qvel", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "act", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "history", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qacc_warmstart", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_state", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ctrl", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_applied", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xfrc_applied", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "eq_active", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mocap_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "mocap_quat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qacc", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "act_dot", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "userdata", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sensordata", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_asleep", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "plugin_data", + "c_type": "uintptr_t *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xquat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xmat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xipos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ximat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xanchor", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "xaxis", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geom_xmat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "site_xmat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cam_xmat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "light_xdir", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "subtree_com", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cdof", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cinert", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert_xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexelem_aabb", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_J", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_length", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert_J", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert_length", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bvh_aabb_dyn", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_wrapadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_wrapnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_J", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_length", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "wrap_obj", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "wrap_xpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_length", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "moment_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "moment_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "moment_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_moment", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "crb", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qM", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "M", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qLD", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qLDiagInv", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "bvh_active", + "c_type": "mjtByte *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_awake", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_awake", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "body_awake_ind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "parent_awake_ind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_awake_ind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge_velocity", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ten_velocity", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_velocity", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cvel", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cdof_dot", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_bias", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_spring", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_damper", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_gravcomp", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_fluid", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_passive", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "subtree_linvel", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "subtree_angmom", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qH", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qHDiagInv", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qDeriv", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qLU", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_force", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_actuator", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_smooth", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qacc_smooth", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_constraint", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "qfrc_inverse", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cacc", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cfrc_int", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "cfrc_ext", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "contact", + "c_type": "mjContact *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_id", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_J_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_J_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_J_rowsuper", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_J_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_J", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_pos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_margin", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_frictionloss", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_diagApprox", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_KBIP", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_D", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_R", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tendon_efcadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "tree_island", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_ntree", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_itreeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "map_itree2tree", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "dof_island", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_nv", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_idofadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_dofadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "map_dof2idof", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "map_idof2dof", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ifrc_smooth", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iacc_smooth", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iM_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iM_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iM_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iM", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iLD", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iLDiagInv", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iacc", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_island", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_ne", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_nf", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_nefc", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "island_iefcadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "map_efc2iefc", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "map_iefc2efc", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_type", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_id", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_J_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_J_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_J_rowsuper", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_J_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_J", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_frictionloss", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_D", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_R", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_AR_rownnz", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_AR_rowadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_AR_colind", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_AR", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_vel", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_aref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_b", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_aref", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_state", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "iefc_force", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_state", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "efc_force", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "ifrc_constraint", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "threadpool", + "c_type": "uintptr_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "signature", + "c_type": "uint64_t", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjdata.h", + "line": 191 + }, + "mjvPerturb": { + "name": "mjvPerturb", + "fields": [ + { + "name": "select", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flexselect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "skinselect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "active", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "active2", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "refpos", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "refquat", + "c_type": "mjtNum [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "refselpos", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "localpos", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "localmass", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "scale", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 167 + }, + "mjvCamera": { + "name": "mjvCamera", + "fields": [ + { + "name": "type", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fixedcamid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "trackbodyid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "lookat", + "c_type": "mjtNum [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "distance", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "azimuth", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "elevation", + "c_type": "mjtNum", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "orthographic", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 185 + }, + "mjvGLCamera": { + "name": "mjvGLCamera", + "fields": [ + { + "name": "pos", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "forward", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "up", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "frustum_center", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "frustum_width", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "frustum_bottom", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "frustum_top", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "frustum_near", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "frustum_far", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "orthographic", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 205 + }, + "mjvGeom": { + "name": "mjvGeom", + "fields": [ + { + "name": "type", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dataid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "objtype", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "objid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "category", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "matid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "texcoord", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "segid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "size", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "pos", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "mat", + "c_type": "float [9]", + "array_dim": 9, + "is_pointer": false, + "doc": "" + }, + { + "name": "rgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "emission", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "specular", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shininess", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "reflectance", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "label", + "c_type": "char [100]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "camdist", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "modelrbound", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "transparent", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 227 + }, + "mjvLight": { + "name": "mjvLight", + "fields": [ + { + "name": "id", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pos", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "dir", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "type", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "texid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "attenuation", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "cutoff", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "exponent", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ambient", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "diffuse", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "specular", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "headlight", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "castshadow", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "bulbradius", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "intensity", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "range", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 262 + }, + "mjvOption": { + "name": "mjvOption", + "fields": [ + { + "name": "label", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "frame", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "geomgroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "sitegroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "jointgroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "tendongroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "actuatorgroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "flexgroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "skingroup", + "c_type": "mjtByte [6]", + "array_dim": 6, + "is_pointer": false, + "doc": "" + }, + { + "name": "flags", + "c_type": "mjtByte [31]", + "array_dim": 31, + "is_pointer": false, + "doc": "" + }, + { + "name": "bvh_depth", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flex_layer", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 285 + }, + "mjvScene": { + "name": "mjvScene", + "fields": [ + { + "name": "maxgeom", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "ngeom", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "geoms", + "c_type": "mjvGeom *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geomorder", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "nflex", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flexedgeadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedgenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexfaceadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexfacenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexfaceused", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexedge", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvert", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexface", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexnormal", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flextexcoord", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "flexvertopt", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flexedgeopt", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flexfaceopt", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flexskinopt", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskin", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "skinfacenum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skinvertadr", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skinvertnum", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skinvert", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skinnormal", + "c_type": "float *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "nlight", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "lights", + "c_type": "mjvLight [100]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "camera", + "c_type": "mjvGLCamera [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "enabletransform", + "c_type": "mjtByte", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "translate", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "rotate", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "scale", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "stereo", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flags", + "c_type": "mjtByte [11]", + "array_dim": 11, + "is_pointer": false, + "doc": "" + }, + { + "name": "framewidth", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "framergb", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "status", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 304 + }, + "mjvFigure": { + "name": "mjvFigure", + "fields": [ + { + "name": "flg_legend", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_ticklabel", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_extend", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_barplot", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_selection", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "flg_symmetric", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "linewidth", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gridwidth", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "gridsize", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "gridrgb", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "figurergba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "panergba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "legendrgba", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "textrgb", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "linergb", + "c_type": "float [100][3]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "range", + "c_type": "float [2][2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "xformat", + "c_type": "char [20]", + "array_dim": 20, + "is_pointer": false, + "doc": "" + }, + { + "name": "yformat", + "c_type": "char [20]", + "array_dim": 20, + "is_pointer": false, + "doc": "" + }, + { + "name": "minwidth", + "c_type": "char [20]", + "array_dim": 20, + "is_pointer": false, + "doc": "" + }, + { + "name": "title", + "c_type": "char [1000]", + "array_dim": 1000, + "is_pointer": false, + "doc": "" + }, + { + "name": "xlabel", + "c_type": "char [100]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "linename", + "c_type": "char [100][100]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "legendoffset", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "subplot", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "highlight", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "highlightid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "selection", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "linepnt", + "c_type": "int [100]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "linedata", + "c_type": "float [100][2002]", + "array_dim": 100, + "is_pointer": false, + "doc": "" + }, + { + "name": "xaxispixel", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "yaxispixel", + "c_type": "int [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "xaxisdata", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "yaxisdata", + "c_type": "float [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 367 + }, + "mjResource": { + "name": "mjResource", + "fields": [ + { + "name": "name", + "c_type": "char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "data", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "vfs", + "c_type": "mjVFS *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "timestamp", + "c_type": "char [512]", + "array_dim": 512, + "is_pointer": false, + "doc": "" + }, + { + "name": "provider", + "c_type": "const struct mjpResourceProvider *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 27 + }, + "mjpResourceProvider": { + "name": "mjpResourceProvider", + "fields": [ + { + "name": "prefix", + "c_type": "const char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "open", + "c_type": "mjfOpenResource", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "read", + "c_type": "mjfReadResource", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "close", + "c_type": "mjfCloseResource", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mount", + "c_type": "mjfMountResource", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "unmount", + "c_type": "mjfUnmountResource", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "modified", + "c_type": "mjfResourceModified", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "data", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 60 + }, + "mjpDecoder": { + "name": "mjpDecoder", + "fields": [ + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "extension", + "c_type": "const char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "can_decode", + "c_type": "mjfCanDecode", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "decode", + "c_type": "mjfDecode", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 81 + }, + "mjpEncoder": { + "name": "mjpEncoder", + "fields": [ + { + "name": "content_type", + "c_type": "const char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "extension", + "c_type": "const char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "encode", + "c_type": "mjfEncode", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "close_resource", + "c_type": "mjfCloseResource", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 97 + }, + "mjpPlugin": { + "name": "mjpPlugin", + "fields": [ + { + "name": "name", + "c_type": "const char *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "nattribute", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "attributes", + "c_type": "const char *const *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "capabilityflags", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "needstage", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nstate", + "c_type": "int (*)(const mjModel *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "nsensordata", + "c_type": "int (*)(const mjModel *, int, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "init", + "c_type": "int (*)(const mjModel *, mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "destroy", + "c_type": "void (*)(mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "copy", + "c_type": "void (*)(mjData *, const mjModel *, const mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "reset", + "c_type": "void (*)(const mjModel *, mjtNum *, void *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "compute", + "c_type": "void (*)(const mjModel *, mjData *, int, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "advance", + "c_type": "void (*)(const mjModel *, mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "visualize", + "c_type": "void (*)(const mjModel *, mjData *, const mjvOption *, mjvScene *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "actuator_act_dot", + "c_type": "void (*)(const mjModel *, mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sdf_distance", + "c_type": "mjtNum (*)(const mjtNum *, const mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sdf_gradient", + "c_type": "void (*)(mjtNum *, const mjtNum *, const mjData *, int)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sdf_staticdistance", + "c_type": "mjtNum (*)(const mjtNum *, const mjtNum *)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sdf_attribute", + "c_type": "void (*)(mjtNum *, const char **, const char **)", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sdf_aabb", + "c_type": "void (*)(mjtNum *, const mjtNum *)", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 114 + }, + "mjSDF": { + "name": "mjSDF", + "fields": [ + { + "name": "plugin", + "c_type": "const mjpPlugin **", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "id", + "c_type": "int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "mjtSDFType", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "relpos", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "relmat", + "c_type": "mjtNum *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "geomtype", + "c_type": "mjtGeom *", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 175 + }, + "mjrRect": { + "name": "mjrRect", + "fields": [ + { + "name": "left", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "bottom", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "width", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "height", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 69 + }, + "mjrContext": { + "name": "mjrContext", + "fields": [ + { + "name": "lineWidth", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shadowClip", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shadowScale", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fogStart", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fogEnd", + "c_type": "float", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fogRGBA", + "c_type": "float [4]", + "array_dim": 4, + "is_pointer": false, + "doc": "" + }, + { + "name": "shadowSize", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offWidth", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offHeight", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offSamples", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "fontScale", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxWidth", + "c_type": "int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxHeight", + "c_type": "int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxSamples", + "c_type": "int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "offFBO", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offFBO_r", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offColor", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offColor_r", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offDepthStencil", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "offDepthStencil_r", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shadowFBO", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shadowTex", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxFBO", + "c_type": "unsigned int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxFBO_r", + "c_type": "unsigned int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxColor", + "c_type": "unsigned int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxColor_r", + "c_type": "unsigned int [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + }, + { + "name": "mat_texid", + "c_type": "int [10000]", + "array_dim": 10000, + "is_pointer": false, + "doc": "" + }, + { + "name": "mat_texuniform", + "c_type": "int [1000]", + "array_dim": 1000, + "is_pointer": false, + "doc": "" + }, + { + "name": "mat_texrepeat", + "c_type": "float [2000]", + "array_dim": 2000, + "is_pointer": false, + "doc": "" + }, + { + "name": "ntexture", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "textureType", + "c_type": "int [1000]", + "array_dim": 1000, + "is_pointer": false, + "doc": "" + }, + { + "name": "texture", + "c_type": "unsigned int [1000]", + "array_dim": 1000, + "is_pointer": false, + "doc": "" + }, + { + "name": "basePlane", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "baseMesh", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "baseHField", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "baseBuiltin", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "baseFontNormal", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "baseFontShadow", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "baseFontBig", + "c_type": "unsigned int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rangePlane", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rangeMesh", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rangeHField", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rangeBuiltin", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rangeFont", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nskin", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "skinvertVBO", + "c_type": "unsigned int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skinnormalVBO", + "c_type": "unsigned int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skintexcoordVBO", + "c_type": "unsigned int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "skinfaceVBO", + "c_type": "unsigned int *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "charWidth", + "c_type": "int [127]", + "array_dim": 127, + "is_pointer": false, + "doc": "" + }, + { + "name": "charWidthBig", + "c_type": "int [127]", + "array_dim": 127, + "is_pointer": false, + "doc": "" + }, + { + "name": "charHeight", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "charHeightBig", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "glInitialized", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "windowAvailable", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "windowSamples", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "windowStereo", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "windowDoublebuffer", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "currentBuffer", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "readPixelFormat", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "readDepthMap", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 80 + }, + "mjuiState": { + "name": "mjuiState", + "fields": [ + { + "name": "nrect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rect", + "c_type": "mjrRect [25]", + "array_dim": 25, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "type", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "left", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "right", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "middle", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "doubleclick", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "button", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "buttontime", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "x", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "y", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dx", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dy", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sx", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sy", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "control", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shift", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "alt", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "key", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "keytime", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mouserect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dragrect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dragbutton", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "dropcount", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "droppaths", + "c_type": "const char **", + "array_dim": null, + "is_pointer": true, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 123 + }, + "mjuiThemeSpacing": { + "name": "mjuiThemeSpacing", + "fields": [ + { + "name": "total", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "scroll", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "label", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "section", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "cornersect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "cornersep", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "itemside", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "itemmid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "itemver", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "texthor", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "textver", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "linescroll", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "samples", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 169 + }, + "mjuiThemeColor": { + "name": "mjuiThemeColor", + "fields": [ + { + "name": "master", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "thumb", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "secttitle", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "secttitle2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "secttitleuncheck", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "secttitleuncheck2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "secttitlecheck", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "secttitlecheck2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "sectfont", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "sectsymbol", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "sectpane", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "separator", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "separator2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "shortcut", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "fontactive", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "fontinactive", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "decorinactive", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "decorinactive2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "button", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "check", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "radio", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "select", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "select2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "slider", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "slider2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "edit", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "edit2", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + }, + { + "name": "cursor", + "c_type": "float [3]", + "array_dim": 3, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 189 + }, + "mjuiItemSingle": { + "name": "mjuiItemSingle", + "fields": [ + { + "name": "modifier", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shortcut", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 224 + }, + "mjuiItemMulti": { + "name": "mjuiItemMulti", + "fields": [ + { + "name": "nelem", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "name", + "c_type": "char [35][40]", + "array_dim": 35, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 230 + }, + "mjuiItemSlider": { + "name": "mjuiItemSlider", + "fields": [ + { + "name": "range", + "c_type": "double [2]", + "array_dim": 2, + "is_pointer": false, + "doc": "" + }, + { + "name": "divisions", + "c_type": "double", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 236 + }, + "mjuiItemEdit": { + "name": "mjuiItemEdit", + "fields": [ + { + "name": "nelem", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "range", + "c_type": "double [7][2]", + "array_dim": 7, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 242 + }, + "mjuiItem": { + "name": "mjuiItem", + "fields": [ + { + "name": "type", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "name", + "c_type": "char [40]", + "array_dim": 40, + "is_pointer": false, + "doc": "" + }, + { + "name": "state", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pdata", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "sectionid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "itemid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rect", + "c_type": "mjrRect", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "skip", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 248 + }, + "mjuiSection": { + "name": "mjuiSection", + "fields": [ + { + "name": "name", + "c_type": "char [40]", + "array_dim": 40, + "is_pointer": false, + "doc": "" + }, + { + "name": "state", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "modifier", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "shortcut", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "checkbox", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "nitem", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "item", + "c_type": "mjuiItem [200]", + "array_dim": 200, + "is_pointer": false, + "doc": "" + }, + { + "name": "rtitle", + "c_type": "mjrRect", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "rcontent", + "c_type": "mjrRect", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "lastclick", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 275 + }, + "mjUI": { + "name": "mjUI", + "fields": [ + { + "name": "spacing", + "c_type": "mjuiThemeSpacing", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "color", + "c_type": "mjuiThemeColor", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "predicate", + "c_type": "mjfItemEnable", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "userdata", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "rectid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "auxid", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "radiocol", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "width", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "height", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "maxheight", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "scroll", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mousesect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mouseitem", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mousehelp", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mouseclicks", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "mousesectcheck", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "editsect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "edititem", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "editcursor", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "editscroll", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "edittext", + "c_type": "char [300]", + "array_dim": 300, + "is_pointer": false, + "doc": "" + }, + { + "name": "editchanged", + "c_type": "mjuiItem *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "nsect", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "sect", + "c_type": "mjuiSection [10]", + "array_dim": 10, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 295 + }, + "mjuiDef": { + "name": "mjuiDef", + "fields": [ + { + "name": "type", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "name", + "c_type": "char [40]", + "array_dim": 40, + "is_pointer": false, + "doc": "" + }, + { + "name": "state", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + }, + { + "name": "pdata", + "c_type": "void *", + "array_dim": null, + "is_pointer": true, + "doc": "" + }, + { + "name": "other", + "c_type": "char [300]", + "array_dim": 300, + "is_pointer": false, + "doc": "" + }, + { + "name": "otherint", + "c_type": "int", + "array_dim": null, + "is_pointer": false, + "doc": "" + } + ], + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 335 + } + }, + "defines": { + "mjMINVAL": { + "value": "1E-15", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjtnum.h", + "line": 26 + }, + "mjPI": { + "value": "3.14159265358979323846", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 25 + }, + "mjMAXVAL": { + "value": "1E+10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 26 + }, + "mjMINMU": { + "value": "1E-5", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 27 + }, + "mjMINIMP": { + "value": "0.0001", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 28 + }, + "mjMAXIMP": { + "value": "0.9999", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 29 + }, + "mjMAXCONPAIR": { + "value": "50", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 30 + }, + "mjMAXTREEDEPTH": { + "value": "50", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 31 + }, + "mjMAXFLEXNODES": { + "value": "27", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 32 + }, + "mjMINAWAKE": { + "value": "10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 33 + }, + "mjNEQDATA": { + "value": "11", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 38 + }, + "mjNDYN": { + "value": "10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 39 + }, + "mjNGAIN": { + "value": "10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 40 + }, + "mjNBIAS": { + "value": "10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 41 + }, + "mjNFLUID": { + "value": "12", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 42 + }, + "mjNREF": { + "value": "2", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 43 + }, + "mjNIMP": { + "value": "5", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 44 + }, + "mjNPOLY": { + "value": "2", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 45 + }, + "mjNSENS": { + "value": "3", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 46 + }, + "mjNSOLVER": { + "value": "200", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 47 + }, + "mjNISLAND": { + "value": "20", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmodel.h", + "line": 48 + }, + "MJOPTION_FIELDS": { + "value": "X ( mjtNum , timestep , 1 ) X ( mjtNum , impratio , 1 ) X ( mjtNum , tolerance , 1 ) X ( mjtNum , ls_tolerance , 1 ) X ( mjtNum , noslip_tolerance , 1 ) X ( mjtNum , ccd_tolerance , 1 ) X ( mjtNum , sleep_tolerance , 1 ) XVEC ( mjtNum , gravity , 3 ) XVEC ( mjtNum , wind , 3 ) XVEC ( mjtNum , magnetic , 3 ) X ( mjtNum , density , 1 ) X ( mjtNum , viscosity , 1 ) X ( mjtNum , o_margin , 1 ) XVEC ( mjtNum , o_solref , mjNREF ) XVEC ( mjtNum , o_solimp , mjNIMP ) XVEC ( mjtNum , o_friction , 5 ) X ( int , integrator , 1 ) X ( int , cone , 1 ) X ( int , jacobian , 1 ) X ( int , solver , 1 ) X ( int , iterations , 1 ) X ( int , ls_iterations , 1 ) X ( int , noslip_iterations , 1 ) X ( int , ccd_iterations , 1 ) X ( int , disableflags , 1 ) X ( int , enableflags , 1 ) X ( int , disableactuator , 1 ) X ( int , sdf_initpoints , 1 ) X ( int , sdf_iterations , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 23 + }, + "MJSTATISTIC_FIELDS": { + "value": "X ( meaninertia , 1 ) X ( meanmass , 1 ) X ( meansize , 1 ) X ( extent , 1 ) XVEC ( center , 3 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 58 + }, + "MJVISUAL_GLOBAL_FIELDS": { + "value": "X ( int , cameraid ) X ( int , orthographic ) X ( float , fovy ) X ( float , ipd ) X ( float , azimuth ) X ( float , elevation ) X ( float , linewidth ) X ( float , glow ) X ( float , realtime ) X ( int , offwidth ) X ( int , offheight ) X ( int , ellipsoidinertia ) X ( int , bvactive )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 69 + }, + "MJVISUAL_QUALITY_FIELDS": { + "value": "X ( shadowsize ) X ( offsamples ) X ( numslices ) X ( numstacks ) X ( numquads )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 84 + }, + "MJVISUAL_HEADLIGHT_FIELDS": { + "value": "XVEC ( float , ambient , 3 ) XVEC ( float , diffuse , 3 ) XVEC ( float , specular , 3 ) X ( int , active , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 91 + }, + "MJVISUAL_MAP_FIELDS": { + "value": "X ( stiffness ) X ( stiffnessrot ) X ( force ) X ( torque ) X ( alpha ) X ( fogstart ) X ( fogend ) X ( znear ) X ( zfar ) X ( haze ) X ( shadowclip ) X ( shadowscale ) X ( actuatortendon )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 97 + }, + "MJVISUAL_SCALE_FIELDS": { + "value": "X ( forcewidth ) X ( contactwidth ) X ( contactheight ) X ( connect ) X ( com ) X ( camera ) X ( light ) X ( selectpoint ) X ( jointlength ) X ( jointwidth ) X ( actuatorlength ) X ( actuatorwidth ) X ( framelength ) X ( framewidth ) X ( constraint ) X ( slidercrank ) X ( frustum )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 112 + }, + "MJVISUAL_RGBA_FIELDS": { + "value": "X ( fog ) X ( haze ) X ( force ) X ( inertia ) X ( joint ) X ( actuator ) X ( actuatornegative ) X ( actuatorpositive ) X ( com ) X ( camera ) X ( light ) X ( selectpoint ) X ( connect ) X ( contactpoint ) X ( contactforce ) X ( contactfriction ) X ( contacttorque ) X ( contactgap ) X ( rangefinder ) X ( constraint ) X ( slidercrank ) X ( crankbroken ) X ( frustum ) X ( bv ) X ( bvactive )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 131 + }, + "MJMODEL_SIZES": { + "value": "X ( nq ) X ( nv ) X ( nu ) X ( na ) X ( nbody ) X ( nbvh ) X ( nbvhstatic ) X ( nbvhdynamic ) X ( noct ) X ( njnt ) X ( ntree ) X ( nM ) X ( nB ) X ( nC ) X ( nD ) X ( ngeom ) X ( nsite ) X ( ncam ) X ( nlight ) X ( nflex ) X ( nflexnode ) X ( nflexvert ) X ( nflexedge ) X ( nflexelem ) X ( nflexelemdata ) X ( nflexstiffness ) X ( nflexbending ) X ( nflexelemedge ) X ( nflexshelldata ) X ( nflexevpair ) X ( nflextexcoord ) X ( nJfe ) X ( nJfv ) X ( nmesh ) X ( nmeshvert ) X ( nmeshnormal ) X ( nmeshtexcoord ) X ( nmeshface ) X ( nmeshgraph ) X ( nmeshpoly ) X ( nmeshpolyvert ) X ( nmeshpolymap ) X ( nskin ) X ( nskinvert ) X ( nskintexvert ) X ( nskinface ) X ( nskinbone ) X ( nskinbonevert ) X ( nhfield ) X ( nhfielddata ) X ( ntex ) X ( ntexdata ) X ( nmat ) X ( npair ) X ( nexclude ) X ( neq ) X ( ntendon ) X ( nJten ) X ( nwrap ) X ( nsensor ) X ( nnumeric ) X ( nnumericdata ) X ( ntext ) X ( ntextdata ) X ( ntuple ) X ( ntupledata ) X ( nkey ) X ( nmocap ) X ( nplugin ) X ( npluginattr ) X ( nuser_body ) X ( nuser_jnt ) X ( nuser_geom ) X ( nuser_site ) X ( nuser_cam ) X ( nuser_tendon ) X ( nuser_actuator ) X ( nuser_sensor ) X ( nnames ) X ( npaths ) X ( nnames_map ) X ( nJmom ) X ( ngravcomp ) X ( nemax ) X ( njmax ) X ( nconmax ) X ( nuserdata ) X ( nsensordata ) X ( npluginstate ) X ( nhistory ) X ( narena ) X ( nbuffer )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 162 + }, + "MJMODEL_POINTERS_PREAMBLE": { + "value": "( m ) int nuser_body = m -> nuser_body ; int nuser_jnt = m -> nuser_jnt ; int nuser_geom = m -> nuser_geom ; int nuser_site = m -> nuser_site ; int nuser_cam = m -> nuser_cam ; int nuser_tendon = m -> nuser_tendon ; int nuser_actuator = m -> nuser_actuator ; int nuser_sensor = m -> nuser_sensor ; int nq = m -> nq ; int nv = m -> nv ; int na = m -> na ; int nu = m -> nu ; int nmocap = m -> nmocap ;", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 260 + }, + "MJ_M": { + "value": "( n ) n", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 277 + }, + "MJMODEL_POINTERS_BODY": { + "value": "X ( int , body_parentid , nbody , 1 ) X ( int , body_rootid , nbody , 1 ) X ( int , body_weldid , nbody , 1 ) X ( int , body_mocapid , nbody , 1 ) X ( int , body_jntnum , nbody , 1 ) X ( int , body_jntadr , nbody , 1 ) X ( int , body_dofnum , nbody , 1 ) X ( int , body_dofadr , nbody , 1 ) X ( int , body_treeid , nbody , 1 ) X ( int , body_geomnum , nbody , 1 ) X ( int , body_geomadr , nbody , 1 ) X ( mjtByte , body_simple , nbody , 1 ) X ( mjtByte , body_sameframe , nbody , 1 ) X ( mjtNum , body_pos , nbody , 3 ) X ( mjtNum , body_quat , nbody , 4 ) X ( mjtNum , body_ipos , nbody , 3 ) X ( mjtNum , body_iquat , nbody , 4 ) X ( mjtNum , body_mass , nbody , 1 ) X ( mjtNum , body_subtreemass , nbody , 1 ) X ( mjtNum , body_inertia , nbody , 3 ) X ( mjtNum , body_invweight0 , nbody , 2 ) X ( mjtNum , body_gravcomp , nbody , 1 ) X ( mjtNum , body_margin , nbody , 1 ) X ( mjtNum , body_user , nbody , MJ_M ( nuser_body ) ) X ( int , body_plugin , nbody , 1 ) X ( int , body_contype , nbody , 1 ) X ( int , body_conaffinity , nbody , 1 ) X ( int , body_bvhadr , nbody , 1 ) X ( int , body_bvhnum , nbody , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 283 + }, + "MJMODEL_POINTERS_JOINT": { + "value": "X ( int , jnt_type , njnt , 1 ) X ( int , jnt_qposadr , njnt , 1 ) X ( int , jnt_dofadr , njnt , 1 ) X ( int , jnt_bodyid , njnt , 1 ) X ( int , jnt_actuatorid , njnt , 1 ) X ( int , jnt_group , njnt , 1 ) X ( mjtByte , jnt_limited , njnt , 1 ) X ( mjtByte , jnt_actfrclimited , njnt , 1 ) X ( mjtByte , jnt_actgravcomp , njnt , 1 ) X ( mjtNum , jnt_solref , njnt , mjNREF ) X ( mjtNum , jnt_solimp , njnt , mjNIMP ) X ( mjtNum , jnt_pos , njnt , 3 ) X ( mjtNum , jnt_axis , njnt , 3 ) X ( mjtNum , jnt_stiffness , njnt , 1 ) X ( mjtNum , jnt_stiffnesspoly , njnt , mjNPOLY ) X ( mjtNum , jnt_range , njnt , 2 ) X ( mjtNum , jnt_actfrcrange , njnt , 2 ) X ( mjtNum , jnt_margin , njnt , 1 ) X ( mjtNum , jnt_user , njnt , MJ_M ( nuser_jnt ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 314 + }, + "MJMODEL_POINTERS_DOF": { + "value": "X ( int , dof_bodyid , nv , 1 ) X ( int , dof_jntid , nv , 1 ) X ( int , dof_parentid , nv , 1 ) X ( int , dof_treeid , nv , 1 ) X ( int , dof_Madr , nv , 1 ) X ( int , dof_simplenum , nv , 1 ) X ( mjtNum , dof_solref , nv , mjNREF ) X ( mjtNum , dof_solimp , nv , mjNIMP ) X ( mjtNum , dof_frictionloss , nv , 1 ) X ( mjtNum , dof_armature , nv , 1 ) X ( mjtNum , dof_damping , nv , 1 ) X ( mjtNum , dof_dampingpoly , nv , mjNPOLY ) X ( mjtNum , dof_invweight0 , nv , 1 ) X ( mjtNum , dof_M0 , nv , 1 ) X ( mjtNum , dof_length , nv , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 335 + }, + "MJMODEL_POINTERS_TREE": { + "value": "X ( int , tree_bodyadr , ntree , 1 ) X ( int , tree_bodynum , ntree , 1 ) X ( int , tree_dofadr , ntree , 1 ) X ( int , tree_dofnum , ntree , 1 ) X ( int , tree_sleep_policy , ntree , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 352 + }, + "MJMODEL_POINTERS_GEOM": { + "value": "X ( int , geom_type , ngeom , 1 ) X ( int , geom_contype , ngeom , 1 ) X ( int , geom_conaffinity , ngeom , 1 ) X ( int , geom_condim , ngeom , 1 ) X ( int , geom_bodyid , ngeom , 1 ) X ( int , geom_dataid , ngeom , 1 ) X ( int , geom_matid , ngeom , 1 ) X ( int , geom_group , ngeom , 1 ) X ( int , geom_priority , ngeom , 1 ) X ( int , geom_plugin , ngeom , 1 ) X ( mjtByte , geom_sameframe , ngeom , 1 ) X ( mjtNum , geom_solmix , ngeom , 1 ) X ( mjtNum , geom_solref , ngeom , mjNREF ) X ( mjtNum , geom_solimp , ngeom , mjNIMP ) X ( mjtNum , geom_size , ngeom , 3 ) X ( mjtNum , geom_aabb , ngeom , 6 ) X ( mjtNum , geom_rbound , ngeom , 1 ) X ( mjtNum , geom_pos , ngeom , 3 ) X ( mjtNum , geom_quat , ngeom , 4 ) X ( mjtNum , geom_friction , ngeom , 3 ) X ( mjtNum , geom_margin , ngeom , 1 ) X ( mjtNum , geom_gap , ngeom , 1 ) XNV ( mjtNum , geom_fluid , ngeom , mjNFLUID ) X ( mjtNum , geom_user , ngeom , MJ_M ( nuser_geom ) ) X ( float , geom_rgba , ngeom , 4 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 359 + }, + "MJMODEL_POINTERS_SITE": { + "value": "X ( int , site_type , nsite , 1 ) X ( int , site_bodyid , nsite , 1 ) X ( int , site_matid , nsite , 1 ) X ( int , site_group , nsite , 1 ) X ( mjtByte , site_sameframe , nsite , 1 ) X ( mjtNum , site_size , nsite , 3 ) X ( mjtNum , site_pos , nsite , 3 ) X ( mjtNum , site_quat , nsite , 4 ) X ( mjtNum , site_user , nsite , MJ_M ( nuser_site ) ) X ( float , site_rgba , nsite , 4 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 386 + }, + "MJMODEL_POINTERS_CAMERA": { + "value": "X ( int , cam_mode , ncam , 1 ) X ( int , cam_bodyid , ncam , 1 ) X ( int , cam_targetbodyid , ncam , 1 ) X ( mjtNum , cam_pos , ncam , 3 ) X ( mjtNum , cam_quat , ncam , 4 ) X ( mjtNum , cam_poscom0 , ncam , 3 ) X ( mjtNum , cam_pos0 , ncam , 3 ) X ( mjtNum , cam_mat0 , ncam , 9 ) X ( int , cam_projection , ncam , 1 ) X ( mjtNum , cam_fovy , ncam , 1 ) X ( mjtNum , cam_ipd , ncam , 1 ) X ( int , cam_resolution , ncam , 2 ) X ( int , cam_output , ncam , 1 ) X ( float , cam_sensorsize , ncam , 2 ) X ( float , cam_intrinsic , ncam , 4 ) X ( mjtNum , cam_user , ncam , MJ_M ( nuser_cam ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 398 + }, + "MJMODEL_POINTERS_LIGHT": { + "value": "X ( int , light_mode , nlight , 1 ) X ( int , light_bodyid , nlight , 1 ) X ( int , light_targetbodyid , nlight , 1 ) X ( int , light_type , nlight , 1 ) X ( int , light_texid , nlight , 1 ) X ( mjtByte , light_castshadow , nlight , 1 ) X ( float , light_bulbradius , nlight , 1 ) X ( float , light_intensity , nlight , 1 ) X ( float , light_range , nlight , 1 ) X ( mjtByte , light_active , nlight , 1 ) X ( mjtNum , light_pos , nlight , 3 ) X ( mjtNum , light_dir , nlight , 3 ) X ( mjtNum , light_poscom0 , nlight , 3 ) X ( mjtNum , light_pos0 , nlight , 3 ) X ( mjtNum , light_dir0 , nlight , 3 ) X ( float , light_attenuation , nlight , 3 ) X ( float , light_cutoff , nlight , 1 ) X ( float , light_exponent , nlight , 1 ) X ( float , light_ambient , nlight , 3 ) X ( float , light_diffuse , nlight , 3 ) X ( float , light_specular , nlight , 3 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 416 + }, + "MJMODEL_POINTERS_FLEX": { + "value": "X ( int , flex_contype , nflex , 1 ) X ( int , flex_conaffinity , nflex , 1 ) X ( int , flex_condim , nflex , 1 ) X ( int , flex_priority , nflex , 1 ) X ( mjtNum , flex_solmix , nflex , 1 ) X ( mjtNum , flex_solref , nflex , mjNREF ) X ( mjtNum , flex_solimp , nflex , mjNIMP ) X ( mjtNum , flex_friction , nflex , 3 ) X ( mjtNum , flex_margin , nflex , 1 ) X ( mjtNum , flex_gap , nflex , 1 ) X ( mjtByte , flex_internal , nflex , 1 ) X ( int , flex_selfcollide , nflex , 1 ) X ( int , flex_activelayers , nflex , 1 ) X ( int , flex_passive , nflex , 1 ) X ( int , flex_dim , nflex , 1 ) X ( int , flex_matid , nflex , 1 ) X ( int , flex_group , nflex , 1 ) X ( int , flex_interp , nflex , 1 ) X ( int , flex_bandwidth , nflex , 1 ) X ( int , flex_cellnum , nflex , 3 ) X ( int , flex_nodeadr , nflex , 1 ) X ( int , flex_nodenum , nflex , 1 ) X ( int , flex_vertadr , nflex , 1 ) X ( int , flex_vertnum , nflex , 1 ) X ( int , flex_edgeadr , nflex , 1 ) X ( int , flex_edgenum , nflex , 1 ) X ( int , flex_elemadr , nflex , 1 ) X ( int , flex_elemnum , nflex , 1 ) X ( int , flex_elemdataadr , nflex , 1 ) X ( int , flex_stiffnessadr , nflex , 1 ) X ( int , flex_elemedgeadr , nflex , 1 ) X ( int , flex_bendingadr , nflex , 1 ) X ( int , flex_shellnum , nflex , 1 ) X ( int , flex_shelldataadr , nflex , 1 ) X ( int , flex_evpairadr , nflex , 1 ) X ( int , flex_evpairnum , nflex , 1 ) X ( int , flex_texcoordadr , nflex , 1 ) X ( int , flex_nodebodyid , nflexnode , 1 ) X ( int , flex_vertbodyid , nflexvert , 1 ) X ( int , flex_vertedgeadr , nflexvert , 1 ) X ( int , flex_vertedgenum , nflexvert , 1 ) X ( int , flex_vertedge , nflexedge , 2 ) X ( int , flex_edge , nflexedge , 2 ) X ( int , flex_edgeflap , nflexedge , 2 ) X ( int , flex_elem , nflexelemdata , 1 ) X ( int , flex_elemtexcoord , nflexelemdata , 1 ) X ( int , flex_elemedge , nflexelemedge , 1 ) X ( int , flex_elemlayer , nflexelem , 1 ) X ( int , flex_shell , nflexshelldata , 1 ) X ( int , flex_evpair , nflexevpair , 2 ) X ( mjtNum , flex_vert , nflexvert , 3 ) X ( mjtNum , flex_vert0 , nflexvert , 3 ) X ( mjtNum , flex_vertmetric , nflexvert , 4 ) X ( mjtNum , flex_node , nflexnode , 3 ) X ( mjtNum , flex_node0 , nflexnode , 3 ) X ( mjtNum , flexedge_length0 , nflexedge , 1 ) X ( mjtNum , flexedge_invweight0 , nflexedge , 1 ) X ( mjtNum , flex_radius , nflex , 1 ) X ( mjtNum , flex_size , nflex , 3 ) X ( mjtNum , flex_stiffness , nflexstiffness , 1 ) X ( mjtNum , flex_bending , nflexbending , 1 ) X ( mjtNum , flex_damping , nflex , 1 ) X ( mjtNum , flex_edgestiffness , nflex , 1 ) X ( mjtNum , flex_edgedamping , nflex , 1 ) X ( int , flex_edgeequality , nflex , 1 ) X ( mjtByte , flex_rigid , nflex , 1 ) X ( mjtByte , flexedge_rigid , nflexedge , 1 ) X ( mjtByte , flex_centered , nflex , 1 ) X ( mjtByte , flex_flatskin , nflex , 1 ) X ( int , flex_bvhadr , nflex , 1 ) X ( int , flex_bvhnum , nflex , 1 ) X ( int , flexedge_J_rownnz , nflexedge , 1 ) X ( int , flexedge_J_rowadr , nflexedge , 1 ) X ( int , flexedge_J_colind , nJfe , 1 ) X ( int , flexvert_J_rownnz , nflexvert , 2 ) X ( int , flexvert_J_rowadr , nflexvert , 2 ) X ( int , flexvert_J_colind , nJfv , 2 ) X ( float , flex_rgba , nflex , 4 ) X ( float , flex_texcoord , nflextexcoord , 2 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 439 + }, + "MJMODEL_POINTERS_MESH": { + "value": "X ( int , mesh_vertadr , nmesh , 1 ) X ( int , mesh_vertnum , nmesh , 1 ) X ( int , mesh_faceadr , nmesh , 1 ) X ( int , mesh_facenum , nmesh , 1 ) X ( int , mesh_bvhadr , nmesh , 1 ) X ( int , mesh_bvhnum , nmesh , 1 ) X ( int , mesh_octadr , nmesh , 1 ) X ( int , mesh_octnum , nmesh , 1 ) X ( int , mesh_normaladr , nmesh , 1 ) X ( int , mesh_normalnum , nmesh , 1 ) X ( int , mesh_texcoordadr , nmesh , 1 ) X ( int , mesh_texcoordnum , nmesh , 1 ) X ( int , mesh_graphadr , nmesh , 1 ) XNV ( float , mesh_vert , nmeshvert , 3 ) XNV ( float , mesh_normal , nmeshnormal , 3 ) XNV ( float , mesh_texcoord , nmeshtexcoord , 2 ) XNV ( int , mesh_face , nmeshface , 3 ) XNV ( int , mesh_facenormal , nmeshface , 3 ) XNV ( int , mesh_facetexcoord , nmeshface , 3 ) XNV ( int , mesh_graph , nmeshgraph , 1 ) X ( mjtNum , mesh_scale , nmesh , 3 ) X ( mjtNum , mesh_pos , nmesh , 3 ) X ( mjtNum , mesh_quat , nmesh , 4 ) X ( int , mesh_pathadr , nmesh , 1 ) XNV ( int , mesh_polynum , nmesh , 1 ) XNV ( int , mesh_polyadr , nmesh , 1 ) XNV ( mjtNum , mesh_polynormal , nmeshpoly , 3 ) XNV ( int , mesh_polyvertadr , nmeshpoly , 1 ) XNV ( int , mesh_polyvertnum , nmeshpoly , 1 ) XNV ( int , mesh_polyvert , nmeshpolyvert , 1 ) XNV ( int , mesh_polymapadr , nmeshvert , 1 ) XNV ( int , mesh_polymapnum , nmeshvert , 1 ) XNV ( int , mesh_polymap , nmeshpolymap , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 520 + }, + "MJMODEL_POINTERS_SKIN": { + "value": "X ( int , skin_matid , nskin , 1 ) X ( int , skin_group , nskin , 1 ) X ( float , skin_rgba , nskin , 4 ) X ( float , skin_inflate , nskin , 1 ) X ( int , skin_vertadr , nskin , 1 ) X ( int , skin_vertnum , nskin , 1 ) X ( int , skin_texcoordadr , nskin , 1 ) X ( int , skin_faceadr , nskin , 1 ) X ( int , skin_facenum , nskin , 1 ) X ( int , skin_boneadr , nskin , 1 ) X ( int , skin_bonenum , nskin , 1 ) X ( float , skin_vert , nskinvert , 3 ) X ( float , skin_texcoord , nskintexvert , 2 ) X ( int , skin_face , nskinface , 3 ) X ( int , skin_bonevertadr , nskinbone , 1 ) X ( int , skin_bonevertnum , nskinbone , 1 ) X ( float , skin_bonebindpos , nskinbone , 3 ) X ( float , skin_bonebindquat , nskinbone , 4 ) X ( int , skin_bonebodyid , nskinbone , 1 ) X ( int , skin_bonevertid , nskinbonevert , 1 ) X ( float , skin_bonevertweight , nskinbonevert , 1 ) X ( int , skin_pathadr , nskin , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 555 + }, + "MJMODEL_POINTERS_HFIELD": { + "value": "X ( mjtNum , hfield_size , nhfield , 4 ) X ( int , hfield_nrow , nhfield , 1 ) X ( int , hfield_ncol , nhfield , 1 ) X ( int , hfield_adr , nhfield , 1 ) XNV ( float , hfield_data , nhfielddata , 1 ) X ( int , hfield_pathadr , nhfield , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 579 + }, + "MJMODEL_POINTERS_TEXTURE": { + "value": "X ( int , tex_type , ntex , 1 ) X ( int , tex_colorspace , ntex , 1 ) X ( int , tex_height , ntex , 1 ) X ( int , tex_width , ntex , 1 ) X ( int , tex_nchannel , ntex , 1 ) X ( mjtSize , tex_adr , ntex , 1 ) XNV ( mjtByte , tex_data , ntexdata , 1 ) X ( int , tex_pathadr , ntex , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 587 + }, + "MJMODEL_POINTERS_MATERIAL": { + "value": "X ( int , mat_texid , nmat , mjNTEXROLE ) X ( mjtByte , mat_texuniform , nmat , 1 ) X ( float , mat_texrepeat , nmat , 2 ) X ( float , mat_emission , nmat , 1 ) X ( float , mat_specular , nmat , 1 ) X ( float , mat_shininess , nmat , 1 ) X ( float , mat_reflectance , nmat , 1 ) X ( float , mat_metallic , nmat , 1 ) X ( float , mat_roughness , nmat , 1 ) X ( float , mat_rgba , nmat , 4 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 597 + }, + "MJMODEL_POINTERS_PAIR": { + "value": "X ( int , pair_dim , npair , 1 ) X ( int , pair_geom1 , npair , 1 ) X ( int , pair_geom2 , npair , 1 ) X ( int , pair_signature , npair , 1 ) X ( mjtNum , pair_solref , npair , mjNREF ) X ( mjtNum , pair_solreffriction , npair , mjNREF ) X ( mjtNum , pair_solimp , npair , mjNIMP ) X ( mjtNum , pair_margin , npair , 1 ) X ( mjtNum , pair_gap , npair , 1 ) X ( mjtNum , pair_friction , npair , 5 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 609 + }, + "MJMODEL_POINTERS_EXCLUDE": { + "value": "X ( int , exclude_signature , nexclude , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 621 + }, + "MJMODEL_POINTERS_EQUALITY": { + "value": "X ( int , eq_type , neq , 1 ) X ( int , eq_obj1id , neq , 1 ) X ( int , eq_obj2id , neq , 1 ) X ( int , eq_objtype , neq , 1 ) X ( mjtByte , eq_active0 , neq , 1 ) X ( mjtNum , eq_solref , neq , mjNREF ) X ( mjtNum , eq_solimp , neq , mjNIMP ) X ( mjtNum , eq_data , neq , mjNEQDATA )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 624 + }, + "MJMODEL_POINTERS_TENDON": { + "value": "X ( int , tendon_adr , ntendon , 1 ) X ( int , tendon_num , ntendon , 1 ) X ( int , tendon_matid , ntendon , 1 ) X ( int , tendon_actuatorid , ntendon , 1 ) X ( int , tendon_group , ntendon , 1 ) X ( int , tendon_treenum , ntendon , 1 ) X ( int , tendon_treeid , ntendon , 2 ) X ( int , ten_J_rownnz , ntendon , 1 ) X ( int , ten_J_rowadr , ntendon , 1 ) X ( int , ten_J_colind , nJten , 1 ) X ( mjtByte , tendon_limited , ntendon , 1 ) X ( mjtByte , tendon_actfrclimited , ntendon , 1 ) X ( mjtNum , tendon_width , ntendon , 1 ) X ( mjtNum , tendon_solref_lim , ntendon , mjNREF ) X ( mjtNum , tendon_solimp_lim , ntendon , mjNIMP ) X ( mjtNum , tendon_solref_fri , ntendon , mjNREF ) X ( mjtNum , tendon_solimp_fri , ntendon , mjNIMP ) X ( mjtNum , tendon_range , ntendon , 2 ) X ( mjtNum , tendon_actfrcrange , ntendon , 2 ) X ( mjtNum , tendon_margin , ntendon , 1 ) X ( mjtNum , tendon_stiffness , ntendon , 1 ) X ( mjtNum , tendon_stiffnesspoly , ntendon , mjNPOLY ) X ( mjtNum , tendon_damping , ntendon , 1 ) X ( mjtNum , tendon_dampingpoly , ntendon , mjNPOLY ) X ( mjtNum , tendon_armature , ntendon , 1 ) X ( mjtNum , tendon_frictionloss , ntendon , 1 ) X ( mjtNum , tendon_lengthspring , ntendon , 2 ) X ( mjtNum , tendon_length0 , ntendon , 1 ) X ( mjtNum , tendon_invweight0 , ntendon , 1 ) X ( mjtNum , tendon_user , ntendon , MJ_M ( nuser_tendon ) ) X ( float , tendon_rgba , ntendon , 4 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 634 + }, + "MJMODEL_POINTERS_ACTUATOR": { + "value": "X ( int , actuator_trntype , nu , 1 ) X ( int , actuator_dyntype , nu , 1 ) X ( int , actuator_gaintype , nu , 1 ) X ( int , actuator_biastype , nu , 1 ) X ( int , actuator_trnid , nu , 2 ) X ( mjtNum , actuator_damping , nu , 1 ) X ( mjtNum , actuator_dampingpoly , nu , mjNPOLY ) X ( mjtNum , actuator_armature , nu , 1 ) X ( int , actuator_actadr , nu , 1 ) X ( int , actuator_actnum , nu , 1 ) X ( int , actuator_group , nu , 1 ) X ( int , actuator_history , nu , 2 ) X ( int , actuator_historyadr , nu , 1 ) X ( mjtNum , actuator_delay , nu , 1 ) X ( mjtByte , actuator_ctrllimited , nu , 1 ) X ( mjtByte , actuator_forcelimited , nu , 1 ) X ( mjtByte , actuator_actlimited , nu , 1 ) X ( mjtNum , actuator_dynprm , nu , mjNDYN ) X ( mjtNum , actuator_gainprm , nu , mjNGAIN ) X ( mjtNum , actuator_biasprm , nu , mjNBIAS ) X ( mjtByte , actuator_actearly , nu , 1 ) X ( mjtNum , actuator_ctrlrange , nu , 2 ) X ( mjtNum , actuator_forcerange , nu , 2 ) X ( mjtNum , actuator_actrange , nu , 2 ) X ( mjtNum , actuator_gear , nu , 6 ) X ( mjtNum , actuator_cranklength , nu , 1 ) X ( mjtNum , actuator_acc0 , nu , 1 ) X ( mjtNum , actuator_length0 , nu , 1 ) X ( mjtNum , actuator_lengthrange , nu , 2 ) X ( mjtNum , actuator_user , nu , MJ_M ( nuser_actuator ) ) X ( int , actuator_plugin , nu , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 667 + }, + "MJMODEL_POINTERS_SENSOR": { + "value": "X ( int , sensor_type , nsensor , 1 ) X ( int , sensor_datatype , nsensor , 1 ) X ( int , sensor_needstage , nsensor , 1 ) X ( int , sensor_objtype , nsensor , 1 ) X ( int , sensor_objid , nsensor , 1 ) X ( int , sensor_reftype , nsensor , 1 ) X ( int , sensor_refid , nsensor , 1 ) X ( int , sensor_intprm , nsensor , mjNSENS ) X ( int , sensor_dim , nsensor , 1 ) X ( int , sensor_adr , nsensor , 1 ) X ( mjtNum , sensor_cutoff , nsensor , 1 ) X ( mjtNum , sensor_noise , nsensor , 1 ) X ( int , sensor_history , nsensor , 2 ) X ( int , sensor_historyadr , nsensor , 1 ) X ( mjtNum , sensor_delay , nsensor , 1 ) X ( mjtNum , sensor_interval , nsensor , 2 ) X ( mjtNum , sensor_user , nsensor , MJ_M ( nuser_sensor ) ) X ( int , sensor_plugin , nsensor , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 700 + }, + "MJMODEL_POINTERS": { + "value": "X ( mjtNum , qpos0 , nq , 1 ) X ( mjtNum , qpos_spring , nq , 1 ) MJMODEL_POINTERS_BODY X ( int , bvh_depth , nbvh , 1 ) X ( int , bvh_child , nbvh , 2 ) X ( int , bvh_nodeid , nbvh , 1 ) X ( mjtNum , bvh_aabb , nbvhstatic , 6 ) X ( int , oct_depth , noct , 1 ) X ( int , oct_child , noct , 8 ) X ( mjtNum , oct_aabb , noct , 6 ) X ( mjtNum , oct_coeff , noct , 8 ) MJMODEL_POINTERS_JOINT MJMODEL_POINTERS_DOF MJMODEL_POINTERS_TREE MJMODEL_POINTERS_GEOM MJMODEL_POINTERS_SITE MJMODEL_POINTERS_CAMERA MJMODEL_POINTERS_LIGHT MJMODEL_POINTERS_FLEX MJMODEL_POINTERS_MESH MJMODEL_POINTERS_SKIN MJMODEL_POINTERS_HFIELD MJMODEL_POINTERS_TEXTURE MJMODEL_POINTERS_MATERIAL MJMODEL_POINTERS_PAIR MJMODEL_POINTERS_EXCLUDE MJMODEL_POINTERS_EQUALITY MJMODEL_POINTERS_TENDON X ( int , wrap_type , nwrap , 1 ) X ( int , wrap_objid , nwrap , 1 ) X ( mjtNum , wrap_prm , nwrap , 1 ) MJMODEL_POINTERS_ACTUATOR MJMODEL_POINTERS_SENSOR X ( int , plugin , nplugin , 1 ) X ( int , plugin_stateadr , nplugin , 1 ) X ( int , plugin_statenum , nplugin , 1 ) X ( char , plugin_attr , npluginattr , 1 ) X ( int , plugin_attradr , nplugin , 1 ) X ( int , numeric_adr , nnumeric , 1 ) X ( int , numeric_size , nnumeric , 1 ) X ( mjtNum , numeric_data , nnumericdata , 1 ) X ( int , text_adr , ntext , 1 ) X ( int , text_size , ntext , 1 ) X ( char , text_data , ntextdata , 1 ) X ( int , tuple_adr , ntuple , 1 ) X ( int , tuple_size , ntuple , 1 ) X ( int , tuple_objtype , ntupledata , 1 ) X ( int , tuple_objid , ntupledata , 1 ) X ( mjtNum , tuple_objprm , ntupledata , 1 ) X ( mjtNum , key_time , nkey , 1 ) X ( mjtNum , key_qpos , nkey , MJ_M ( nq ) ) X ( mjtNum , key_qvel , nkey , MJ_M ( nv ) ) X ( mjtNum , key_act , nkey , MJ_M ( na ) ) X ( mjtNum , key_mpos , nkey , MJ_M ( nmocap ) * 3 ) X ( mjtNum , key_mquat , nkey , MJ_M ( nmocap ) * 4 ) X ( mjtNum , key_ctrl , nkey , MJ_M ( nu ) ) X ( int , name_bodyadr , nbody , 1 ) X ( int , name_jntadr , njnt , 1 ) X ( int , name_geomadr , ngeom , 1 ) X ( int , name_siteadr , nsite , 1 ) X ( int , name_camadr , ncam , 1 ) X ( int , name_lightadr , nlight , 1 ) X ( int , name_flexadr , nflex , 1 ) X ( int , name_meshadr , nmesh , 1 ) X ( int , name_skinadr , nskin , 1 ) X ( int , name_hfieldadr , nhfield , 1 ) X ( int , name_texadr , ntex , 1 ) X ( int , name_matadr , nmat , 1 ) X ( int , name_pairadr , npair , 1 ) X ( int , name_excludeadr , nexclude , 1 ) X ( int , name_eqadr , neq , 1 ) X ( int , name_tendonadr , ntendon , 1 ) X ( int , name_actuatoradr , nu , 1 ) X ( int , name_sensoradr , nsensor , 1 ) X ( int , name_numericadr , nnumeric , 1 ) X ( int , name_textadr , ntext , 1 ) X ( int , name_tupleadr , ntuple , 1 ) X ( int , name_keyadr , nkey , 1 ) X ( int , name_pluginadr , nplugin , 1 ) X ( char , names , nnames , 1 ) X ( int , names_map , nnames_map , 1 ) X ( char , paths , npaths , 1 ) X ( int , B_rownnz , nbody , 1 ) X ( int , B_rowadr , nbody , 1 ) X ( int , B_colind , nB , 1 ) X ( int , M_rownnz , nv , 1 ) X ( int , M_rowadr , nv , 1 ) X ( int , M_colind , nC , 1 ) X ( int , mapM2M , nC , 1 ) X ( int , D_rownnz , nv , 1 ) X ( int , D_rowadr , nv , 1 ) X ( int , D_diag , nv , 1 ) X ( int , D_colind , nD , 1 ) X ( int , mapM2D , nD , 1 ) X ( int , mapD2M , nC , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 720 + }, + "MJDATA_POINTERS": { + "value": "X ( mjtNum , qpos , nq , 1 ) X ( mjtNum , qvel , nv , 1 ) X ( mjtNum , act , na , 1 ) X ( mjtNum , history , nhistory , 1 ) X ( mjtNum , qacc_warmstart , nv , 1 ) X ( mjtNum , plugin_state , npluginstate , 1 ) X ( mjtNum , ctrl , nu , 1 ) X ( mjtNum , qfrc_applied , nv , 1 ) X ( mjtNum , xfrc_applied , nbody , 6 ) X ( mjtByte , eq_active , neq , 1 ) X ( mjtNum , mocap_pos , nmocap , 3 ) X ( mjtNum , mocap_quat , nmocap , 4 ) X ( mjtNum , qacc , nv , 1 ) X ( mjtNum , act_dot , na , 1 ) X ( mjtNum , userdata , nuserdata , 1 ) X ( mjtNum , sensordata , nsensordata , 1 ) X ( int , tree_asleep , ntree , 1 ) X ( int , plugin , nplugin , 1 ) X ( uintptr_t , plugin_data , nplugin , 1 ) X ( mjtNum , xpos , nbody , 3 ) X ( mjtNum , xquat , nbody , 4 ) X ( mjtNum , xmat , nbody , 9 ) X ( mjtNum , xipos , nbody , 3 ) X ( mjtNum , ximat , nbody , 9 ) X ( mjtNum , xanchor , njnt , 3 ) X ( mjtNum , xaxis , njnt , 3 ) X ( mjtNum , geom_xpos , ngeom , 3 ) X ( mjtNum , geom_xmat , ngeom , 9 ) X ( mjtNum , site_xpos , nsite , 3 ) X ( mjtNum , site_xmat , nsite , 9 ) X ( mjtNum , cam_xpos , ncam , 3 ) X ( mjtNum , cam_xmat , ncam , 9 ) X ( mjtNum , light_xpos , nlight , 3 ) X ( mjtNum , light_xdir , nlight , 3 ) X ( mjtNum , subtree_com , nbody , 3 ) X ( mjtNum , cdof , nv , 6 ) X ( mjtNum , cinert , nbody , 10 ) X ( mjtNum , flexvert_xpos , nflexvert , 3 ) X ( mjtNum , flexelem_aabb , nflexelem , 6 ) X ( mjtNum , flexedge_J , nJfe , 1 ) X ( mjtNum , flexedge_length , nflexedge , 1 ) X ( mjtNum , flexvert_J , nJfv , 2 ) X ( mjtNum , flexvert_length , nflexvert , 2 ) X ( mjtNum , bvh_aabb_dyn , nbvhdynamic , 6 ) X ( int , ten_wrapadr , ntendon , 1 ) X ( int , ten_wrapnum , ntendon , 1 ) X ( mjtNum , ten_J , nJten , 1 ) X ( mjtNum , ten_length , ntendon , 1 ) X ( int , wrap_obj , nwrap , 2 ) X ( mjtNum , wrap_xpos , nwrap , 6 ) X ( mjtNum , actuator_length , nu , 1 ) X ( int , moment_rownnz , nu , 1 ) X ( int , moment_rowadr , nu , 1 ) X ( int , moment_colind , nJmom , 1 ) X ( mjtNum , actuator_moment , nJmom , 1 ) XNV ( mjtNum , crb , nbody , 10 ) XNV ( mjtNum , qM , nM , 1 ) XNV ( mjtNum , M , nC , 1 ) XNV ( mjtNum , qLD , nC , 1 ) X ( mjtNum , qLDiagInv , nv , 1 ) X ( mjtByte , bvh_active , nbvh , 1 ) X ( int , tree_awake , ntree , 1 ) X ( int , body_awake , nbody , 1 ) X ( int , body_awake_ind , nbody , 1 ) X ( int , parent_awake_ind , nbody , 1 ) X ( int , dof_awake_ind , nv , 1 ) X ( mjtNum , flexedge_velocity , nflexedge , 1 ) X ( mjtNum , ten_velocity , ntendon , 1 ) X ( mjtNum , actuator_velocity , nu , 1 ) X ( mjtNum , cvel , nbody , 6 ) X ( mjtNum , cdof_dot , nv , 6 ) X ( mjtNum , qfrc_bias , nv , 1 ) X ( mjtNum , qfrc_spring , nv , 1 ) X ( mjtNum , qfrc_damper , nv , 1 ) X ( mjtNum , qfrc_gravcomp , nv , 1 ) X ( mjtNum , qfrc_fluid , nv , 1 ) X ( mjtNum , qfrc_passive , nv , 1 ) X ( mjtNum , subtree_linvel , nbody , 3 ) X ( mjtNum , subtree_angmom , nbody , 3 ) XNV ( mjtNum , qH , nC , 1 ) X ( mjtNum , qHDiagInv , nv , 1 ) XNV ( mjtNum , qDeriv , nD , 1 ) XNV ( mjtNum , qLU , nD , 1 ) X ( mjtNum , actuator_force , nu , 1 ) X ( mjtNum , qfrc_actuator , nv , 1 ) X ( mjtNum , qfrc_smooth , nv , 1 ) X ( mjtNum , qacc_smooth , nv , 1 ) X ( mjtNum , qfrc_constraint , nv , 1 ) X ( mjtNum , qfrc_inverse , nv , 1 ) X ( mjtNum , cacc , nbody , 6 ) X ( mjtNum , cfrc_int , nbody , 6 ) X ( mjtNum , cfrc_ext , nbody , 6 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 822 + }, + "MJ_D": { + "value": "( n ) n", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 919 + }, + "MJDATA_ARENA_POINTERS_CONTACT": { + "value": "X ( mjContact , contact , MJ_D ( ncon ) , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 922 + }, + "MJDATA_ARENA_POINTERS_SOLVER": { + "value": "X ( int , efc_type , MJ_D ( nefc ) , 1 ) X ( int , efc_id , MJ_D ( nefc ) , 1 ) XNV ( int , efc_J_rownnz , MJ_D ( nefc ) , 1 ) XNV ( int , efc_J_rowadr , MJ_D ( nefc ) , 1 ) XNV ( int , efc_J_rowsuper , MJ_D ( nefc ) , 1 ) XNV ( int , efc_J_colind , MJ_D ( nJ ) , 1 ) XNV ( mjtNum , efc_J , MJ_D ( nJ ) , 1 ) X ( mjtNum , efc_pos , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_margin , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_frictionloss , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_diagApprox , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_KBIP , MJ_D ( nefc ) , 4 ) X ( mjtNum , efc_D , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_R , MJ_D ( nefc ) , 1 ) X ( int , tendon_efcadr , MJ_M ( ntendon ) , 1 ) X ( mjtNum , efc_vel , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_aref , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_b , MJ_D ( nefc ) , 1 ) X ( int , efc_state , MJ_D ( nefc ) , 1 ) X ( mjtNum , efc_force , MJ_D ( nefc ) , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 926 + }, + "MJDATA_ARENA_POINTERS_DUAL": { + "value": "XNV ( int , efc_AR_rownnz , MJ_D ( nefc ) , 1 ) XNV ( int , efc_AR_rowadr , MJ_D ( nefc ) , 1 ) XNV ( int , efc_AR_colind , MJ_D ( nA ) , 1 ) XNV ( mjtNum , efc_AR , MJ_D ( nA ) , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 949 + }, + "MJDATA_ARENA_POINTERS_ISLAND": { + "value": "X ( int , tree_island , MJ_M ( ntree ) , 1 ) X ( int , island_ntree , MJ_D ( nisland ) , 1 ) X ( int , island_itreeadr , MJ_D ( nisland ) , 1 ) X ( int , map_itree2tree , MJ_M ( ntree ) , 1 ) X ( int , dof_island , MJ_M ( nv ) , 1 ) X ( int , island_nv , MJ_D ( nisland ) , 1 ) X ( int , island_idofadr , MJ_D ( nisland ) , 1 ) X ( int , island_dofadr , MJ_D ( nisland ) , 1 ) X ( int , map_dof2idof , MJ_M ( nv ) , 1 ) X ( int , map_idof2dof , MJ_M ( nv ) , 1 ) X ( mjtNum , ifrc_smooth , MJ_D ( nidof ) , 1 ) X ( mjtNum , iacc_smooth , MJ_D ( nidof ) , 1 ) XNV ( int , iM_rownnz , MJ_D ( nidof ) , 1 ) XNV ( int , iM_rowadr , MJ_D ( nidof ) , 1 ) XNV ( int , iM_colind , MJ_M ( nC ) , 1 ) XNV ( mjtNum , iM , MJ_M ( nC ) , 1 ) XNV ( mjtNum , iLD , MJ_M ( nC ) , 1 ) X ( mjtNum , iLDiagInv , MJ_D ( nidof ) , 1 ) X ( mjtNum , iacc , MJ_D ( nidof ) , 1 ) X ( int , efc_island , MJ_D ( nefc ) , 1 ) X ( int , island_ne , MJ_D ( nisland ) , 1 ) X ( int , island_nf , MJ_D ( nisland ) , 1 ) X ( int , island_nefc , MJ_D ( nisland ) , 1 ) X ( int , island_iefcadr , MJ_D ( nisland ) , 1 ) X ( int , map_efc2iefc , MJ_D ( nefc ) , 1 ) X ( int , map_iefc2efc , MJ_D ( nefc ) , 1 ) X ( int , iefc_type , MJ_D ( nefc ) , 1 ) X ( int , iefc_id , MJ_D ( nefc ) , 1 ) XNV ( int , iefc_J_rownnz , MJ_D ( nefc ) , 1 ) XNV ( int , iefc_J_rowadr , MJ_D ( nefc ) , 1 ) XNV ( int , iefc_J_rowsuper , MJ_D ( nefc ) , 1 ) XNV ( int , iefc_J_colind , MJ_D ( nJ ) , 1 ) XNV ( mjtNum , iefc_J , MJ_D ( nJ ) , 1 ) X ( mjtNum , iefc_frictionloss , MJ_D ( nefc ) , 1 ) X ( mjtNum , iefc_D , MJ_D ( nefc ) , 1 ) X ( mjtNum , iefc_R , MJ_D ( nefc ) , 1 ) X ( mjtNum , iefc_aref , MJ_D ( nefc ) , 1 ) X ( int , iefc_state , MJ_D ( nefc ) , 1 ) X ( mjtNum , iefc_force , MJ_D ( nefc ) , 1 ) X ( mjtNum , ifrc_constraint , MJ_D ( nidof ) , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 956 + }, + "MJDATA_ARENA_POINTERS": { + "value": "MJDATA_ARENA_POINTERS_CONTACT MJDATA_ARENA_POINTERS_SOLVER MJDATA_ARENA_POINTERS_DUAL MJDATA_ARENA_POINTERS_ISLAND", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 999 + }, + "MJDATA_SCALAR": { + "value": "X ( size_t , narena ) X ( size_t , nbuffer ) X ( int , nplugin ) X ( size_t , pstack ) X ( size_t , pbase ) X ( size_t , parena ) X ( size_t , maxuse_stack ) X ( size_t , maxuse_arena ) X ( int , maxuse_con ) X ( int , maxuse_efc ) X ( int , ncon ) X ( int , ne ) X ( int , nf ) X ( int , nl ) X ( int , nefc ) X ( int , nJ ) X ( int , nA ) X ( int , nisland ) X ( int , nidof ) X ( int , ntree_awake ) X ( int , nbody_awake ) X ( int , nparent_awake ) X ( int , nv_awake ) X ( mjtByte , flg_energypos ) X ( mjtByte , flg_energyvel ) X ( mjtByte , flg_subtreevel ) X ( mjtByte , flg_rnepost ) X ( mjtNum , time ) X ( uintptr_t , threadpool )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 1007 + }, + "MJDATA_VECTOR": { + "value": "X ( size_t , maxuse_threadstack , mjMAXTHREAD , 1 ) X ( mjSolverStat , solver , mjNISLAND , mjNSOLVER ) X ( int , solver_niter , mjNISLAND , 1 ) X ( int , solver_nnz , mjNISLAND , 1 ) X ( mjtNum , solver_fwdinv , 2 , 1 ) X ( mjWarningStat , warning , mjNWARNING , 1 ) X ( mjTimerStat , timer , mjNTIMER , 1 ) X ( mjtNum , energy , 2 , 1 )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 1040 + }, + "XNV": { + "value": "X", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjxmacro.h", + "line": 1053 + }, + "mjVERSION_HEADER": { + "value": "3008001", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 19 + }, + "mjMAXTHREAD": { + "value": "128", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjthread.h", + "line": 18 + }, + "MUJOCO_HELPER_DLL_IMPORT": { + "value": "__declspec ( dllimport )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjexport.h", + "line": 19 + }, + "MUJOCO_HELPER_DLL_EXPORT": { + "value": "__declspec ( dllexport )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjexport.h", + "line": 20 + }, + "mjMAX": { + "value": "( a , b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmacro.h", + "line": 19 + }, + "mjMIN": { + "value": "( a , b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmacro.h", + "line": 20 + }, + "mjDISABLED": { + "value": "( x ) ( m -> opt . disableflags & ( x ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmacro.h", + "line": 23 + }, + "mjENABLED": { + "value": "( x ) ( m -> opt . enableflags & ( x ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmacro.h", + "line": 24 + }, + "mjACTUATORDISABLED": { + "value": "( i ) ( m -> opt . disableactuator & ( 1 << m -> actuator_group [ i ] ) )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmacro.h", + "line": 27 + }, + "mjPRINTFLIKE": { + "value": "( n , m )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjmacro.h", + "line": 34 + }, + "mjNGROUP": { + "value": "6", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 23 + }, + "mjMAXLIGHT": { + "value": "100", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 24 + }, + "mjMAXOVERLAY": { + "value": "500", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 25 + }, + "mjMAXLINE": { + "value": "100", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 26 + }, + "mjMAXLINEPNT": { + "value": "1001", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 27 + }, + "mjMAXPLANEGRID": { + "value": "200", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjvisualize.h", + "line": 28 + }, + "mjPLUGIN_LIB_INIT": { + "value": "( n ) static void _mj_init_ ## n ( void ) __attribute__ ( ( constructor ) ) ; static void _mj_init_ ## n ( void )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjplugin.h", + "line": 189 + }, + "mjNAUX": { + "value": "10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 24 + }, + "mjMAXTEXTURE": { + "value": "1000", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 25 + }, + "mjMAXMATERIAL": { + "value": "1000", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjrender.h", + "line": 26 + }, + "ASAN_POISON_MEMORY_REGION": { + "value": "( addr , size )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjsan.h", + "line": 33 + }, + "ASAN_UNPOISON_MEMORY_REGION": { + "value": "( addr , size )", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjsan.h", + "line": 34 + }, + "mjMAXUISECT": { + "value": "10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 20 + }, + "mjMAXUIITEM": { + "value": "200", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 21 + }, + "mjMAXUITEXT": { + "value": "300", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 22 + }, + "mjMAXUINAME": { + "value": "40", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 23 + }, + "mjMAXUIMULTI": { + "value": "35", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 24 + }, + "mjMAXUIEDIT": { + "value": "7", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 25 + }, + "mjMAXUIRECT": { + "value": "25", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 26 + }, + "mjSEPCLOSED": { + "value": "1000", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 28 + }, + "mjPRESERVE": { + "value": "2000", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 29 + }, + "mjKEY_ESCAPE": { + "value": "256", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 33 + }, + "mjKEY_ENTER": { + "value": "257", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 34 + }, + "mjKEY_TAB": { + "value": "258", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 35 + }, + "mjKEY_BACKSPACE": { + "value": "259", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 36 + }, + "mjKEY_INSERT": { + "value": "260", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 37 + }, + "mjKEY_DELETE": { + "value": "261", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 38 + }, + "mjKEY_RIGHT": { + "value": "262", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 39 + }, + "mjKEY_LEFT": { + "value": "263", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 40 + }, + "mjKEY_DOWN": { + "value": "264", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 41 + }, + "mjKEY_UP": { + "value": "265", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 42 + }, + "mjKEY_PAGE_UP": { + "value": "266", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 43 + }, + "mjKEY_PAGE_DOWN": { + "value": "267", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 44 + }, + "mjKEY_HOME": { + "value": "268", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 45 + }, + "mjKEY_END": { + "value": "269", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 46 + }, + "mjKEY_F1": { + "value": "290", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 47 + }, + "mjKEY_F2": { + "value": "291", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 48 + }, + "mjKEY_F3": { + "value": "292", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 49 + }, + "mjKEY_F4": { + "value": "293", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 50 + }, + "mjKEY_F5": { + "value": "294", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 51 + }, + "mjKEY_F6": { + "value": "295", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 52 + }, + "mjKEY_F7": { + "value": "296", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 53 + }, + "mjKEY_F8": { + "value": "297", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 54 + }, + "mjKEY_F9": { + "value": "298", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 55 + }, + "mjKEY_F10": { + "value": "299", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 56 + }, + "mjKEY_F11": { + "value": "300", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 57 + }, + "mjKEY_F12": { + "value": "301", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 58 + }, + "mjKEY_NUMPAD_0": { + "value": "320", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 59 + }, + "mjKEY_NUMPAD_9": { + "value": "329", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mjui.h", + "line": 60 + }, + "mju_sqrt": { + "value": "sqrt", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1015 + }, + "mju_exp": { + "value": "exp", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1016 + }, + "mju_sin": { + "value": "sin", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1017 + }, + "mju_cos": { + "value": "cos", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1018 + }, + "mju_tan": { + "value": "tan", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1019 + }, + "mju_asin": { + "value": "asin", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1020 + }, + "mju_acos": { + "value": "acos", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1021 + }, + "mju_atan2": { + "value": "atan2", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1022 + }, + "mju_tanh": { + "value": "tanh", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1023 + }, + "mju_pow": { + "value": "pow", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1024 + }, + "mju_abs": { + "value": "fabs", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1025 + }, + "mju_log": { + "value": "log", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1026 + }, + "mju_log10": { + "value": "log10", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1027 + }, + "mju_floor": { + "value": "floor", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1028 + }, + "mju_ceil": { + "value": "ceil", + "doc": "", + "file": "third_party/install/mujoco/include/mujoco/mujoco.h", + "line": 1029 + } + }, + "hand_enums": { + "EMjActuatorType": { + "name": "EMjActuatorType", + "members": { + "Motor": 0, + "Position": 1, + "Velocity": 2, + "IntVelocity": 3, + "Damper": 4, + "Cylinder": 5, + "Muscle": 6, + "Adhesion": 7, + "DcMotor": 8 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/actuators/mjactuator.h", + "line": 42 + }, + "EMjDcMotorInput": { + "name": "EMjDcMotorInput", + "members": { + "Voltage": 0, + "Position": 1, + "Velocity": 2 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/actuators/mjdcmotoractuator.h", + "line": 35 + }, + "EMjBodySleepPolicy": { + "name": "EMjBodySleepPolicy", + "members": { + "Auto": 0, + "Never": 3, + "Allowed": 4, + "InitAsleep": 5 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/bodies/mjbody.h", + "line": 47 + }, + "EMjEqualityType": { + "name": "EMjEqualityType", + "members": { + "Connect": 0, + "Weld": 1, + "Joint": 2, + "Tendon": 3, + "Flex": 4, + "FlexVert": 5, + "FlexStrain": 6 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/constraints/mjequality.h", + "line": 36 + }, + "EMjFlexcompType": { + "name": "EMjFlexcompType", + "members": { + "Grid": 0, + "Box": 1, + "Cylinder": 2, + "Ellipsoid": 3, + "Square": 4, + "Disc": 5, + "Circle": 6, + "Mesh": 7, + "Gmsh": 8, + "Direct": 9 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/deformable/mjflexcomp.h", + "line": 36 + }, + "EMjGeomType": { + "name": "EMjGeomType", + "members": { + "Plane": 0, + "Hfield": 1, + "Sphere": 2, + "Capsule": 3, + "Ellipsoid": 4, + "Cylinder": 5, + "Box": 6, + "Mesh": 7, + "SDF": 8 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/geometry/mjgeom.h", + "line": 39 + }, + "EMjSiteType": { + "name": "EMjSiteType", + "members": { + "Sphere": 0, + "Capsule": 1, + "Ellipsoid": 2, + "Cylinder": 3, + "Box": 4, + "Mesh": 5, + "Hfield": 6 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/geometry/mjsite.h", + "line": 42 + }, + "EMjJointType": { + "name": "EMjJointType", + "members": { + "Free": 0, + "Ball": 1, + "Slide": 2, + "Hinge": 3 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/joints/mjjoint.h", + "line": 39 + }, + "EMjCameraMode": { + "name": "EMjCameraMode", + "members": { + "Real": 0, + "Depth": 1, + "SemanticSegmentation": 2, + "InstanceSegmentation": 3 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/sensors/mjcameratypes.h", + "line": 35 + }, + "EMjSensorType": { + "name": "EMjSensorType", + "members": { + "Touch": 0, + "Accelerometer": 1, + "Velocimeter": 2, + "Gyro": 3, + "Force": 4, + "Torque": 5, + "Magnetometer": 6, + "RangeFinder": 7, + "CamProjection": 8, + "JointPos": 9, + "JointVel": 10, + "TendonPos": 11, + "TendonVel": 12, + "ActuatorPos": 13, + "ActuatorVel": 14, + "ActuatorFrc": 15, + "JointActFrc": 16, + "TendonActFrc": 17, + "BallQuat": 18, + "BallAngVel": 19, + "JointLimitPos": 20, + "JointLimitVel": 21, + "JointLimitFrc": 22, + "TendonLimitPos": 23, + "TendonLimitVel": 24, + "TendonLimitFrc": 25, + "FramePos": 26, + "FrameQuat": 27, + "FrameXAxis": 28, + "FrameYAxis": 29, + "FrameZAxis": 30, + "FrameLinVel": 31, + "FrameAngVel": 32, + "FrameLinAcc": 33, + "FrameAngAcc": 34, + "SubtreeCom": 35, + "SubtreeLinVel": 36, + "SubtreeAngMom": 37, + "InsideSite": 38, + "GeomDist": 39, + "GeomNormal": 40, + "GeomFromTo": 41, + "Contact": 42, + "EPotential": 43, + "EKinetic": 44, + "Clock": 45, + "Tactile": 46, + "Plugin": 47, + "User": 48 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/sensors/mjsensor.h", + "line": 42 + }, + "EMjTendonWrapType": { + "name": "EMjTendonWrapType", + "members": { + "Joint": 0, + "Site": 1, + "Geom": 2, + "Pulley": 3 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/components/tendons/mjtendon.h", + "line": 40 + }, + "EMjDebugShaderMode": { + "name": "EMjDebugShaderMode", + "members": { + "Off": 0, + "Island": 1, + "InstanceSegmentation": 2, + "SemanticSegmentation": 3 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/core/mjdebugvisualizer.h", + "line": 39 + }, + "EMjGainType": { + "name": "EMjGainType", + "members": { + "Fixed": 0, + "Affine": 1, + "Muscle": 2, + "DcMotor": 3, + "User": 4 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 33 + }, + "EMjBiasType": { + "name": "EMjBiasType", + "members": { + "None": 0, + "Affine": 1, + "Muscle": 2, + "DcMotor": 3, + "User": 4 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 44 + }, + "EMjDynType": { + "name": "EMjDynType", + "members": { + "None": 0, + "Integrator": 1, + "Filter": 2, + "FilterExact": 3, + "Muscle": 4, + "DcMotor": 5, + "User": 6 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 55 + }, + "EMjGeomInertia": { + "name": "EMjGeomInertia", + "members": { + "Volume": 0, + "Shell": 1 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 68 + }, + "EMjFluidShape": { + "name": "EMjFluidShape", + "members": { + "None": 0, + "Ellipsoid": 1 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 76 + }, + "EMjCameraTrackingMode": { + "name": "EMjCameraTrackingMode", + "members": { + "Fixed": 0, + "Track": 1, + "TrackCom": 2, + "TargetBody": 3, + "TargetBodyCom": 4 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 84 + }, + "EMjCameraProjection": { + "name": "EMjCameraProjection", + "members": { + "Perspective": 0, + "Orthographic": 1 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 95 + }, + "EMjObjType": { + "name": "EMjObjType", + "members": { + "Unknown": 0, + "Body": 1, + "XBody": 2, + "Joint": 3, + "DoF": 4, + "Geom": 5, + "Site": 6, + "Camera": 7, + "Light": 8, + "Flex": 9, + "Mesh": 10, + "Skin": 11, + "HField": 12, + "Texture": 13, + "Material": 14, + "Pair": 15, + "Exclude": 16, + "Equality": 17, + "Tendon": 18, + "Actuator": 19, + "Sensor": 20, + "Numeric": 21, + "Text": 22, + "Tuple": 23, + "Key": 24, + "Plugin": 25, + "Frame": 100 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 103 + }, + "EMjActuatorTrnType": { + "name": "EMjActuatorTrnType", + "members": { + "Joint": 0, + "JointInParent": 1, + "SliderCrank": 2, + "Tendon": 3, + "Site": 4, + "Body": 5, + "Undefined": 6 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 136 + }, + "EMjFlexcompDof": { + "name": "EMjFlexcompDof", + "members": { + "Full": 0, + "Radial": 1, + "Trilinear": 2, + "Quadratic": 3, + "TwoD": 4 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjarticulationenums.h", + "line": 149 + }, + "EMjIntegrator": { + "name": "EMjIntegrator", + "members": { + "Euler": 0, + "RK4": 1, + "Implicit": 2, + "ImplicitFast": 3 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjoptionenums.h", + "line": 33 + }, + "EMjCone": { + "name": "EMjCone", + "members": { + "Pyramidal": 0, + "Elliptic": 1 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjoptionenums.h", + "line": 43 + }, + "EMjSolver": { + "name": "EMjSolver", + "members": { + "PGS": 0, + "CG": 1, + "Newton": 2 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/mujoco/generated/mjoptionenums.h", + "line": 51 + }, + "EMjPropertyType": { + "name": "EMjPropertyType", + "members": { + "Slider": 0, + "Toggle": 1, + "LabelOnly": 2, + "Header": 3 + }, + "member_docs": {}, + "underlying_type": "uint8", + "doc": "", + "file": "source/urlab/public/ui/mjpropertyrow.h", + "line": 38 + } + } +} \ No newline at end of file diff --git a/Scripts/mjcf_schema_snapshot.json b/Scripts/codegen/snapshots/mjcf_schema_snapshot.json similarity index 56% rename from Scripts/mjcf_schema_snapshot.json rename to Scripts/codegen/snapshots/mjcf_schema_snapshot.json index 05a5798..ef17273 100644 --- a/Scripts/mjcf_schema_snapshot.json +++ b/Scripts/codegen/snapshots/mjcf_schema_snapshot.json @@ -1,7 +1,7 @@ { "_meta": { "mujoco_version": "3.8.1", - "snapshot_date": "2026-05-15", + "snapshot_date": "2026-05-28", "source": "https://github.com/google-deepmind/mujoco/blob/main/src/xml/xml_native_reader.cc", "description": "MJCF schema snapshot, auto-extracted by Scripts/codegen/build_mjcf_schema_snapshot.py from the MuJoCo submodule's xml_native_reader.cc." }, @@ -351,6 +351,400 @@ "user" ] }, + "sensor_per_type": { + "touch": { + "mj_type": "mjSENS_TOUCH", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "accelerometer": { + "mj_type": "mjSENS_ACCELEROMETER", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "velocimeter": { + "mj_type": "mjSENS_VELOCIMETER", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "gyro": { + "mj_type": "mjSENS_GYRO", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "force": { + "mj_type": "mjSENS_FORCE", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "torque": { + "mj_type": "mjSENS_TORQUE", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "magnetometer": { + "mj_type": "mjSENS_MAGNETOMETER", + "objtype": "mjOBJ_SITE", + "reftype": null, + "obj_attr": "site", + "ref_attr": null, + "computed": false + }, + "camprojection": { + "mj_type": "mjSENS_CAMPROJECTION", + "objtype": "mjOBJ_SITE", + "reftype": "mjOBJ_CAMERA", + "obj_attr": "site", + "ref_attr": "camera", + "computed": false + }, + "rangefinder": { + "mj_type": "mjSENS_RANGEFINDER", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "site", + "ref_attr": null, + "computed": true + }, + "jointpos": { + "mj_type": "mjSENS_JOINTPOS", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "jointvel": { + "mj_type": "mjSENS_JOINTVEL", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "tendonpos": { + "mj_type": "mjSENS_TENDONPOS", + "objtype": "mjOBJ_TENDON", + "reftype": null, + "obj_attr": "tendon", + "ref_attr": null, + "computed": false + }, + "tendonvel": { + "mj_type": "mjSENS_TENDONVEL", + "objtype": "mjOBJ_TENDON", + "reftype": null, + "obj_attr": "tendon", + "ref_attr": null, + "computed": false + }, + "actuatorpos": { + "mj_type": "mjSENS_ACTUATORPOS", + "objtype": "mjOBJ_ACTUATOR", + "reftype": null, + "obj_attr": "actuator", + "ref_attr": null, + "computed": false + }, + "actuatorvel": { + "mj_type": "mjSENS_ACTUATORVEL", + "objtype": "mjOBJ_ACTUATOR", + "reftype": null, + "obj_attr": "actuator", + "ref_attr": null, + "computed": false + }, + "actuatorfrc": { + "mj_type": "mjSENS_ACTUATORFRC", + "objtype": "mjOBJ_ACTUATOR", + "reftype": null, + "obj_attr": "actuator", + "ref_attr": null, + "computed": false + }, + "jointactuatorfrc": { + "mj_type": "mjSENS_JOINTACTFRC", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "tendonactuatorfrc": { + "mj_type": "mjSENS_TENDONACTFRC", + "objtype": "mjOBJ_TENDON", + "reftype": null, + "obj_attr": "tendon", + "ref_attr": null, + "computed": false + }, + "ballquat": { + "mj_type": "mjSENS_BALLQUAT", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "ballangvel": { + "mj_type": "mjSENS_BALLANGVEL", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "jointlimitpos": { + "mj_type": "mjSENS_JOINTLIMITPOS", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "jointlimitvel": { + "mj_type": "mjSENS_JOINTLIMITVEL", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "jointlimitfrc": { + "mj_type": "mjSENS_JOINTLIMITFRC", + "objtype": "mjOBJ_JOINT", + "reftype": null, + "obj_attr": "joint", + "ref_attr": null, + "computed": false + }, + "tendonlimitpos": { + "mj_type": "mjSENS_TENDONLIMITPOS", + "objtype": "mjOBJ_TENDON", + "reftype": null, + "obj_attr": "tendon", + "ref_attr": null, + "computed": false + }, + "tendonlimitvel": { + "mj_type": "mjSENS_TENDONLIMITVEL", + "objtype": "mjOBJ_TENDON", + "reftype": null, + "obj_attr": "tendon", + "ref_attr": null, + "computed": false + }, + "tendonlimitfrc": { + "mj_type": "mjSENS_TENDONLIMITFRC", + "objtype": "mjOBJ_TENDON", + "reftype": null, + "obj_attr": "tendon", + "ref_attr": null, + "computed": false + }, + "framepos": { + "mj_type": "mjSENS_FRAMEPOS", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "framequat": { + "mj_type": "mjSENS_FRAMEQUAT", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "framexaxis": { + "mj_type": "mjSENS_FRAMEXAXIS", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "frameyaxis": { + "mj_type": "mjSENS_FRAMEYAXIS", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "framezaxis": { + "mj_type": "mjSENS_FRAMEZAXIS", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "framelinvel": { + "mj_type": "mjSENS_FRAMELINVEL", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "frameangvel": { + "mj_type": "mjSENS_FRAMEANGVEL", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": "refname", + "computed": false + }, + "framelinacc": { + "mj_type": "mjSENS_FRAMELINACC", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": null, + "computed": false + }, + "frameangacc": { + "mj_type": "mjSENS_FRAMEANGACC", + "objtype": "from_xml", + "reftype": null, + "obj_attr": "objname", + "ref_attr": null, + "computed": false + }, + "subtreecom": { + "mj_type": "mjSENS_SUBTREECOM", + "objtype": "mjOBJ_BODY", + "reftype": null, + "obj_attr": "body", + "ref_attr": null, + "computed": false + }, + "subtreelinvel": { + "mj_type": "mjSENS_SUBTREELINVEL", + "objtype": "mjOBJ_BODY", + "reftype": null, + "obj_attr": "body", + "ref_attr": null, + "computed": false + }, + "subtreeangmom": { + "mj_type": "mjSENS_SUBTREEANGMOM", + "objtype": "mjOBJ_BODY", + "reftype": null, + "obj_attr": "body", + "ref_attr": null, + "computed": false + }, + "insidesite": { + "mj_type": "mjSENS_INSIDESITE", + "objtype": "from_xml", + "reftype": "mjOBJ_SITE", + "obj_attr": "objname", + "ref_attr": "site", + "computed": false + }, + "distance": { + "mj_type": "mjSENS_GEOMDIST", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "body1", + "ref_attr": "body2", + "computed": true + }, + "normal": { + "mj_type": "mjSENS_GEOMNORMAL", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "body1", + "ref_attr": "body2", + "computed": true + }, + "fromto": { + "mj_type": "mjSENS_GEOMFROMTO", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "body1", + "ref_attr": "body2", + "computed": true + }, + "contact": { + "mj_type": "mjSENS_CONTACT", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "site", + "ref_attr": "body2", + "computed": true + }, + "e_potential": { + "mj_type": "mjSENS_E_POTENTIAL", + "objtype": "mjOBJ_UNKNOWN", + "reftype": null, + "obj_attr": null, + "ref_attr": null, + "computed": false + }, + "e_kinetic": { + "mj_type": "mjSENS_E_KINETIC", + "objtype": "mjOBJ_UNKNOWN", + "reftype": null, + "obj_attr": null, + "ref_attr": null, + "computed": false + }, + "clock": { + "mj_type": "mjSENS_CLOCK", + "objtype": "mjOBJ_UNKNOWN", + "reftype": null, + "obj_attr": null, + "ref_attr": null, + "computed": false + }, + "tactile": { + "mj_type": "mjSENS_TACTILE", + "objtype": "mjOBJ_MESH", + "reftype": "mjOBJ_GEOM", + "obj_attr": "mesh", + "ref_attr": "geom", + "computed": false + }, + "user": { + "mj_type": "mjSENS_USER", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "objname", + "ref_attr": null, + "computed": true + }, + "plugin": { + "mj_type": "mjSENS_PLUGIN", + "objtype": "computed", + "reftype": "computed", + "obj_attr": "objname", + "ref_attr": "refname", + "computed": true + } + }, "tendon": { "spatial": { "attrs": [ diff --git a/Scripts/mjxmacro_snapshot.json b/Scripts/codegen/snapshots/mjxmacro_snapshot.json similarity index 69% rename from Scripts/mjxmacro_snapshot.json rename to Scripts/codegen/snapshots/mjxmacro_snapshot.json index bdfe4c1..52f77d5 100644 --- a/Scripts/mjxmacro_snapshot.json +++ b/Scripts/codegen/snapshots/mjxmacro_snapshot.json @@ -1,7 +1,19 @@ { "_meta": { "source": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", - "schema_kind": "mjxmacro" + "schema_kind": "mjxmacro", + "struct_field_sources": { + "MJOPTION_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJSTATISTIC_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJVISUAL_GLOBAL_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJVISUAL_QUALITY_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJVISUAL_HEADLIGHT_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJVISUAL_MAP_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJVISUAL_SCALE_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJVISUAL_RGBA_FIELDS": "third_party\\install\\MuJoCo\\include\\mujoco\\mjxmacro.h", + "MJSCOMPILER_FIELDS": "Scripts\\codegen\\_vendored\\mjspecmacro.h", + "MJSPEC_FIELDS": "Scripts\\codegen\\_vendored\\mjspecmacro.h" + } }, "mjmodel_pointers": { "MJMODEL_POINTERS_BODY": [ @@ -552,6 +564,24 @@ "name": "geom_gap", "outer_dim": "ngeom", "stride": "1" + }, + { + "type": "mjtNum", + "name": "geom_fluid", + "outer_dim": "ngeom", + "stride": "mjNFLUID" + }, + { + "type": "mjtNum", + "name": "geom_user", + "outer_dim": "ngeom", + "stride": "MJ_M(nuser_geom)" + }, + { + "type": "float", + "name": "geom_rgba", + "outer_dim": "ngeom", + "stride": "4" } ], "MJMODEL_POINTERS_SITE": [ @@ -1396,6 +1426,126 @@ "name": "mesh_graphadr", "outer_dim": "nmesh", "stride": "1" + }, + { + "type": "float", + "name": "mesh_vert", + "outer_dim": "nmeshvert", + "stride": "3" + }, + { + "type": "float", + "name": "mesh_normal", + "outer_dim": "nmeshnormal", + "stride": "3" + }, + { + "type": "float", + "name": "mesh_texcoord", + "outer_dim": "nmeshtexcoord", + "stride": "2" + }, + { + "type": "int", + "name": "mesh_face", + "outer_dim": "nmeshface", + "stride": "3" + }, + { + "type": "int", + "name": "mesh_facenormal", + "outer_dim": "nmeshface", + "stride": "3" + }, + { + "type": "int", + "name": "mesh_facetexcoord", + "outer_dim": "nmeshface", + "stride": "3" + }, + { + "type": "int", + "name": "mesh_graph", + "outer_dim": "nmeshgraph", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "mesh_scale", + "outer_dim": "nmesh", + "stride": "3" + }, + { + "type": "mjtNum", + "name": "mesh_pos", + "outer_dim": "nmesh", + "stride": "3" + }, + { + "type": "mjtNum", + "name": "mesh_quat", + "outer_dim": "nmesh", + "stride": "4" + }, + { + "type": "int", + "name": "mesh_pathadr", + "outer_dim": "nmesh", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polynum", + "outer_dim": "nmesh", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polyadr", + "outer_dim": "nmesh", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "mesh_polynormal", + "outer_dim": "nmeshpoly", + "stride": "3" + }, + { + "type": "int", + "name": "mesh_polyvertadr", + "outer_dim": "nmeshpoly", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polyvertnum", + "outer_dim": "nmeshpoly", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polyvert", + "outer_dim": "nmeshpolyvert", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polymapadr", + "outer_dim": "nmeshvert", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polymapnum", + "outer_dim": "nmeshvert", + "stride": "1" + }, + { + "type": "int", + "name": "mesh_polymap", + "outer_dim": "nmeshpolymap", + "stride": "1" } ], "MJMODEL_POINTERS_SKIN": [ @@ -1556,6 +1706,18 @@ "name": "hfield_adr", "outer_dim": "nhfield", "stride": "1" + }, + { + "type": "float", + "name": "hfield_data", + "outer_dim": "nhfielddata", + "stride": "1" + }, + { + "type": "int", + "name": "hfield_pathadr", + "outer_dim": "nhfield", + "stride": "1" } ], "MJMODEL_POINTERS_TEXTURE": [ @@ -1594,6 +1756,18 @@ "name": "tex_adr", "outer_dim": "ntex", "stride": "1" + }, + { + "type": "mjtByte", + "name": "tex_data", + "outer_dim": "ntexdata", + "stride": "1" + }, + { + "type": "int", + "name": "tex_pathadr", + "outer_dim": "ntex", + "stride": "1" } ], "MJMODEL_POINTERS_MATERIAL": [ @@ -2596,417 +2770,1574 @@ "name": "actuator_moment", "outer_dim": "nJmom", "stride": "1" - } - ], - "MJDATA_ARENA_POINTERS_SOLVER": [ + }, { - "type": "int", - "name": "efc_type", - "outer_dim": "MJ_D(nefc)", - "stride": "1" + "type": "mjtNum", + "name": "crb", + "outer_dim": "nbody", + "stride": "10" }, { - "type": "int", - "name": "efc_id", - "outer_dim": "MJ_D(nefc)", + "type": "mjtNum", + "name": "qM", + "outer_dim": "nM", "stride": "1" - } - ], - "MJDATA_ARENA_POINTERS_DUAL": [], - "MJDATA_ARENA_POINTERS_ISLAND": [ + }, { - "type": "int", - "name": "tree_island", - "outer_dim": "MJ_M(ntree)", + "type": "mjtNum", + "name": "M", + "outer_dim": "nC", "stride": "1" }, { - "type": "int", - "name": "island_ntree", - "outer_dim": "MJ_D(nisland)", + "type": "mjtNum", + "name": "qLD", + "outer_dim": "nC", "stride": "1" }, { - "type": "int", - "name": "island_itreeadr", - "outer_dim": "MJ_D(nisland)", + "type": "mjtNum", + "name": "qLDiagInv", + "outer_dim": "nv", "stride": "1" }, { - "type": "int", - "name": "map_itree2tree", - "outer_dim": "MJ_M(ntree)", + "type": "mjtByte", + "name": "bvh_active", + "outer_dim": "nbvh", "stride": "1" }, { "type": "int", - "name": "dof_island", - "outer_dim": "MJ_M(nv)", + "name": "tree_awake", + "outer_dim": "ntree", "stride": "1" }, { "type": "int", - "name": "island_nv", - "outer_dim": "MJ_D(nisland)", + "name": "body_awake", + "outer_dim": "nbody", "stride": "1" }, { "type": "int", - "name": "island_idofadr", - "outer_dim": "MJ_D(nisland)", + "name": "body_awake_ind", + "outer_dim": "nbody", "stride": "1" }, { "type": "int", - "name": "island_dofadr", - "outer_dim": "MJ_D(nisland)", + "name": "parent_awake_ind", + "outer_dim": "nbody", "stride": "1" }, { "type": "int", - "name": "map_dof2idof", - "outer_dim": "MJ_M(nv)", + "name": "dof_awake_ind", + "outer_dim": "nv", "stride": "1" }, { - "type": "int", - "name": "map_idof2dof", - "outer_dim": "MJ_M(nv)", + "type": "mjtNum", + "name": "flexedge_velocity", + "outer_dim": "nflexedge", "stride": "1" }, { "type": "mjtNum", - "name": "ifrc_smooth", - "outer_dim": "MJ_D(nidof)", + "name": "ten_velocity", + "outer_dim": "ntendon", "stride": "1" }, { "type": "mjtNum", - "name": "iacc_smooth", - "outer_dim": "MJ_D(nidof)", + "name": "actuator_velocity", + "outer_dim": "nu", "stride": "1" - } - ], - "MJDATA_ARENA_POINTERS": [] - }, - "struct_fields": { - "MJOPTION_FIELDS": [ + }, { "type": "mjtNum", - "name": "timestep", - "count": "1", - "is_vec": false + "name": "cvel", + "outer_dim": "nbody", + "stride": "6" }, { "type": "mjtNum", - "name": "impratio", - "count": "1", - "is_vec": false + "name": "cdof_dot", + "outer_dim": "nv", + "stride": "6" }, { "type": "mjtNum", - "name": "tolerance", - "count": "1", - "is_vec": false + "name": "qfrc_bias", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "ls_tolerance", - "count": "1", - "is_vec": false + "name": "qfrc_spring", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "noslip_tolerance", - "count": "1", - "is_vec": false + "name": "qfrc_damper", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "ccd_tolerance", - "count": "1", - "is_vec": false + "name": "qfrc_gravcomp", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "sleep_tolerance", - "count": "1", - "is_vec": false + "name": "qfrc_fluid", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "gravity", - "count": "3", - "is_vec": true + "name": "qfrc_passive", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "wind", - "count": "3", - "is_vec": true + "name": "subtree_linvel", + "outer_dim": "nbody", + "stride": "3" }, { "type": "mjtNum", - "name": "magnetic", - "count": "3", - "is_vec": true + "name": "subtree_angmom", + "outer_dim": "nbody", + "stride": "3" }, { "type": "mjtNum", - "name": "density", - "count": "1", - "is_vec": false + "name": "qH", + "outer_dim": "nC", + "stride": "1" }, { "type": "mjtNum", - "name": "viscosity", - "count": "1", - "is_vec": false + "name": "qHDiagInv", + "outer_dim": "nv", + "stride": "1" }, { "type": "mjtNum", - "name": "o_margin", - "count": "1", - "is_vec": false + "name": "qDeriv", + "outer_dim": "nD", + "stride": "1" }, { "type": "mjtNum", - "name": "o_solref", - "count": "mjNREF", - "is_vec": true + "name": "qLU", + "outer_dim": "nD", + "stride": "1" }, { "type": "mjtNum", - "name": "o_solimp", - "count": "mjNIMP", - "is_vec": true + "name": "actuator_force", + "outer_dim": "nu", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "qfrc_actuator", + "outer_dim": "nv", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "qfrc_smooth", + "outer_dim": "nv", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "qacc_smooth", + "outer_dim": "nv", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "qfrc_constraint", + "outer_dim": "nv", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "qfrc_inverse", + "outer_dim": "nv", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "cacc", + "outer_dim": "nbody", + "stride": "6" + }, + { + "type": "mjtNum", + "name": "cfrc_int", + "outer_dim": "nbody", + "stride": "6" + }, + { + "type": "mjtNum", + "name": "cfrc_ext", + "outer_dim": "nbody", + "stride": "6" + } + ], + "MJDATA_ARENA_POINTERS_CONTACT": [ + { + "type": "mjContact", + "name": "contact", + "outer_dim": "MJ_D(ncon)", + "stride": "1" + } + ], + "MJDATA_ARENA_POINTERS_SOLVER": [ + { + "type": "int", + "name": "efc_type", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_id", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_J_rownnz", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_J_rowadr", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_J_rowsuper", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_J_colind", + "outer_dim": "MJ_D(nJ)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_J", + "outer_dim": "MJ_D(nJ)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_pos", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_margin", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_frictionloss", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_diagApprox", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_KBIP", + "outer_dim": "MJ_D(nefc)", + "stride": "4" + }, + { + "type": "mjtNum", + "name": "efc_D", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_R", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "tendon_efcadr", + "outer_dim": "MJ_M(ntendon)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_vel", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_aref", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_b", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_state", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_force", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + } + ], + "MJDATA_ARENA_POINTERS_DUAL": [ + { + "type": "int", + "name": "efc_AR_rownnz", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_AR_rowadr", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_AR_colind", + "outer_dim": "MJ_D(nA)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "efc_AR", + "outer_dim": "MJ_D(nA)", + "stride": "1" + } + ], + "MJDATA_ARENA_POINTERS_ISLAND": [ + { + "type": "int", + "name": "tree_island", + "outer_dim": "MJ_M(ntree)", + "stride": "1" + }, + { + "type": "int", + "name": "island_ntree", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "island_itreeadr", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "map_itree2tree", + "outer_dim": "MJ_M(ntree)", + "stride": "1" + }, + { + "type": "int", + "name": "dof_island", + "outer_dim": "MJ_M(nv)", + "stride": "1" + }, + { + "type": "int", + "name": "island_nv", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "island_idofadr", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "island_dofadr", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "map_dof2idof", + "outer_dim": "MJ_M(nv)", + "stride": "1" + }, + { + "type": "int", + "name": "map_idof2dof", + "outer_dim": "MJ_M(nv)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "ifrc_smooth", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iacc_smooth", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + }, + { + "type": "int", + "name": "iM_rownnz", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + }, + { + "type": "int", + "name": "iM_rowadr", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + }, + { + "type": "int", + "name": "iM_colind", + "outer_dim": "MJ_M(nC)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iM", + "outer_dim": "MJ_M(nC)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iLD", + "outer_dim": "MJ_M(nC)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iLDiagInv", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iacc", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + }, + { + "type": "int", + "name": "efc_island", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "island_ne", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "island_nf", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "island_nefc", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "island_iefcadr", + "outer_dim": "MJ_D(nisland)", + "stride": "1" + }, + { + "type": "int", + "name": "map_efc2iefc", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "map_iefc2efc", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_type", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_id", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_J_rownnz", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_J_rowadr", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_J_rowsuper", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_J_colind", + "outer_dim": "MJ_D(nJ)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iefc_J", + "outer_dim": "MJ_D(nJ)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iefc_frictionloss", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iefc_D", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iefc_R", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iefc_aref", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "int", + "name": "iefc_state", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "iefc_force", + "outer_dim": "MJ_D(nefc)", + "stride": "1" + }, + { + "type": "mjtNum", + "name": "ifrc_constraint", + "outer_dim": "MJ_D(nidof)", + "stride": "1" + } + ], + "MJDATA_ARENA_POINTERS": [] + }, + "struct_fields": { + "MJOPTION_FIELDS": [ + { + "type": "mjtNum", + "name": "timestep", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "impratio", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "tolerance", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "ls_tolerance", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "noslip_tolerance", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "ccd_tolerance", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "sleep_tolerance", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "gravity", + "count": "3", + "is_vec": true + }, + { + "type": "mjtNum", + "name": "wind", + "count": "3", + "is_vec": true + }, + { + "type": "mjtNum", + "name": "magnetic", + "count": "3", + "is_vec": true + }, + { + "type": "mjtNum", + "name": "density", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "viscosity", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "o_margin", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "o_solref", + "count": "mjNREF", + "is_vec": true + }, + { + "type": "mjtNum", + "name": "o_solimp", + "count": "mjNIMP", + "is_vec": true + }, + { + "type": "mjtNum", + "name": "o_friction", + "count": "5", + "is_vec": true + }, + { + "type": "int", + "name": "integrator", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "cone", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "jacobian", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "solver", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "iterations", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "ls_iterations", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "noslip_iterations", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "ccd_iterations", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "disableflags", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "enableflags", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "disableactuator", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "sdf_initpoints", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "sdf_iterations", + "count": "1", + "is_vec": false + } + ], + "MJSTATISTIC_FIELDS": [ + { + "type": "mjtNum", + "name": "meaninertia", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "meanmass", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "meansize", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "extent", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "center", + "count": "3", + "is_vec": true + } + ], + "MJVISUAL_GLOBAL_FIELDS": [ + { + "type": "int", + "name": "cameraid", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "orthographic", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "fovy", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "ipd", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "azimuth", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "elevation", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "linewidth", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "glow", + "count": "1", + "is_vec": false + }, + { + "type": "float", + "name": "realtime", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "offwidth", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "offheight", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "ellipsoidinertia", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "bvactive", + "count": "1", + "is_vec": false + } + ], + "MJVISUAL_QUALITY_FIELDS": [ + { + "type": "mjtNum", + "name": "shadowsize", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "offsamples", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "numslices", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "numstacks", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "numquads", + "count": "1", + "is_vec": false + } + ], + "MJVISUAL_HEADLIGHT_FIELDS": [ + { + "type": "float", + "name": "ambient", + "count": "3", + "is_vec": true + }, + { + "type": "float", + "name": "diffuse", + "count": "3", + "is_vec": true + }, + { + "type": "float", + "name": "specular", + "count": "3", + "is_vec": true + }, + { + "type": "int", + "name": "active", + "count": "1", + "is_vec": false + } + ], + "MJVISUAL_MAP_FIELDS": [ + { + "type": "mjtNum", + "name": "stiffness", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "stiffnessrot", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "force", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "torque", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "alpha", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "fogstart", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "fogend", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "znear", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "zfar", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "haze", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "shadowclip", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "shadowscale", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "actuatortendon", + "count": "1", + "is_vec": false + } + ], + "MJVISUAL_SCALE_FIELDS": [ + { + "type": "mjtNum", + "name": "forcewidth", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "contactwidth", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "contactheight", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "connect", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "com", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "camera", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "light", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "selectpoint", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "jointlength", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "jointwidth", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "actuatorlength", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "actuatorwidth", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "framelength", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "framewidth", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "constraint", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "slidercrank", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "frustum", + "count": "1", + "is_vec": false + } + ], + "MJVISUAL_RGBA_FIELDS": [ + { + "type": "mjtNum", + "name": "fog", + "count": "1", + "is_vec": false }, { "type": "mjtNum", - "name": "o_friction", - "count": "5", - "is_vec": true + "name": "haze", + "count": "1", + "is_vec": false }, { - "type": "int", - "name": "integrator", + "type": "mjtNum", + "name": "force", "count": "1", "is_vec": false }, { - "type": "int", - "name": "cone", + "type": "mjtNum", + "name": "inertia", "count": "1", "is_vec": false }, { - "type": "int", - "name": "jacobian", + "type": "mjtNum", + "name": "joint", "count": "1", "is_vec": false }, { - "type": "int", - "name": "solver", + "type": "mjtNum", + "name": "actuator", "count": "1", "is_vec": false }, { - "type": "int", - "name": "iterations", + "type": "mjtNum", + "name": "actuatornegative", "count": "1", "is_vec": false }, { - "type": "int", - "name": "ls_iterations", + "type": "mjtNum", + "name": "actuatorpositive", "count": "1", "is_vec": false }, { - "type": "int", - "name": "noslip_iterations", + "type": "mjtNum", + "name": "com", "count": "1", "is_vec": false }, { - "type": "int", - "name": "ccd_iterations", + "type": "mjtNum", + "name": "camera", "count": "1", "is_vec": false }, { - "type": "int", - "name": "disableflags", + "type": "mjtNum", + "name": "light", "count": "1", "is_vec": false }, { - "type": "int", - "name": "enableflags", + "type": "mjtNum", + "name": "selectpoint", "count": "1", "is_vec": false }, { - "type": "int", - "name": "disableactuator", + "type": "mjtNum", + "name": "connect", "count": "1", "is_vec": false }, { - "type": "int", - "name": "sdf_initpoints", + "type": "mjtNum", + "name": "contactpoint", "count": "1", "is_vec": false }, { - "type": "int", - "name": "sdf_iterations", + "type": "mjtNum", + "name": "contactforce", "count": "1", "is_vec": false - } - ], - "MJSTATISTIC_FIELDS": [ + }, { "type": "mjtNum", - "name": "meaninertia", + "name": "contactfriction", "count": "1", "is_vec": false }, { "type": "mjtNum", - "name": "meanmass", + "name": "contacttorque", "count": "1", "is_vec": false }, { "type": "mjtNum", - "name": "meansize", + "name": "contactgap", "count": "1", "is_vec": false }, { "type": "mjtNum", - "name": "extent", + "name": "rangefinder", "count": "1", "is_vec": false }, { "type": "mjtNum", - "name": "center", + "name": "constraint", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "slidercrank", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "crankbroken", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "frustum", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "bv", + "count": "1", + "is_vec": false + }, + { + "type": "mjtNum", + "name": "bvactive", + "count": "1", + "is_vec": false + } + ], + "MJSCOMPILER_FIELDS": [ + { + "type": "mjtByte", + "name": "autolimits", + "count": "1", + "is_vec": false + }, + { + "type": "double", + "name": "boundmass", + "count": "1", + "is_vec": false + }, + { + "type": "double", + "name": "boundinertia", + "count": "1", + "is_vec": false + }, + { + "type": "double", + "name": "settotalmass", + "count": "1", + "is_vec": false + }, + { + "type": "mjtByte", + "name": "balanceinertia", + "count": "1", + "is_vec": false + }, + { + "type": "mjtByte", + "name": "fitaabb", + "count": "1", + "is_vec": false + }, + { + "type": "mjtByte", + "name": "degree", + "count": "1", + "is_vec": false + }, + { + "type": "char", + "name": "eulerseq", "count": "3", "is_vec": true + }, + { + "type": "mjtByte", + "name": "discardvisual", + "count": "1", + "is_vec": false + }, + { + "type": "mjtByte", + "name": "usethread", + "count": "1", + "is_vec": false + }, + { + "type": "mjtByte", + "name": "fusestatic", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "inertiafromgeom", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "inertiagrouprange", + "count": "2", + "is_vec": true + }, + { + "type": "mjtByte", + "name": "saveinertial", + "count": "1", + "is_vec": false + }, + { + "type": "int", + "name": "alignfree", + "count": "1", + "is_vec": false + }, + { + "type": "mjLROpt", + "name": "LRopt", + "count": "1", + "is_vec": false + }, + { + "type": "mjString*", + "name": "meshdir", + "count": "1", + "is_vec": false + }, + { + "type": "mjString*", + "name": "texturedir", + "count": "1", + "is_vec": false } ], - "MJVISUAL_GLOBAL_FIELDS": [ + "MJSPEC_FIELDS": [ + { + "type": "mjsElement*", + "name": "element", + "count": "1", + "is_vec": false + }, + { + "type": "mjString*", + "name": "modelname", + "count": "1", + "is_vec": false + }, + { + "type": "mjsCompiler", + "name": "compiler", + "count": "1", + "is_vec": false + }, + { + "type": "mjtByte", + "name": "strippath", + "count": "1", + "is_vec": false + }, + { + "type": "mjOption", + "name": "option", + "count": "1", + "is_vec": false + }, + { + "type": "mjVisual", + "name": "visual", + "count": "1", + "is_vec": false + }, + { + "type": "mjStatistic", + "name": "stat", + "count": "1", + "is_vec": false + }, + { + "type": "mjtSize", + "name": "memory", + "count": "1", + "is_vec": false + }, { "type": "int", - "name": "cameraid", + "name": "nemax", "count": "1", "is_vec": false }, { "type": "int", - "name": "orthographic", + "name": "nuserdata", "count": "1", "is_vec": false }, { - "type": "float", - "name": "fovy", + "type": "int", + "name": "nuser_body", "count": "1", "is_vec": false }, { - "type": "float", - "name": "ipd", + "type": "int", + "name": "nuser_jnt", "count": "1", "is_vec": false }, { - "type": "float", - "name": "azimuth", + "type": "int", + "name": "nuser_geom", "count": "1", "is_vec": false }, { - "type": "float", - "name": "elevation", + "type": "int", + "name": "nuser_site", "count": "1", "is_vec": false }, { - "type": "float", - "name": "linewidth", + "type": "int", + "name": "nuser_cam", "count": "1", "is_vec": false }, { - "type": "float", - "name": "glow", + "type": "int", + "name": "nuser_tendon", "count": "1", "is_vec": false }, { - "type": "float", - "name": "realtime", + "type": "int", + "name": "nuser_actuator", "count": "1", "is_vec": false }, { "type": "int", - "name": "offwidth", + "name": "nuser_sensor", "count": "1", "is_vec": false }, { "type": "int", - "name": "offheight", + "name": "nkey", "count": "1", "is_vec": false }, { "type": "int", - "name": "ellipsoidinertia", + "name": "njmax", "count": "1", "is_vec": false }, { "type": "int", - "name": "bvactive", + "name": "nconmax", "count": "1", "is_vec": false - } - ], - "MJVISUAL_QUALITY_FIELDS": [], - "MJVISUAL_HEADLIGHT_FIELDS": [ + }, { - "type": "float", - "name": "ambient", - "count": "3", - "is_vec": true + "type": "mjtSize", + "name": "nstack", + "count": "1", + "is_vec": false }, { - "type": "float", - "name": "diffuse", - "count": "3", - "is_vec": true + "type": "mjString*", + "name": "comment", + "count": "1", + "is_vec": false }, { - "type": "float", - "name": "specular", - "count": "3", - "is_vec": true + "type": "mjString*", + "name": "modelfiledir", + "count": "1", + "is_vec": false }, { - "type": "int", - "name": "active", + "type": "mjtByte", + "name": "hasImplicitPluginElem", "count": "1", "is_vec": false } - ], - "MJVISUAL_MAP_FIELDS": [], - "MJVISUAL_SCALE_FIELDS": [], - "MJVISUAL_RGBA_FIELDS": [] + ] } } \ No newline at end of file diff --git a/Scripts/codegen/sync_vendored.py b/Scripts/codegen/sync_vendored.py new file mode 100644 index 0000000..f863bec --- /dev/null +++ b/Scripts/codegen/sync_vendored.py @@ -0,0 +1,165 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Refresh vendored third-party files listed in +``Scripts/codegen/_vendored/_VENDORED_FROM.md``. + +Manifest format: GitHub-flavoured markdown table with columns +``file | upstream_url | upstream_sha | retrieved_date | license | local_dest``. +``upstream_url`` may contain ``{sha}`` which gets substituted with +``upstream_sha`` at fetch time. + +Re-running on the same SHAs produces zero diff in the manifest (the +script rewrites the table with stable column ordering + sorted-by-dest +rows, and re-stamps ``retrieved_date`` only when the fetch changed the +file content). + +Usage: + python Scripts/codegen/sync_vendored.py + [--manifest Scripts/codegen/_vendored/_VENDORED_FROM.md] + [--dry-run] (don't write anything; print what would happen) +""" + +from __future__ import annotations + +import argparse +import datetime as _dt +import hashlib +import os +import re +import sys +import urllib.request +from typing import Dict, List + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_PLUGIN_ROOT = os.path.normpath(os.path.join(_HERE, "..", "..")) +_DEFAULT_MANIFEST = os.path.join(_HERE, "_vendored", "_VENDORED_FROM.md") + + +# Markdown-table row: pipe-separated, with leading + trailing pipes +# trimmed. Comments / preamble paragraphs are ignored. +_ROW_RE = re.compile(r"^\s*\|(?P.+)\|\s*$") + + +def _parse_manifest(text: str) -> List[Dict[str, str]]: + """Return the table rows as dicts keyed by column header. Skips the + header row and the markdown separator row (``|---|---|...``).""" + rows: List[Dict[str, str]] = [] + header: List[str] = [] + for line in text.splitlines(): + m = _ROW_RE.match(line) + if not m: + continue + cols = [c.strip() for c in m.group("row").split("|")] + if not header: + header = cols + continue + if all(c.startswith("-") or c == "" for c in cols): + continue # separator + if len(cols) != len(header): + continue # malformed; ignore quietly + rows.append(dict(zip(header, cols))) + return rows + + +_COL_ORDER = ("file", "upstream_url", "upstream_sha", "retrieved_date", + "license", "local_dest") + + +def _format_manifest(rows: List[Dict[str, str]], preamble: str) -> str: + """Render the table with stable column ordering + sorted-by-dest rows.""" + rows = sorted(rows, key=lambda r: r.get("local_dest", "")) + header = " | ".join(_COL_ORDER) + sep = " | ".join("-" * max(3, len(c)) for c in _COL_ORDER) + lines = [f"| {header} |", f"| {sep} |"] + for r in rows: + cells = [r.get(c, "") for c in _COL_ORDER] + lines.append("| " + " | ".join(cells) + " |") + return preamble.rstrip() + "\n\n" + "\n".join(lines) + "\n" + + +def _extract_preamble(text: str) -> str: + """Strip everything from the first table row onward.""" + lines = text.splitlines() + out: List[str] = [] + for line in lines: + if _ROW_RE.match(line): + break + out.append(line) + return "\n".join(out) + + +def _fetch(url: str, sha: str) -> bytes: + real_url = url.replace("{sha}", sha) + print(f" GET {real_url}", file=sys.stderr) + req = urllib.request.Request(real_url, headers={"User-Agent": "urlab-sync_vendored"}) + with urllib.request.urlopen(req, timeout=30) as resp: # nosec: trusted manifest URLs + return resp.read() + + +def _maybe_write(path: str, content: bytes, dry_run: bool) -> bool: + """Returns True if the file content changed.""" + existing = None + if os.path.exists(path): + with open(path, "rb") as f: + existing = f.read() + if existing == content: + return False + if dry_run: + print(f" WOULD WRITE {path} ({len(content)} bytes)") + return True + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "wb") as f: + f.write(content) + print(f" WROTE {path} ({len(content)} bytes; sha256=" + f"{hashlib.sha256(content).hexdigest()[:12]})") + return True + + +def main(argv: List[str] | None = None) -> int: + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument("--manifest", default=_DEFAULT_MANIFEST) + ap.add_argument("--dry-run", action="store_true", + help="don't write any files; print what would happen") + args = ap.parse_args(argv) + + if not os.path.exists(args.manifest): + print(f"manifest not found: {args.manifest}", file=sys.stderr) + return 1 + + with open(args.manifest, "r", encoding="utf-8") as f: + text = f.read() + preamble = _extract_preamble(text) + rows = _parse_manifest(text) + + today = _dt.date.today().isoformat() + updated_rows: List[Dict[str, str]] = [] + for row in rows: + url = row.get("upstream_url", "") + sha = row.get("upstream_sha", "") + dest_rel = row.get("local_dest", "") + if not (url and sha and dest_rel): + print(f"skipping malformed row: {row}", file=sys.stderr) + updated_rows.append(row) + continue + try: + content = _fetch(url, sha) + except Exception as exc: # noqa: BLE001 + print(f" FAILED to fetch {url} @ {sha}: {exc}", file=sys.stderr) + updated_rows.append(row) + continue + dest_abs = os.path.join(_PLUGIN_ROOT, dest_rel.replace("/", os.sep)) + changed = _maybe_write(dest_abs, content, args.dry_run) + if changed and not args.dry_run: + row["retrieved_date"] = today + updated_rows.append(row) + + new_text = _format_manifest(updated_rows, preamble) + if new_text != text and not args.dry_run: + with open(args.manifest, "w", encoding="utf-8") as f: + f.write(new_text) + print(f"updated manifest: {args.manifest}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/Scripts/codegen/tests/conftest.py b/Scripts/codegen/tests/conftest.py index 1d55e7b..97eda15 100644 --- a/Scripts/codegen/tests/conftest.py +++ b/Scripts/codegen/tests/conftest.py @@ -24,7 +24,7 @@ @pytest.fixture(scope="session") def real_schema() -> Dict[str, Any]: """The actual MJCF schema snapshot shipped with the plugin.""" - path = os.path.join(_PLUGIN_ROOT, "Scripts", "mjcf_schema_snapshot.json") + path = os.path.join(_PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "mjcf_schema_snapshot.json") with open(path, "r", encoding="utf-8") as f: return json.load(f) @@ -38,11 +38,36 @@ def real_rules() -> Dict[str, Any]: @pytest.fixture(scope="session") def real_mjxmacro() -> Dict[str, Any]: - path = os.path.join(_PLUGIN_ROOT, "Scripts", "mjxmacro_snapshot.json") + path = os.path.join(_PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "mjxmacro_snapshot.json") with open(path, "r", encoding="utf-8") as f: return json.load(f) +@pytest.fixture(scope="session") +def real_mjspec() -> Dict[str, Any]: + """The mjspec snapshot file was retired; the runtime + now projects the introspect snapshot into the legacy mjspec shape. + The fixture mirrors that projection so tests stay isomorphic.""" + import generate_ue_components as gen + introspect_path = os.path.join( + _PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "introspect_snapshot.json", + ) + with open(introspect_path, "r", encoding="utf-8") as f: + introspect = json.load(f) + return gen._mjspec_from_introspect(introspect) + + +@pytest.fixture(autouse=True) +def _clear_diags(): + """Each test starts with a clean diagnostics buffer + strict counter. + Module-level state survives across tests otherwise — autouse keeps + drift-check tests from leaking state into one another.""" + import generate_ue_components as gen # noqa: E402, local import + gen._reset_diags() + yield + gen._reset_diags() + + @pytest.fixture def minimal_rules() -> Dict[str, Any]: """A small synthetic rules block, useful for unit-testing emission diff --git a/Scripts/codegen/tests/test_behavioral_emit_guarantees.py b/Scripts/codegen/tests/test_behavioral_emit_guarantees.py new file mode 100644 index 0000000..fc13977 --- /dev/null +++ b/Scripts/codegen/tests/test_behavioral_emit_guarantees.py @@ -0,0 +1,198 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Behavioural lock-ins for the codegen's emit surface. + +Substring-only assertions catch typos but not semantics — these tests +pin three load-bearing properties of the generated C++: + +1. XML enum roundtrip — every ``value_map`` entry produces matching + import + export arms whose XML strings and UE members agree. +2. ``mjs_setTo*`` argument order — the codegen feeds params to the + call in the exact order declared by the C signature in the + snapshot, not by rule-side iteration order. Misordered args here + would call ``mjs_setToPosition(kp_value, kv_value, ...)`` swapped + and silently miscalibrate every Position actuator. +3. Override-toggle gate — every codegen-emitted UPROPERTY pair is + ``bOverride_X`` (toggle) + ``X`` (value). Both names must agree + so the editor InlineEditConditionToggle wiring binds correctly. +""" + +from __future__ import annotations + +import os +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +if _CODEGEN_DIR not in sys.path: + sys.path.insert(0, _CODEGEN_DIR) + +import re + +import generate_ue_components as gen + + +# ---------- xml_enum roundtrip --------------------------------------------- + +def test_xml_enum_roundtrip_arms_match(real_rules): + """Every value_map entry must be reachable from both directions: + ``XML string -> UE member`` (import) and ``UE member -> XML + string`` (export). A typo in either arm would silently misimport + or misexport the attr without a compile error.""" + for elem, elem_rule in real_rules.get("element_rules", {}).items(): + for attr, enum_def in elem_rule.get("xml_enum_attrs", {}).items(): + value_map = enum_def.get("value_map") or {} + if not value_map: + continue + ue_enum_type = enum_def["ue_enum_type"] + import_cpp = gen._emit_xml_enum_import(attr, enum_def) + # Enums with no ``mjs_field`` (e.g. dcmotor.input, routed + # through mjs_setToDCMotor) emit nothing on the export side + # by design — skip the export arm in that case. + export_cpp = ( + gen._emit_xml_enum_export(attr, enum_def) + if enum_def.get("mjs_field") else "" + ) + for xml_val, mapping in value_map.items(): + ue_member = mapping[0] if isinstance(mapping, list) else mapping + # Import side mentions both XML literal and UE member. + assert f'"{xml_val}"' in import_cpp, ( + f"{elem}.{attr}: import arm missing XML literal " + f"'{xml_val}'\n{import_cpp}" + ) + assert f"{ue_enum_type}::{ue_member}" in import_cpp, ( + f"{elem}.{attr}: import arm missing " + f"{ue_enum_type}::{ue_member}\n{import_cpp}" + ) + if export_cpp: + assert f"{ue_enum_type}::{ue_member}" in export_cpp, ( + f"{elem}.{attr}: export arm missing " + f"{ue_enum_type}::{ue_member}\n{export_cpp}" + ) + + +# ---------- mjs_setTo* arg order ------------------------------------------- + +def test_setto_call_args_follow_c_signature_order(): + """The generated ``mjs_setToX(Element, a, b, c)`` call must list + args in the order declared by the C signature. Reordering by + rule-side iteration would silently swap kp/kv on actuator + subtypes.""" + rules = { + "default_type": "float", + "type_mappings": {"kp": "float", "kv": "float", "dampratio": "float"}, + "setto_param_defaults": {}, + } + mjspec = { + "setto_functions": { + "mjs_setToPosition": { + "params": [ + {"name": "kp", "c_type": "double", "array_dim": None}, + {"name": "kv", "c_type": "double", "array_dim": None}, + {"name": "dampratio", "c_type": "double", "array_dim": None}, + ], + }, + }, + } + setto_rules = {"call": "mjs_setToPosition"} + out = gen._emit_setto_call( + subtype_key="position", + setto_rules=setto_rules, + rules=rules, + mjspec=mjspec, + subtype_schema_attrs=["kp", "kv", "dampratio"], + base_schema_attrs=[], + ) + assert "mjs_setToPosition(Element" in out + # Capture the argument list and confirm kp appears before kv before + # dampratio — exact textual order in the call. + match = re.search(r"mjs_setToPosition\(Element,(.*?)\);", out, re.DOTALL) + assert match is not None, out + args_blob = match.group(1) + kp_pos = args_blob.find("(double)kp") + kv_pos = args_blob.find("(double)kv") + dampratio_pos = args_blob.find("(double)dampratio") + assert 0 < kp_pos < kv_pos < dampratio_pos, ( + f"setto args out of order: kp@{kp_pos} kv@{kv_pos} " + f"dampratio@{dampratio_pos}\n{out}" + ) + + +def test_setto_call_respects_signature_order_when_rule_lists_differently(): + """Rule-side ``param_renames`` lookup order MUST NOT influence the + emitted arg order — the C signature is the source of truth.""" + rules = { + "default_type": "float", + "type_mappings": {"PropB": "float", "PropA": "float"}, + "setto_param_defaults": {}, + } + mjspec = { + "setto_functions": { + "mjs_setToFake": { + "params": [ + {"name": "a", "c_type": "double", "array_dim": None}, + {"name": "b", "c_type": "double", "array_dim": None}, + ], + }, + }, + } + # param_renames iteration order intentionally NOT matching signature order. + setto_rules = {"call": "mjs_setToFake", + "param_renames": {"b": "PropB", "a": "PropA"}} + out = gen._emit_setto_call( + subtype_key="fake", + setto_rules=setto_rules, + rules=rules, + mjspec=mjspec, + subtype_schema_attrs=["PropA", "PropB"], + base_schema_attrs=[], + ) + match = re.search(r"mjs_setToFake\(Element,(.*?)\);", out, re.DOTALL) + assert match is not None, out + args_blob = match.group(1) + a_pos = args_blob.find("PropA") + b_pos = args_blob.find("PropB") + assert 0 < a_pos < b_pos, ( + f"renamed setto args out of signature order: A@{a_pos} B@{b_pos}\n{out}" + ) + + +# ---------- override-toggle gate ------------------------------------------- + +_UPROPERTY_PAIR_RE = re.compile( + r"bool\s+(bOverride_(\w+))\s*=\s*false;\s*\n+" + r"\s*UPROPERTY\(.*?\)\)\s*\n" + r"\s*\S+\s+(\w+)\s*=" +) + + +def test_override_toggle_name_matches_uproperty_for_all_categories(real_rules): + """For every category whose schema produces a UPROPERTY pair, the + ``bOverride_X`` toggle and the value property ``X`` must share the + same final identifier. A drift between them would still compile + but the InlineEditConditionToggle wiring in the editor would + silently dead-end.""" + schema_path = os.path.join(_CODEGEN_DIR, "snapshots", "mjcf_schema_snapshot.json") + if not os.path.exists(schema_path): + import pytest + pytest.skip("mjcf_schema.json snapshot not present") + import json + with open(schema_path, "r", encoding="utf-8") as f: + schema = json.load(f) + saw_pair = False + for cat_name, cat_rules in real_rules.get("categories", {}).items(): + attrs = gen.schema_attrs(schema, cat_rules.get("schema_common_block", "")) + if not attrs: + continue + out = gen.emit_schema_for_attrs( + attrs, real_rules, + element_name=cat_name, + category_label=cat_name, + ) + for match in _UPROPERTY_PAIR_RE.finditer(out.properties_h): + full_toggle, toggle_suffix, value_name = match.groups() + assert toggle_suffix == value_name, ( + f"category '{cat_name}': UPROPERTY pair drift — toggle " + f"'{full_toggle}' but value name is '{value_name}'" + ) + saw_pair = True + assert saw_pair, "no UPROPERTY pairs found in any category — check broken" diff --git a/Scripts/codegen/tests/test_camp_b_enum_migration.py b/Scripts/codegen/tests/test_camp_b_enum_migration.py new file mode 100644 index 0000000..f2d73a1 --- /dev/null +++ b/Scripts/codegen/tests/test_camp_b_enum_migration.py @@ -0,0 +1,188 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks the generated_enums extensions: +``extra_members`` (URLab-extra members appended after mj-derived ones) +and the ``disabled`` opt-out (skips emission so a rule can land before +the corresponding hand-rolled enums are swapped out). + +Also asserts that the Camp B rule entries shipped under +``MjArticulationEnums`` in codegen_rules.json resolve cleanly against +the current mjspec snapshot — every ``from_mj_enum`` exists and the +``ue_member_from_mj`` keys all map to real ``mjt*`` constants.""" + +from __future__ import annotations + +import os + +import generate_ue_components as gen + + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +_PLUGIN_ROOT = os.path.dirname(os.path.dirname(_CODEGEN_DIR)) + + +# ---------- extra_members -------------------------------------------------- + +def test_extra_members_append_after_mj_derived_members(): + """URLab-extra members (DcMotor on EMjGainType etc) must follow + the mj-derived block so existing member ordering doesn't change.""" + rules_def = { + "public_header": "Generated/MjT.h", + "enums": [{ + "ue_name": "EMjT", + "from_mj_enum": "mjtT", + "ue_member_from_mj": { + "mjT_A": "A", + "mjT_B": "B", + }, + "extra_members": [{"name": "DcMotor"}], + }], + } + mjspec = {"enums": {"mjtT": {"mjT_A": 0, "mjT_B": 1}}} + writes = gen._emit_generated_enum_file( + "MjArticulationEnums", rules_def, mjspec, "/tmp/public", + ) + assert len(writes) == 1 + content = writes[0].content + a_idx = content.index("A = 0") + b_idx = content.index("B = 1") + dc_idx = content.index("DcMotor = 2") + assert a_idx < b_idx < dc_idx + + +def test_extra_member_explicit_value_overrides_auto_increment(): + """``{"name": ..., "value": N}`` pins a specific underlying value + — needed for enums that mirror mjt* numbering exactly.""" + rules_def = { + "public_header": "Generated/MjT.h", + "enums": [{ + "ue_name": "EMjT", + "from_mj_enum": "mjtT", + "ue_member_from_mj": {}, + "extra_members": [ + {"name": "None", "value": 0}, + {"name": "Plane", "value": 7}, + ], + }], + } + mjspec = {"enums": {"mjtT": {"mjT_DUMMY": 0}}} + writes = gen._emit_generated_enum_file( + "MjArticulationEnums", rules_def, mjspec, "/tmp/public", + ) + assert writes + content = writes[0].content + assert "None = 0" in content + assert "Plane = 7" in content + + +def test_extra_member_without_name_fires_diagnostic(): + rules_def = { + "public_header": "Generated/MjT.h", + "enums": [{ + "ue_name": "EMjT", + "from_mj_enum": "mjtT", + "ue_member_from_mj": {"mjT_A": "A"}, + "extra_members": [{"value": 5}], # missing name + }], + } + mjspec = {"enums": {"mjtT": {"mjT_A": 0}}} + gen._emit_generated_enum_file( + "MjArticulationEnums", rules_def, mjspec, "/tmp/public", + ) + assert any("missing 'name'" in d.message for d in gen._DIAGS_BUFFER.pending) + + +# ---------- disabled opt-out ----------------------------------------------- + +def test_disabled_top_level_skips_emission(): + """``disabled: true`` at the rule entry level emits no FileWrite — + used while staging a migration so a hand-rolled enum isn't + duplicated by the codegen output.""" + rules_def = { + "disabled": True, + "public_header": "Generated/MjT.h", + "enums": [{ + "ue_name": "EMjT", + "from_mj_enum": "mjtT", + "ue_member_from_mj": {"mjT_A": "A"}, + }], + } + mjspec = {"enums": {"mjtT": {"mjT_A": 0}}} + writes = gen._emit_generated_enum_file( + "MjArticulationEnums", rules_def, mjspec, "/tmp/public", + ) + assert writes == [] + + +def test_disabled_per_entry_skips_one_enum_in_a_rule(): + """Per-entry ``disabled: true`` skips just that enum but lets the + rule's other entries still emit. Granular staging.""" + rules_def = { + "public_header": "Generated/MjT.h", + "enums": [ + { + "ue_name": "EMjEnabled", + "from_mj_enum": "mjtT", + "ue_member_from_mj": {"mjT_A": "Alpha"}, + }, + { + "ue_name": "EMjDisabled", + "disabled": True, + "from_mj_enum": "mjtT", + "ue_member_from_mj": {"mjT_A": "Beta"}, + }, + ], + } + mjspec = {"enums": {"mjtT": {"mjT_A": 0}}} + writes = gen._emit_generated_enum_file( + "MjArticulationEnums", rules_def, mjspec, "/tmp/public", + ) + assert len(writes) == 1 + content = writes[0].content + assert "EMjEnabled" in content + assert "EMjDisabled" not in content + + +# ---------- Camp B rule audit --------------------------------------------- + +def test_camp_b_rule_resolves_against_real_mjspec(real_rules, real_mjspec): + """Every Camp B entry's from_mj_enum must exist in the mjspec + snapshot, and every ue_member_from_mj key must be a real mjt* + constant. Catches typos in the migration rule before the actual + flip lands.""" + camp_b = real_rules.get("generated_enums", {}).get("MjArticulationEnums") + if not camp_b or not isinstance(camp_b, dict): + return # rule not present yet + mj_enums = real_mjspec.get("enums", {}) + for entry in camp_b.get("enums", []): + # Pure URLab enums (no mjt counterpart) omit from_mj_enum and + # rely entirely on extra_members. Skip the cross-check for those. + mj_enum_name = entry.get("from_mj_enum") + if not mj_enum_name: + continue + assert mj_enum_name in mj_enums, ( + f"Camp B '{entry['ue_name']}' -> from_mj_enum " + f"'{mj_enum_name}' not in mjspec.enums" + ) + members = mj_enums[mj_enum_name] + for mj_const in entry.get("ue_member_from_mj", {}): + assert mj_const in members, ( + f"Camp B '{entry['ue_name']}' ue_member_from_mj key " + f"'{mj_const}' is not in mjtEnum '{mj_enum_name}'" + ) + + +def test_camp_b_rule_post_flip_state(real_rules): + """After the flip, the rule no longer carries ``disabled: true`` + and the hand-rolled UENUM decls under + ``Source/URLab/Public/MuJoCo/Components/`` have been replaced + with includes of the generated header.""" + camp_b = real_rules.get("generated_enums", {}).get("MjArticulationEnums") + if not camp_b or not isinstance(camp_b, dict): + return + assert not camp_b.get("disabled"), ( + "MjArticulationEnums should be enabled after the Camp B flip." + ) + + +# On-disk presence is covered by test_regen_no_diff.py::test_codegen_check_clean. diff --git a/Scripts/codegen/tests/test_canon_emitter_bodies.py b/Scripts/codegen/tests/test_canon_emitter_bodies.py new file mode 100644 index 0000000..13b8170 --- /dev/null +++ b/Scripts/codegen/tests/test_canon_emitter_bodies.py @@ -0,0 +1,91 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Behavioural lock-ins for the canon emitter bodies that previously +only had registry-presence coverage. ``actuator_transmission`` and +``fromto_decompose`` are inline (no rule-side helper string); their +emitted C++ is hand-crafted, so any rename or signature change there +should surface in pytest rather than at UE compile.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +# ---------- actuator_transmission --------------------------------------- + +def test_actuator_transmission_import_reads_every_target_attr(): + """The import block reads joint/jointinparent/tendon/site/body and + the slidersite/refsite siblings. A missing branch means a rule + author can't author that transmission type via XML.""" + out = gen._canon_import_actuator_transmission(canon_def={}, element_name="actuator") + for attr in ("joint", "jointinparent", "tendon", "site", "body", + "slidersite", "refsite"): + assert f'TEXT("{attr}")' in out, f"import missing TEXT(\"{attr}\")" + # Each path resolves to an EMjActuatorTrnType. + for trn in ("Joint", "JointInParent", "Tendon", "Site", "Body", + "SliderCrank"): + assert f"EMjActuatorTrnType::{trn}" in out, trn + + +def test_actuator_transmission_export_emits_switch_with_undefined_default(): + out = gen._canon_export_actuator_transmission(canon_def={}) + # Every case writes Element->trntype. + for trn, mj_const in [ + ("Joint", "mjTRN_JOINT"), + ("JointInParent", "mjTRN_JOINTINPARENT"), + ("Tendon", "mjTRN_TENDON"), + ("Site", "mjTRN_SITE"), + ("Body", "mjTRN_BODY"), + ("SliderCrank", "mjTRN_SLIDERCRANK"), + ]: + assert f"EMjActuatorTrnType::{trn}" in out, trn + assert mj_const in out, mj_const + assert "default:" in out and "mjTRN_UNDEFINED" in out + # slidersite / refsite only written when their type is set. + assert "SliderCrank && !SliderSite.IsEmpty()" in out + assert "Site && !RefSite.IsEmpty()" in out + + +# ---------- fromto_decompose -------------------------------------------- + +def test_fromto_decompose_import_uses_helper_and_writes_pos_quat_size(): + canon_def = { + "import_helper": "MjUtils::DecomposeFromTo", + "category_specifics": {"geom": { + "z_slot_check": "(Type == EMjGeomType::Box || Type == EMjGeomType::Ellipsoid)" + }}, + } + out = gen._canon_import_fromto_decompose(canon_def, element_name="geom") + assert "MjUtils::DecomposeFromTo(Node, FTPos, FTQuat, FTHalf)" in out + # Writes Pos / Quat with their override toggles. + assert "Pos = FTPos;" in out and "bOverride_Pos = true;" in out + assert "Quat = FTQuat;" in out and "bOverride_Quat = true;" in out + # Uses the category-specific z_slot_check inline. + assert "EMjGeomType::Box" in out and "EMjGeomType::Ellipsoid" in out + # Grows the size array to accommodate the slot. + assert "while (size.Num() <= FTSlot)" in out + + +def test_fromto_decompose_import_falls_back_to_y_slot_for_capsule(): + canon_def = { + "import_helper": "MjUtils::DecomposeFromTo", + "category_specifics": {"site": { + "z_slot_check": "(Type == EMjSiteType::Box || Type == EMjSiteType::Ellipsoid)" + }}, + } + out = gen._canon_import_fromto_decompose(canon_def, element_name="site") + # The z_slot_check is element-specific; site uses EMjSiteType, not Geom. + assert "EMjSiteType::Box" in out + assert "EMjGeomType" not in out + # Without a matching category_specifics entry, the slot would be `false` (Y slot). + out_other = gen._canon_import_fromto_decompose( + {"import_helper": "MjUtils::DecomposeFromTo"}, + element_name="unknown", + ) + assert "bFTZSlot = false" in out_other + + +def test_fromto_decompose_export_is_empty(): + """The export path is a no-op: ``fromto`` decomposes to Pos/Quat/Size + on import; those properties carry the values through to export via + their own canonicalisations.""" + assert gen._canon_export_fromto_decompose(canon_def={}) == "" diff --git a/Scripts/codegen/tests/test_canon_registry.py b/Scripts/codegen/tests/test_canon_registry.py new file mode 100644 index 0000000..f008188 --- /dev/null +++ b/Scripts/codegen/tests/test_canon_registry.py @@ -0,0 +1,64 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the canonicalisation registry. + +The registry collapses the previous duplicated if-chains in +``_canon_import_block`` / ``_canon_export_block`` into one dict. +Adding a new canon means adding one ``Canonicalisation`` entry; an +unknown canon name in the JSON rules still fires the same loud +diagnostic instead of silently dropping its emission.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_registry_covers_every_canonicalisation_in_rules_json(real_rules): + """Every canonicalisation declared in codegen_rules.json must have + a registry entry. Mismatch fires the silent-drop diagnostic at + runtime — catch it here at test time instead.""" + declared = set(real_rules.get("canonicalizations", {}).keys()) + registered = set(gen._CANONICALISATIONS.keys()) + missing = declared - registered + assert not missing, ( + f"canonicalizations declared in rules JSON but not in the " + f"registry: {sorted(missing)}" + ) + + +def test_unknown_canon_fires_import_diagnostic(): + out = gen._canon_import_block("nonexistent_canon", {}, element_name="geom") + assert out == "" + assert any("nonexistent_canon" in d.message and "import" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_unknown_canon_fires_export_diagnostic(): + out = gen._canon_export_block("nonexistent_canon", {}) + assert out == "" + assert any("nonexistent_canon" in d.message and "export" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_spatial_pose_import_is_one_liner_helper_call(): + """Locks the trivial-shape canonicalisation so a regression in the + registry dispatch shows up directly.""" + canon_def = { + "import_helper": "MjUtils::ReadVec3InMeters", + "emits_property": {"name": "Pos", "type": "FVector"}, + } + out = gen._canon_import_block("spatial_pose", canon_def, "") + assert out.strip() == ( + 'MjUtils::ReadVec3InMeters(Node, TEXT("pos"), Pos, bOverride_Pos);' + ) + + +def test_canonicalisation_class_is_frozen(): + """Registry entries must be frozen so a phase can't accidentally + swap an emitter at runtime.""" + entry = next(iter(gen._CANONICALISATIONS.values())) + import dataclasses + assert dataclasses.is_dataclass(entry) + # FrozenInstanceError on attempted assignment. + import pytest + with pytest.raises(dataclasses.FrozenInstanceError): + entry.name = "mutated" # type: ignore[misc] diff --git a/Scripts/codegen/tests/test_canonicalization.py b/Scripts/codegen/tests/test_canonicalization.py index e52b9a4..2fe93e2 100644 --- a/Scripts/codegen/tests/test_canonicalization.py +++ b/Scripts/codegen/tests/test_canonicalization.py @@ -7,36 +7,30 @@ def test_orientation_absorbs_all_attrs(minimal_rules): + """Every orientation sibling (euler / axisangle / xyaxes / zaxis) + is absorbed into the canonical Quat UPROPERTY — none should leak + out as a standalone property.""" attrs = ["quat", "euler", "axisangle", "xyaxes", "zaxis", "size"] out = emit_schema_for_attrs(attrs, minimal_rules, "geom", "Geom") - # Raw orientation attrs do NOT appear as per-attr properties. - for raw in ("Quat ", "Euler", "Axisangle", "Xyaxes", "Zaxis"): - # The canonical "Quat" property DOES appear once. Use the trailing - # space to disambiguate from `FQuat Quat`. - pass - # Canonical Quat is emitted once. assert "FQuat Quat" in out.properties_h assert "bOverride_Quat" in out.properties_h - # No per-attr Euler etc. assert "FQuat Euler" not in out.properties_h assert "AxisAngle " not in out.properties_h assert "Xyaxes " not in out.properties_h -def test_orientation_import_uses_canonical_helper(minimal_rules): +def test_orientation_roundtrips_through_canon_helpers(minimal_rules): + """A single ``quat`` schema attr drives both arms of the canon — the + import pulls through ``MjOrientationUtils::OrientationToMjQuat`` + + ``MjToUERotation``, and the export pushes through + ``UEToMjRotation``.""" out = emit_schema_for_attrs(["quat"], minimal_rules, "geom", "Geom") - # Must invoke the canonicalisation helper, not a per-attr parser. + # Import arm. assert "MjOrientationUtils::OrientationToMjQuat(Node, CompilerSettings, TmpQuat)" in out.imports_cpp - # Must route the result through MjUtils::MjToUERotation so the UPROPERTY - # lands in UE coordinate frame (X/Z sign-flipped) plus wxyz->xyzw reorder. assert "Quat = MjUtils::MjToUERotation(TmpQuat)" in out.imports_cpp assert "bOverride_Quat = true" in out.imports_cpp - - -def test_orientation_export_uses_canonical_helper(minimal_rules): - out = emit_schema_for_attrs(["quat"], minimal_rules, "geom", "Geom") + # Export arm. assert "MjUtils::UEToMjRotation(Quat, TmpQuat)" in out.exports_cpp - # Writes to Element->quat[0..3]. assert "Element->quat[0] = TmpQuat[0]" in out.exports_cpp assert "Element->quat[3] = TmpQuat[3]" in out.exports_cpp diff --git a/Scripts/codegen/tests/test_coverage_checks.py b/Scripts/codegen/tests/test_coverage_checks.py new file mode 100644 index 0000000..099f7e0 --- /dev/null +++ b/Scripts/codegen/tests/test_coverage_checks.py @@ -0,0 +1,218 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Behavioural coverage tests for the six drift checks that previously +had no direct test — every check now has a "should fire" path and a +"should be quiet" path. Each check fires through ``_diag_add`` with a +specific ``source=`` tag so assertions can target the message bucket +without depending on prose.""" + +from __future__ import annotations + +import _codegen_checks as checks +import generate_ue_components as gen + + +def _pending_sources() -> list: + return [d.source for d in gen._DIAGS_BUFFER.pending] + + +def _reset() -> None: + gen._reset_diags() + + +# ---------- _check_top_level_elements_coverage -------------------------- + +def test_top_level_elements_coverage_fires_for_unmodeled_element(): + _reset() + schema = {"new_widget": {}, "joint": {}} + rules = { + "categories": {"joint": {"schema_common_block": "joint"}}, + "intentionally_unmodeled_elements": {}, + } + checks._check_top_level_elements_coverage(schema, rules) + assert any("new_widget" in d.message and d.source == "top_level_coverage" + for d in gen._DIAGS_BUFFER.pending) + + +def test_top_level_elements_coverage_quiet_for_documented_element(): + _reset() + schema = {"asset": {}, "joint": {}} + rules = { + "categories": {"joint": {"schema_common_block": "joint"}}, + "intentionally_unmodeled_elements": {}, + } + # 'asset' is in the container_keys allowlist. + checks._check_top_level_elements_coverage(schema, rules) + assert "top_level_coverage" not in _pending_sources() + + +# ---------- _check_actuator_subtypes_coverage -------------------------- + +def test_actuator_subtypes_coverage_fires_for_unmodeled_subtype(): + _reset() + schema = {"actuator_types": {"newkind": []}} + rules = {"categories": {"actuator": { + "subtypes": [{"key": "motor"}, {"key": "position"}], + }}} + checks._check_actuator_subtypes_coverage(schema, rules) + assert any("newkind" in d.message and d.source == "actuator_subtypes_coverage" + for d in gen._DIAGS_BUFFER.pending) + + +def test_actuator_subtypes_coverage_quiet_when_all_modeled(): + _reset() + schema = {"actuator_types": {"motor": []}} + rules = {"categories": {"actuator": { + "subtypes": [{"key": "motor"}], + }}} + checks._check_actuator_subtypes_coverage(schema, rules) + assert "actuator_subtypes_coverage" not in _pending_sources() + + +# ---------- _check_sensor_subtypes_coverage ---------------------------- + +def test_sensor_subtypes_coverage_fires_for_unmodeled_subtype(): + _reset() + schema = {"sensor_types": ["touch", "newsensor"]} + rules = {"categories": {"sensor": { + "subtypes": [{"key": "touch"}], + }}} + checks._check_sensor_subtypes_coverage(schema, rules) + assert any("newsensor" in d.message and d.source == "sensor_subtypes_coverage" + for d in gen._DIAGS_BUFFER.pending) + + +def test_sensor_subtypes_coverage_quiet_when_all_modeled(): + _reset() + schema = {"sensor_types": ["touch"]} + rules = {"categories": {"sensor": { + "subtypes": [{"key": "touch"}], + }}} + checks._check_sensor_subtypes_coverage(schema, rules) + assert "sensor_subtypes_coverage" not in _pending_sources() + + +# ---------- _check_setto_param_coverage -------------------------------- + +def test_setto_param_coverage_fires_for_unmapped_param(): + _reset() + schema = {"actuator_common": {"attrs": ["kp"]}, "actuator_types": {"position": ["kv"]}} + rules = { + "categories": {"actuator": { + "schema_common_block": "actuator_common", + "subtype_setto": {"position": {"call": "mjs_setToPosition"}}, + }}, + "setto_param_defaults": {}, + } + mjspec = {"setto_functions": {"mjs_setToPosition": { + "params": [ + {"name": "kp", "c_type": "double", "array_dim": None}, + {"name": "kv", "c_type": "double", "array_dim": None}, + {"name": "noveltie", "c_type": "double", "array_dim": None}, + ], + }}} + checks._check_setto_param_coverage(schema, rules, mjspec) + assert any("noveltie" in d.message and d.source == "setto_param_coverage" + for d in gen._DIAGS_BUFFER.pending) + + +def test_setto_param_coverage_quiet_when_all_mapped(): + _reset() + schema = {"actuator_common": {"attrs": ["kp"]}, "actuator_types": {"position": ["kv"]}} + rules = { + "categories": {"actuator": { + "schema_common_block": "actuator_common", + "subtype_setto": {"position": {"call": "mjs_setToPosition"}}, + }}, + "setto_param_defaults": {"mjs_setToPosition": {"inheritrange": "0.0"}}, + } + mjspec = {"setto_functions": {"mjs_setToPosition": { + "params": [ + {"name": "kp", "c_type": "double", "array_dim": None}, + {"name": "kv", "c_type": "double", "array_dim": None}, + {"name": "inheritrange", "c_type": "double", "array_dim": None}, + ], + }}} + checks._check_setto_param_coverage(schema, rules, mjspec) + assert "setto_param_coverage" not in _pending_sources() + + +# ---------- _check_mjs_struct_field_drift ------------------------------ + +def test_mjs_struct_field_drift_fires_for_uncovered_field(): + _reset() + schema = {"joint_common": ["stiffness"]} + rules = { + "categories": {"joint": { + "schema_common_block": "joint_common", + "mjs_struct": "mjsJoint", + }}, + "intentionally_unmodeled_mjs_fields": {}, + } + mjspec = {"structs": {"mjsJoint": ["stiffness", "mystery_field"]}} + checks._check_mjs_struct_field_drift(schema, rules, mjspec) + assert any("mystery_field" in d.message and d.source == "mjs_field_drift" + for d in gen._DIAGS_BUFFER.pending) + + +def test_mjs_struct_field_drift_quiet_when_all_modeled(): + _reset() + schema = {"joint_common": ["stiffness"]} + rules = { + "categories": {"joint": { + "schema_common_block": "joint_common", + "mjs_struct": "mjsJoint", + }}, + "intentionally_unmodeled_mjs_fields": {}, + } + mjspec = {"structs": {"mjsJoint": ["stiffness", "name"]}} # 'name' is structural + checks._check_mjs_struct_field_drift(schema, rules, mjspec) + assert "mjs_field_drift" not in _pending_sources() + + +# ---------- _check_generated_enum_coverage ----------------------------- + +def test_generated_enum_coverage_fires_for_unmapped_member(): + _reset() + rules = {"generated_enums": {"MjOptionEnums": { + "enums": [{ + "ue_name": "EMjIntegrator", + "from_mj_enum": "mjtIntegrator", + "ue_member_from_mj": {"mjINT_EULER": "Euler"}, + # mjINT_RK4 missing from the rule -> should diag. + }], + }}} + mjspec = {"enums": {"mjtIntegrator": {"mjINT_EULER": 0, "mjINT_RK4": 1}}} + checks._check_generated_enum_coverage(rules, mjspec) + assert any("mjINT_RK4" in d.message and d.source == "enum_drift" + for d in gen._DIAGS_BUFFER.pending) + + +def test_generated_enum_coverage_quiet_when_all_mapped(): + _reset() + rules = {"generated_enums": {"MjOptionEnums": { + "enums": [{ + "ue_name": "EMjIntegrator", + "from_mj_enum": "mjtIntegrator", + "ue_member_from_mj": {"mjINT_EULER": "Euler", "mjINT_RK4": "RK4"}, + }], + }}} + mjspec = {"enums": {"mjtIntegrator": {"mjINT_EULER": 0, "mjINT_RK4": 1}}} + checks._check_generated_enum_coverage(rules, mjspec) + assert "enum_drift" not in _pending_sources() + + +def test_generated_enum_coverage_fires_when_from_mj_enum_unknown(): + """Snapshot drift: a from_mj_enum that's not in the projected + mjspec must produce a diagnostic instead of a silent skip.""" + _reset() + rules = {"generated_enums": {"MjOptionEnums": { + "enums": [{ + "ue_name": "EMjGone", + "from_mj_enum": "mjtGoneRenamed", + "ue_member_from_mj": {"mjGONE_X": "X"}, + }], + }}} + mjspec = {"enums": {"mjtIntegrator": {"mjINT_EULER": 0}}} + checks._check_generated_enum_coverage(rules, mjspec) + assert any("mjtGoneRenamed" in d.message and d.source == "enum_drift" + for d in gen._DIAGS_BUFFER.pending) diff --git a/Scripts/codegen/tests/test_dry_run.py b/Scripts/codegen/tests/test_dry_run.py index 3f1eb7b..8a05fcb 100644 --- a/Scripts/codegen/tests/test_dry_run.py +++ b/Scripts/codegen/tests/test_dry_run.py @@ -15,12 +15,6 @@ _PLUGIN_ROOT = os.path.abspath(os.path.join(_HERE, "..", "..", "..")) -@pytest.fixture(scope="session") -def real_mjspec(): - with open(os.path.join(_PLUGIN_ROOT, "Scripts", "mjspec_snapshot.json"), "r") as f: - return json.load(f) - - def test_collect_all_writes_includes_expected_categories(real_schema, real_rules, real_mjxmacro, real_mjspec): from generate_ue_components import collect_all_writes # The plugin's actual Public/Private roots (read-only — we don't write). diff --git a/Scripts/codegen/tests/test_emit_enum_switch.py b/Scripts/codegen/tests/test_emit_enum_switch.py new file mode 100644 index 0000000..34da527 --- /dev/null +++ b/Scripts/codegen/tests/test_emit_enum_switch.py @@ -0,0 +1,110 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the ``emit_enum_switch`` codegen helper. + +The helper backs three sites: xml_enum exports (single-line cases + +``default: break;``), objtype dispatch (multi-key groups + multi-line +default), and geom FinalType resolution (single-line cases, no +default). Each shape is locked here so a future tweak to the helper +can't silently break byte-identity on the emitted .cpp.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_single_line_case_shape_matches_xml_enum_export(): + """Single ``str`` member → one-line ``case Enum::M: ; break;`` + — the shape every xml_enum_export emits.""" + out = gen.emit_enum_switch( + "JointType", "EMjJointType", + [ + ("Hinge", "Element->type = (mjtJoint)mjJNT_HINGE"), + ("Slide", "Element->type = (mjtJoint)mjJNT_SLIDE"), + ], + indent=" ", + default_break=True, + ) + expected = ( + " switch (JointType)\n" + " {\n" + " case EMjJointType::Hinge: Element->type = (mjtJoint)mjJNT_HINGE; break;\n" + " case EMjJointType::Slide: Element->type = (mjtJoint)mjJNT_SLIDE; break;\n" + " default: break;\n" + " }\n" + ) + assert out == expected + + +def test_multi_key_group_stacks_labels_with_multiline_body(): + """A list-of-strings member stacks case labels and emits body + + break on indented separate lines — the shape objtype_dispatch + needs for ``case Body:`` / ``case XBody:`` collapsing to one expr.""" + out = gen.emit_enum_switch( + "ObjType", "EMjObjType", + [ + (["Body", "XBody"], "Target = mjOBJ_BODY"), + ("Geom", "Target = mjOBJ_GEOM"), + ], + indent=" ", + default_body="Target = mjOBJ_UNKNOWN", + ) + expected = ( + " switch (ObjType)\n" + " {\n" + " case EMjObjType::Body:\n" + " case EMjObjType::XBody:\n" + " Target = mjOBJ_BODY;\n" + " break;\n" + " case EMjObjType::Geom: Target = mjOBJ_GEOM; break;\n" + " default:\n" + " Target = mjOBJ_UNKNOWN;\n" + " break;\n" + " }\n" + ) + assert out == expected + + +def test_no_default_when_neither_flag_set(): + """geom_final_type emits no default branch — the helper must + omit it cleanly.""" + out = gen.emit_enum_switch( + "Type", "EMjGeomType", + [("Sphere", "FinalType = mjGEOM_SPHERE")], + indent=" ", + ) + expected = ( + " switch (Type)\n" + " {\n" + " case EMjGeomType::Sphere: FinalType = mjGEOM_SPHERE; break;\n" + " }\n" + ) + assert out == expected + + +def test_default_body_takes_priority_over_default_break(): + """When both are set, the multi-line default wins. Keeps caller + intent obvious — ``default_break`` is the simple short-form.""" + out = gen.emit_enum_switch( + "X", "EMjX", + [("A", "y = 1")], + default_break=True, + default_body="y = 0", + ) + assert "default:\n" in out + assert "default: break;" not in out + + +def test_indent_propagates_to_case_labels_and_body(): + """Case labels sit at ``indent + 4 spaces``; multi-line case bodies + at ``indent + 8 spaces``. The lock prevents indentation drift.""" + out = gen.emit_enum_switch( + "X", "EMjX", + [(["A", "B"], "z = 1")], + indent=" ", # 12 spaces + ) + # switch line at 12 spaces. + assert out.startswith(" switch (X)\n") + # case labels at 12 + 4 = 16 spaces. + assert " case EMjX::A:\n" in out + # body at 12 + 8 = 20 spaces. + assert " z = 1;\n" in out diff --git a/Scripts/codegen/tests/test_emit_property.py b/Scripts/codegen/tests/test_emit_property.py index f636790..3b66f3d 100644 --- a/Scripts/codegen/tests/test_emit_property.py +++ b/Scripts/codegen/tests/test_emit_property.py @@ -8,22 +8,12 @@ from generate_ue_components import ( EmittedSchema, emit_schema_for_attrs, - pascal_case, - override_toggle_name, ) -def test_schema_verbatim_name(): - """Codegen uses MuJoCo schema names AS-IS (no PascalCase, no renames).""" - assert pascal_case("limited") == "limited" - assert pascal_case("ctrlrange") == "ctrlrange" - assert pascal_case("solreflimit") == "solreflimit" - assert pascal_case("springref") == "springref" - - -def test_override_toggle_name(): - assert override_toggle_name("limited") == "bOverride_limited" - assert override_toggle_name("ctrlrange") == "bOverride_ctrlrange" +# override_toggle_name is exercised everywhere emit_schema_for_attrs runs; +# the cross-category guarantee is pinned in +# test_behavioral_emit_guarantees::test_override_toggle_name_matches_uproperty_for_all_categories. def test_emit_basic_property(minimal_rules): diff --git a/Scripts/codegen/tests/test_emitter_capabilities.py b/Scripts/codegen/tests/test_emitter_capabilities.py new file mode 100644 index 0000000..24d8515 --- /dev/null +++ b/Scripts/codegen/tests/test_emitter_capabilities.py @@ -0,0 +1,106 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Tests for opt-in emitter capabilities in generate_ue_components.py: + +1. ``_resolve_value_map``: returns the rule's literal ``value_map``; + missing ``value_map`` raises. +2. ``xml_enum_attrs.emit_property_decl: true``: codegen emits the UE + enum UPROPERTY decl into the schema PROPERTIES block. + +Each test uses synthetic rules to exercise its capability in isolation. +""" + +from __future__ import annotations + +import os +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +if _CODEGEN_DIR not in sys.path: + sys.path.insert(0, _CODEGEN_DIR) + +import pytest # noqa: E402 + +from generate_ue_components import ( # noqa: E402 + _resolve_value_map, + _emit_xml_enum_import, + emit_schema_for_attrs, +) + + +# ----- value_map resolver ---------------------------------------------- + +def test_value_map_returned_verbatim(): + """The resolver returns the rule's literal ``value_map`` unchanged.""" + enum_def = { + "ue_property": "Type", + "ue_enum_type": "EMjJointType", + "value_map": {"hinge": ["Hinge", "mjJNT_HINGE"]}, + } + resolved = _resolve_value_map("type", enum_def) + assert resolved == {"hinge": ["Hinge", "mjJNT_HINGE"]} + + +def test_value_map_resolver_errors_when_missing(): + enum_def = {"ue_property": "X", "ue_enum_type": "E"} + with pytest.raises(RuntimeError, match="missing value_map"): + _resolve_value_map("attr", enum_def) + + +def test_xml_enum_import_emits_expected_blocks(): + enum_def = { + "ue_property": "Type", + "ue_enum_type": "EMjJointType", + "value_map": {"hinge": ["Hinge", "mjJNT_HINGE"], "slide": ["Slide", "mjJNT_SLIDE"]}, + } + out = _emit_xml_enum_import("type", enum_def) + assert "Type = EMjJointType::Hinge" in out + assert "Type = EMjJointType::Slide" in out + assert "bOverride_Type = true" in out + + +# ----- emit_property_decl opt-in --------------------------------------- + +def test_emit_property_decl_off_skips_uproperty(): + """Default behaviour: xml_enum_attrs entries do NOT emit the UE + UPROPERTY decl (the .h hand-declares it).""" + rules = { + "element_rules": { + "joint": { + "xml_enum_attrs": { + "type": { + "ue_property": "Type", + "ue_enum_type": "EMjJointType", + "value_map": {"hinge": ["Hinge", "mjJNT_HINGE"]}, + } + } + } + } + } + out = emit_schema_for_attrs([], rules, element_name="joint", category_label="Joint") + assert "EMjJointType" not in out.properties_h + + +def test_emit_property_decl_on_emits_uproperty_pair(): + """With opt-in, codegen emits both the override toggle and the + EMjX UPROPERTY using the standard _emit_uproperty shape.""" + rules = { + "element_rules": { + "joint": { + "xml_enum_attrs": { + "type": { + "ue_property": "Type", + "ue_enum_type": "EMjJointType", + "emit_property_decl": True, + "value_map": {"hinge": ["Hinge", "mjJNT_HINGE"]}, + } + } + } + } + } + out = emit_schema_for_attrs([], rules, element_name="joint", category_label="Joint") + assert "EMjJointType Type" in out.properties_h + assert "bOverride_Type" in out.properties_h + + diff --git a/Scripts/codegen/tests/test_enum_scrape.py b/Scripts/codegen/tests/test_enum_scrape.py new file mode 100644 index 0000000..c405501 --- /dev/null +++ b/Scripts/codegen/tests/test_enum_scrape.py @@ -0,0 +1,53 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the mjt* enum surface the codegen consumes. + +mjt* enums come from the clang-AST introspect snapshot — libclang +gives us the real member values and handles every ``typedef enum +mjtX_ { ... } mjtX;`` shape uniformly. The shipped snapshot has to +carry every enum the codegen rules reference; the cross-check below +is the guard.""" + +from __future__ import annotations + +import json +import os +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +if _CODEGEN_DIR not in sys.path: + sys.path.insert(0, _CODEGEN_DIR) + + +def _load_projected_mjspec(): + """Load introspect + project into the legacy mjspec shape via the + same helper the runtime uses. Mirrors the conftest fixture.""" + import generate_ue_components as gen + plugin_root = os.path.normpath(os.path.join(_HERE, "..", "..", "..")) + snap_path = os.path.join( + plugin_root, "Scripts", "codegen", "snapshots", + "introspect_snapshot.json", + ) + with open(snap_path, "r", encoding="utf-8") as f: + introspect = json.load(f) + return gen._mjspec_from_introspect(introspect) + + +def test_real_snapshot_has_expected_enums(): + """Introspect must carry every mjt* enum the codegen rules drift + checks rely on (the cross-walk between value_map entries and the + enum members the snapshot reports for that mjt* type).""" + mjspec = _load_projected_mjspec() + enums = mjspec.get("enums", {}) + for expected in ( + "mjtJoint", # joint.type + "mjtGeom", # geom.type + "mjtSensor", # sensor types + "mjtObj", # objtype / reftype + "mjtTrn", # actuator transmission + "mjtIntegrator", # mjOption.integrator + "mjtCone", # mjOption.cone + "mjtSolver", # mjOption.solver + ): + assert expected in enums, f"missing enum {expected} from snapshot" + assert len(enums[expected]) > 0, f"enum {expected} has no members" diff --git a/Scripts/codegen/tests/test_expand_stride_guard.py b/Scripts/codegen/tests/test_expand_stride_guard.py new file mode 100644 index 0000000..58d156d --- /dev/null +++ b/Scripts/codegen/tests/test_expand_stride_guard.py @@ -0,0 +1,54 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks the ``_expand_stride`` guard. ``MJ_M(...)`` lowers to +``m->...``; numeric and ``mjN*`` strides pass through unchanged. Any +``MJ_*( ... )`` macro that survives is an unhandled shape and must +surface a diagnostic before the generated MjBind.h fails to compile.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_mj_m_macro_lowers_to_pointer_field(): + assert gen._expand_stride("MJ_M(nuser_jnt)") == "m->nuser_jnt" + + +def test_numeric_stride_passes_through_unchanged(): + for s in ("1", "3", "9"): + assert gen._expand_stride(s) == s + + +def test_mj_n_constant_passes_through_unchanged(): + assert gen._expand_stride("mjNREF") == "mjNREF" + assert gen._expand_stride("mjNBIAS") == "mjNBIAS" + + +def test_compound_expression_expands_and_keeps_other_tokens(): + """Real MuJoCo strides occasionally combine ``MJ_M(...)*N`` for + derived per-element block sizes. The guard must NOT fire because + the substitution removes the only MJ_ macro.""" + assert gen._expand_stride("MJ_M(nuser_geom)*3") == "m->nuser_geom*3" + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_unknown_macro_fires_guard_diagnostic(): + """A future MuJoCo bump that introduces e.g. ``MJ_D(foo)`` must + not silently land verbatim in MjBind.h.""" + out = gen._expand_stride("MJ_D(foo)") + assert "MJ_D(foo)" in out + assert any("unhandled MuJoCo macro" in d.message and "MJ_D(foo)" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_multiple_unknown_macros_listed_together(): + gen._expand_stride("MJ_D(a) + MJ_V(b)") + diags = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("MJ_D(a)" in m and "MJ_V(b)" in m for m in diags), diags + + +def test_known_and_unknown_mixed_still_fires_for_unknown(): + """Known macro expanded, unknown surfaces a diag.""" + out = gen._expand_stride("MJ_M(nuser_jnt) * MJ_D(foo)") + assert "m->nuser_jnt" in out + assert "MJ_D(foo)" in out + assert any("MJ_D(foo)" in d.message for d in gen._DIAGS_BUFFER.pending) diff --git a/Scripts/codegen/tests/test_find_matching_brace.py b/Scripts/codegen/tests/test_find_matching_brace.py new file mode 100644 index 0000000..61c2e70 --- /dev/null +++ b/Scripts/codegen/tests/test_find_matching_brace.py @@ -0,0 +1,80 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks ``_find_matching_brace`` — the brace-aware extractor that +backs the banner-overwrite audit. The previous ``\\{([^}]*)\\}`` regex +truncated at the first inner ``}``, silently underreporting extra ctor +content when a real ctor body contained a range-for loop or nested +if. The extractor must track string literals and comments so a ``{`` +inside ``TEXT("...")`` does not shift the depth count.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_finds_simple_matching_brace(): + text = "x { hello } y" + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + assert close_idx is not None + assert text[close_idx] == "}" + assert text[open_idx + 1:close_idx] == " hello " + + +def test_handles_nested_braces(): + text = "ctor() { if (x) { do(); } else { other(); } }" + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + # close_idx must be the FINAL '}', not the first inner one. + assert close_idx == len(text) - 1 + + +def test_ignores_braces_in_string_literal(): + text = 'fn() { Print(TEXT("{nested}")); }' + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + # The string contains '{' and '}' but they must NOT change depth; + # the matcher should land on the final outer '}'. + assert close_idx == len(text) - 1 + + +def test_ignores_braces_in_char_literal(): + text = "fn() { char c = '{'; print(c); }" + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + assert close_idx == len(text) - 1 + + +def test_ignores_braces_in_line_comment(): + text = "fn() { // tail {\n real(); }" + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + assert close_idx == len(text) - 1 + + +def test_ignores_braces_in_block_comment(): + text = "fn() { /* tail { in comment */ real(); }" + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + assert close_idx == len(text) - 1 + + +def test_returns_none_for_unmatched_open(): + """If the input is malformed (open without a matching close), the + helper returns None — caller decides whether that's a diag or a + silent skip.""" + assert gen._find_matching_brace("fn() { unclosed", 5) is None + + +def test_returns_none_when_index_is_not_open_brace(): + assert gen._find_matching_brace("x }", 1) is None + assert gen._find_matching_brace("x", 5) is None # off-end + + +def test_escape_sequences_in_string_dont_terminate_early(): + """A ``\\"`` inside a string literal must not close the string + early — the matcher would otherwise re-enter brace-counting mode + inside the literal and mis-count.""" + text = r'fn() { print("a\"b{c"); real(); }' + open_idx = text.index("{") + close_idx = gen._find_matching_brace(text, open_idx) + assert close_idx == len(text) - 1 diff --git a/Scripts/codegen/tests/test_geom_final_type.py b/Scripts/codegen/tests/test_geom_final_type.py new file mode 100644 index 0000000..b0f40af --- /dev/null +++ b/Scripts/codegen/tests/test_geom_final_type.py @@ -0,0 +1,85 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the ``geom_final_type`` rule shape — resolves an mjsGeom +type at compile time + emits the mesh-name export under the right +EMjGeomType condition.""" + +from __future__ import annotations + +import generate_ue_components as gen +from generate_ue_components import _emit_geom_final_type_block + + +def _geom_value_map_rules(): + """Minimal cat/element rules that exercise the FinalType switch.""" + cat_rules = { + "geom_final_type": { + "xml_enum_ref": "type", + "override_field": "bOverride_Type", + "default_lookup": "Default->Type", + "default_fallback": "mjGEOM_SPHERE", + "name_export_for": "mjGEOM_MESH", + "name_field": "MeshName", + "name_setter": "Element->meshname.assign", + "name_target": "*Element", + }, + } + element_rules = { + "xml_enum_attrs": { + "type": { + "ue_property": "Type", + "ue_enum": "EMjGeomType", + "ue_enum_type": "EMjGeomType", + "override_toggle": "bOverride_Type", + "default_lookup": "Default->Type", + "value_map": { + "sphere": ["Sphere", "mjGEOM_SPHERE"], + "box": ["Box", "mjGEOM_BOX"], + "mesh": ["Mesh", "mjGEOM_MESH"], + }, + }, + }, + } + return cat_rules, element_rules + + +def test_geom_final_type_emits_full_block(): + cat_rules, element_rules = _geom_value_map_rules() + out = _emit_geom_final_type_block(cat_rules, element_rules) + assert out is not None + assert "FinalType" in out + assert "case EMjGeomType::Sphere: FinalType = mjGEOM_SPHERE;" in out + assert "case EMjGeomType::Box: FinalType = mjGEOM_BOX;" in out + assert "case EMjGeomType::Mesh: FinalType = mjGEOM_MESH;" in out + assert "MeshName" in out + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_geom_final_type_returns_none_when_no_rule(): + assert _emit_geom_final_type_block({}, {}) is None + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_geom_final_type_diagnoses_missing_enum_def(): + cat_rules = { + "geom_final_type": { + "xml_enum_ref": "nonexistent", + "default_fallback": "mjGEOM_SPHERE", + "first_mj_const_token": "mjGEOM_PLANE", + "name_for": "mjGEOM_MESH", + "name_field": "MeshName", + "name_setter": "Element->meshname.assign", + "name_target": "*Element", + }, + } + out = _emit_geom_final_type_block(cat_rules, {"xml_enum_attrs": {}}) + assert out is None + assert any("nonexistent" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_geom_final_type_diagnoses_empty_value_map(): + cat_rules, element_rules = _geom_value_map_rules() + # Wipe out the value_map and provide no mjspec to fall back to. + element_rules["xml_enum_attrs"]["type"]["value_map"] = {} + out = _emit_geom_final_type_block(cat_rules, element_rules) + assert out is None + assert any("empty value_map" in d.message for d in gen._DIAGS_BUFFER.pending) diff --git a/Scripts/codegen/tests/test_hand_enum_drift.py b/Scripts/codegen/tests/test_hand_enum_drift.py new file mode 100644 index 0000000..9c8d168 --- /dev/null +++ b/Scripts/codegen/tests/test_hand_enum_drift.py @@ -0,0 +1,234 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the hand-enum drift checks: ``_scan_hand_enums`` scrapes +URLab ``EMj*`` enum members from Source/, and ``_check_hand_enum_drift`` +cross-references them against MuJoCo's ``mjt*`` enums and the rules' +``value_map`` UE-member references.""" + +from __future__ import annotations + +import generate_ue_components as gen +import _codegen_checks as _checks +gen._scan_hand_enums = _checks._scan_hand_enums + + +def _write_enum_header(tmp_path, filename: str, enum_text: str): + p = tmp_path / filename + p.write_text(enum_text, encoding="utf-8") + return p + + +# ---------- _scan_hand_enums ----------------------------------------------- + +def test_scan_hand_enums_parses_umeta_members(tmp_path): + """UMETA(DisplayName=...) on each member must NOT hide the member + from the scanner (was the original parser bug — EMjCameraTrackingMode + lost TrackCom and TargetBodyCom because the per-line regex required + the line to end at the member).""" + _write_enum_header(tmp_path, "Sample.h", """ + UENUM(BlueprintType) + enum class EMjSample : uint8 + { + Fixed UMETA(DisplayName = "Fixed"), + Track UMETA(DisplayName = "Track"), + TrackCom UMETA(DisplayName = "Track (Centre of Mass)"), + TargetBody UMETA(DisplayName = "Target Body"), + TargetBodyCom UMETA(DisplayName = "Target Body (Centre of Mass)"), + }; + """) + enums = gen._scan_hand_enums(str(tmp_path)) + assert "EMjSample" in enums + assert enums["EMjSample"] == [ + "Fixed", "Track", "TrackCom", "TargetBody", "TargetBodyCom", + ] + + +def test_scan_hand_enums_handles_explicit_values(tmp_path): + """Explicit ``= N`` initialisers must not break member capture.""" + _write_enum_header(tmp_path, "WithVals.h", """ + enum class EMjWithVals : uint8 + { + Connect = 0, + Weld = 1, + Joint = 2, + }; + """) + enums = gen._scan_hand_enums(str(tmp_path)) + assert enums["EMjWithVals"] == ["Connect", "Weld", "Joint"] + + +# ---------- _check_hand_enum_drift ----------------------------------------- + +def test_hand_enum_drift_diagnoses_subtype_enum_value_typo(tmp_path): + _write_enum_header(tmp_path, "MjJoint.h", """ + enum class EMjJointType : uint8 { Hinge, Slide, Ball }; + """) + rules = { + "categories": { + "joint": { + "type_enum_name": "EMjJointType", + "subtypes": [ + {"key": "hinge", "enum_value": "Hinge"}, + {"key": "screw", "enum_value": "Screwd"}, # typo + ], + }, + }, + } + gen._check_hand_enum_drift({}, rules, None, str(tmp_path)) + assert any("Screwd" in d.message and "EMjJointType" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_hand_enum_drift_diagnoses_value_map_ue_member_typo(tmp_path): + _write_enum_header(tmp_path, "MjGeom.h", """ + enum class EMjGeomType : uint8 { Sphere, Box, Mesh }; + """) + rules = { + "categories": {}, + "element_rules": { + "geom": { + "xml_enum_attrs": { + "type": { + "ue_enum_type": "EMjGeomType", + "value_map": { + "sphere": ["Sphere", "mjGEOM_SPHERE"], + "box": ["Bxox", "mjGEOM_BOX"], # typo + }, + }, + }, + }, + }, + } + gen._check_hand_enum_drift({}, rules, None, str(tmp_path)) + assert any("Bxox" in d.message and "EMjGeomType" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_hand_enum_drift_surfaces_new_mj_enum_value(tmp_path): + """A new mjJNT_SCREW upstream with no value_map entry fires a + diagnostic — closes the silent-runtime-fallthrough class.""" + _write_enum_header(tmp_path, "MjJoint.h", """ + enum class EMjJointType : uint8 { Hinge, Slide, Ball }; + """) + rules = { + "categories": {}, + "element_rules": { + "joint": { + "xml_enum_attrs": { + "type": { + "ue_enum_type": "EMjJointType", + "mjs_cast": "mjtJoint", + "value_map": { + "hinge": ["Hinge", "mjJNT_HINGE"], + "slide": ["Slide", "mjJNT_SLIDE"], + "ball": ["Ball", "mjJNT_BALL"], + }, + }, + }, + }, + }, + } + mjspec = { + "enums": { + "mjtJoint": ["mjJNT_FREE", "mjJNT_BALL", "mjJNT_SLIDE", + "mjJNT_HINGE", "mjJNT_SCREW"], + }, + } + gen._check_hand_enum_drift({}, rules, mjspec, str(tmp_path)) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("mjJNT_SCREW" in m for m in msgs), msgs + assert any("mjJNT_FREE" in m for m in msgs), msgs + + +def test_hand_enum_drift_respects_intentional_skips(tmp_path): + _write_enum_header(tmp_path, "MjActuator.h", """ + enum class EMjGainType : uint8 { Fixed, Affine, Muscle }; + """) + rules = { + "categories": {}, + "intentionally_unmapped_mj_enum_values": { + "mjtGain": ["mjGAIN_DCMOTOR"], + }, + "element_rules": { + "actuator": { + "xml_enum_attrs": { + "gaintype": { + "ue_enum_type": "EMjGainType", + "mjs_cast": "mjtGain", + "value_map": { + "fixed": ["Fixed", "mjGAIN_FIXED"], + "affine": ["Affine", "mjGAIN_AFFINE"], + "muscle": ["Muscle", "mjGAIN_MUSCLE"], + }, + }, + }, + }, + }, + } + mjspec = { + "enums": { + "mjtGain": ["mjGAIN_FIXED", "mjGAIN_AFFINE", "mjGAIN_MUSCLE", + "mjGAIN_USER", "mjGAIN_DCMOTOR"], + }, + } + gen._check_hand_enum_drift({}, rules, mjspec, str(tmp_path)) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + # DCMOTOR is in the skip list -> no diag. + assert not any("mjGAIN_DCMOTOR" in m for m in msgs) + # USER is not -> diag fires. + assert any("mjGAIN_USER" in m for m in msgs), msgs + + +def test_hand_enum_drift_per_element_overrides(tmp_path): + """Same mjt* enum (mjtGeom) admits different subsets for geom vs + site. The __per_element__ override must scope correctly.""" + _write_enum_header(tmp_path, "MjGeom.h", """ + enum class EMjGeomType : uint8 { Sphere, Box, Plane, Mesh }; + """) + _write_enum_header(tmp_path, "MjSite.h", """ + enum class EMjSiteType : uint8 { Sphere, Box }; + """) + rules = { + "categories": {}, + "intentionally_unmapped_mj_enum_values": { + "__per_element__": { + "site.type": ["mjGEOM_PLANE", "mjGEOM_MESH"], + }, + }, + "element_rules": { + "geom": { + "xml_enum_attrs": { + "type": { + "ue_enum_type": "EMjGeomType", + "mjs_cast": "mjtGeom", + "value_map": { + "sphere": ["Sphere", "mjGEOM_SPHERE"], + "box": ["Box", "mjGEOM_BOX"], + "plane": ["Plane", "mjGEOM_PLANE"], + "mesh": ["Mesh", "mjGEOM_MESH"], + }, + }, + }, + }, + "site": { + "xml_enum_attrs": { + "type": { + "ue_enum_type": "EMjSiteType", + "mjs_cast": "mjtGeom", + "value_map": { + "sphere": ["Sphere", "mjGEOM_SPHERE"], + "box": ["Box", "mjGEOM_BOX"], + }, + }, + }, + }, + }, + } + mjspec = {"enums": {"mjtGeom": ["mjGEOM_SPHERE", "mjGEOM_BOX", + "mjGEOM_PLANE", "mjGEOM_MESH"]}} + gen._check_hand_enum_drift({}, rules, mjspec, str(tmp_path)) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + # Geom has all 4 mapped -> no diag. + assert not any("element 'geom'" in m for m in msgs) + # Site skips Plane + Mesh -> no diag for those either. + assert not any("mjGEOM_PLANE" in m and "site" in m for m in msgs) + assert not any("mjGEOM_MESH" in m and "site" in m for m in msgs) diff --git a/Scripts/codegen/tests/test_inject_helpers.py b/Scripts/codegen/tests/test_inject_helpers.py new file mode 100644 index 0000000..adfc451 --- /dev/null +++ b/Scripts/codegen/tests/test_inject_helpers.py @@ -0,0 +1,97 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the codegen's inject-guard layer: ``_audit_banner_safety`` +on ``fully_emitted`` overwrites, layout dispatcher fall-through, +and canonicalisation dispatch on unknown canon names.""" + +from __future__ import annotations + +import generate_ue_components as gen +from generate_ue_components import _audit_banner_safety + + +# ---------- banner-safety audit --------------------------------------------- + +def test_audit_banner_safety_silent_on_template_only(tmp_path): + """A subclass file containing only its own header include and a + bare ``Type = ...`` constructor should not trigger a diagnostic.""" + p = tmp_path / "MjBoxGeom.cpp" + p.write_text( + '#include "MuJoCo/Components/Geometry/MjBoxGeom.h"\n' + "UMjBoxGeom::UMjBoxGeom()\n" + "{\n" + " Type = EMjGeomType::Box;\n" + "}\n", + encoding="utf-8", + ) + subtype = {"class_name": "UMjBoxGeom"} + _audit_banner_safety(str(p), subtype) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_audit_banner_safety_flags_extra_include(tmp_path): + """An extra non-template #include in a soon-to-be-overwritten file + triggers a diagnostic so the rule author knows hand-rolled content + will be discarded.""" + p = tmp_path / "MjBoxGeom.cpp" + p.write_text( + '#include "MuJoCo/Components/Geometry/MjBoxGeom.h"\n' + '#include "SomeOther/Header.h"\n' + "UMjBoxGeom::UMjBoxGeom()\n" + "{\n" + " Type = EMjGeomType::Box;\n" + "}\n", + encoding="utf-8", + ) + subtype = {"class_name": "UMjBoxGeom"} + _audit_banner_safety(str(p), subtype) + assert any("SomeOther/Header.h" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_audit_banner_safety_flags_extra_ctor_body(tmp_path): + """Constructor body content beyond ``Type = EMj...::X`` and the + rule-provided ``extra_constructor`` is flagged — that's where the + joint-subtype bOverride_Type bug came from.""" + p = tmp_path / "MjHingeJoint.cpp" + p.write_text( + '#include "MuJoCo/Components/Joints/MjHingeJoint.h"\n' + "UMjHingeJoint::UMjHingeJoint()\n" + "{\n" + " Type = EMjJointType::Hinge;\n" + " HandRolledHelperCall();\n" + "}\n", + encoding="utf-8", + ) + subtype = { + "class_name": "UMjHingeJoint", + "extra_constructor": "", + } + _audit_banner_safety(str(p), subtype) + assert any("non-template ctor content" in d.message + and "HandRolledHelperCall" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +# ---------- inject-guard diagnostics ---------------------------------------- + +def test_layout_dispatch_diagnoses_unknown_layout(): + """`_phase_categories` else-branch fires a diag for typo'd layouts. + Catches the silent fall-through where mistyped 'single_uclass' + instead of 'single_uclass_per_file' produces zero output.""" + writes = [] + rules = { + "categories": { + "bogus": {"layout": "single_uclass"}, + }, + } + ctx = gen.PhaseContext( + schema={}, rules=rules, mjxmacro={}, mjspec={}, + public_root="", private_root="", bind_h_path="", writes=writes, + ) + gen._phase_categories(ctx) + assert any("unknown layout" in d.message and "bogus" in d.message + and "single_uclass" in d.message + for d in gen._DIAGS_BUFFER.pending) + assert writes == [] + + +# Unknown-canon diagnostic is pinned in test_canon_registry.py. diff --git a/Scripts/codegen/tests/test_inject_helpers_brace.py b/Scripts/codegen/tests/test_inject_helpers_brace.py new file mode 100644 index 0000000..e82fdf4 --- /dev/null +++ b/Scripts/codegen/tests/test_inject_helpers_brace.py @@ -0,0 +1,162 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the codegen injection helpers: brace-balance gate + +multi-tag inject + string/comment-aware brace stripping. + +The brace-balance check exists because a stray ``}`` lost inside a +long composed block silently relocates the compile error to a place +unrelated to the codegen site. We want the diagnostic to point at the +exact tag instead.""" + +from __future__ import annotations + +import os + +import generate_ue_components as gen +import _codegen_inject as _inject +gen._check_brace_balance = _inject._check_brace_balance + + +def _write(tmp_path, name: str, body: str) -> str: + p = tmp_path / name + p.write_text(body, encoding="utf-8") + return str(p) + + +# ---------- brace-balance -------------------------------------------------- + +def test_brace_balance_flags_unbalanced_block(): + body = "if (x) { do_thing(); " # missing close + gen._check_brace_balance(body, "FOO", "unit_test") + assert any("unbalanced braces" in d.message and "CODEGEN_FOO" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_brace_balance_quiet_on_balanced_block(): + body = "if (x) { do_thing(); }" + gen._check_brace_balance(body, "FOO", "unit_test") + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_brace_balance_ignores_braces_in_strings_and_comments(): + """``"{"`` inside a TEXT() literal must not count toward the open + tally; same for braces in // and /* */ comments.""" + body = ( + 'if (x)\n' + '{\n' + ' Log(TEXT("brace { in string")); // and { in line comment\n' + ' /* and { in block comment */\n' + '}\n' + ) + gen._check_brace_balance(body, "FOO", "unit_test") + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_inject_between_tags_with_balance_flag_fires_diag(): + """``balance_source`` kwarg routes through the brace-balance check.""" + file_text = "before\n// --- CODEGEN_FOO_START ---\nold\n// --- CODEGEN_FOO_END ---\nafter\n" + new_inner = "if (x) {" # unbalanced + _, ok = gen.inject_between_tags(file_text, "FOO", new_inner, + balance_source="unit_test") + assert ok is True + assert any("unbalanced braces" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_inject_between_tags_default_skips_balance_check(): + """Without ``balance_source``, the helper does not run the gate — + callers writing non-C++ blocks (markdown, JSON) aren't forced to + opt out.""" + file_text = "// --- CODEGEN_FOO_START ---\nold\n// --- CODEGEN_FOO_END ---\n" + gen.inject_between_tags(file_text, "FOO", "{ stray") + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +# ---------- _inject_tags_into_cpp ----------------------------------------- + +def test_inject_tags_into_cpp_handles_multiple_tags(tmp_path): + body = ( + "// --- CODEGEN_FOO_START ---\n" + "old foo\n" + "// --- CODEGEN_FOO_END ---\n" + "between\n" + "// --- CODEGEN_BAR_START ---\n" + "old bar\n" + "// --- CODEGEN_BAR_END ---\n" + ) + cpp_path = _write(tmp_path, "host.cpp", body) + writes: list = [] + gen._inject_tags_into_cpp( + cpp_path, + [("FOO", "new foo body"), ("BAR", "new bar body")], + writes, + diag_source="unit_test", + ) + assert len(writes) == 1 + out = writes[0].content + assert "new foo body" in out + assert "new bar body" in out + assert "old foo" not in out + assert "old bar" not in out + + +def test_inject_tags_into_cpp_diagnoses_missing_file(tmp_path): + missing = str(tmp_path / "nope.cpp") + writes: list = [] + gen._inject_tags_into_cpp( + missing, [("FOO", "x")], writes, diag_source="unit_test", + ) + assert writes == [] + assert any("does not exist" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_inject_tags_into_cpp_diagnoses_missing_marker(tmp_path): + cpp_path = _write(tmp_path, "host.cpp", + "// --- CODEGEN_FOO_START ---\nx\n// --- CODEGEN_FOO_END ---\n") + writes: list = [] + gen._inject_tags_into_cpp( + cpp_path, + [("FOO", "new foo"), ("MISSING_TAG", "new missing")], + writes, + diag_source="unit_test", + ) + # The FOO write still landed; MISSING_TAG fires a diagnostic. + assert len(writes) == 1 + assert any("CODEGEN_MISSING_TAG" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_inject_tags_into_cpp_skips_write_when_unchanged(tmp_path): + """Idempotency: re-injecting the same body must not append a + FileWrite. The ``--check`` gate relies on this. The END marker's + indent mirrors the START marker's, so a START at column 0 lands + END at column 0 too.""" + body = ( + "// --- CODEGEN_FOO_START ---\n" + "same body\n" + "// --- CODEGEN_FOO_END ---\n" + ) + cpp_path = _write(tmp_path, "host.cpp", body) + writes: list = [] + gen._inject_tags_into_cpp( + cpp_path, [("FOO", "same body")], writes, diag_source="unit_test", + ) + assert writes == [] + + +def test_inject_between_tags_normalises_end_indent_to_match_start(tmp_path): + """A hand-prepped source where START is at 8 spaces but END is + at 4 spaces (or any mismatch) gets its END normalised to match + START.""" + text = ( + " // --- CODEGEN_FOO_START ---\n" + " body content\n" + " // --- CODEGEN_FOO_END ---\n" + ) + new_text, ok = gen.inject_between_tags(text, "FOO", "new body") + assert ok is True + # Both marker lines now sit at the START's 8-space indent — assert + # the END's leading whitespace exactly so we don't accidentally + # match a substring of a deeper indent. + import re + match = re.search(r"^(\s*)// --- CODEGEN_FOO_END ---$", new_text, + re.MULTILINE) + assert match is not None + assert match.group(1) == " ", repr(match.group(1)) diff --git a/Scripts/codegen/tests/test_introspect_snapshot.py b/Scripts/codegen/tests/test_introspect_snapshot.py new file mode 100644 index 0000000..54d7f0e --- /dev/null +++ b/Scripts/codegen/tests/test_introspect_snapshot.py @@ -0,0 +1,43 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Smoke tests for the clang-AST introspect snapshot. + +Skipped automatically when libclang isn't available (e.g. CI runners +without the package). The real validation happens on the committed +``Scripts/introspect_snapshot.json`` itself — these tests just spot-check +that schema-evolution surprises don't slip through. +""" + +from __future__ import annotations + +import json +import os + +import pytest + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_PLUGIN_ROOT = os.path.normpath(os.path.join(_HERE, "..", "..", "..")) +_SNAPSHOT = os.path.join(_PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "introspect_snapshot.json") + + +def _load() -> dict: + if not os.path.exists(_SNAPSHOT): + pytest.skip("introspect_snapshot.json not built yet; run " + "build_introspect_snapshot.py") + with open(_SNAPSHOT, "r", encoding="utf-8") as f: + return json.load(f) + + +def test_snapshot_meta_and_top_level_keys_present(): + """One combined smoke test: top-level sections are present, each is + non-empty, and the ``_meta`` block carries a stable header hash. + Substring presence of specific MuJoCo names (mjs_addBody, mjtJoint, + etc.) is covered by ``test_enum_scrape::test_real_snapshot_has_ + expected_enums`` plus the regen --check gate.""" + snap = _load() + for section in ("functions", "enums", "structs", "defines"): + assert section in snap, section + assert len(snap[section]) > 0, section + assert "_meta" in snap + assert snap["_meta"]["snapshot_version"] >= 1 + assert len(snap["_meta"]["header_hash"]) == 64 diff --git a/Scripts/codegen/tests/test_kept_props_for_category.py b/Scripts/codegen/tests/test_kept_props_for_category.py new file mode 100644 index 0000000..87232c0 --- /dev/null +++ b/Scripts/codegen/tests/test_kept_props_for_category.py @@ -0,0 +1,111 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks ``kept_props_for_category`` — the ordered prop-list helper +extracted from emit_schema_for_tests. Used by the +schema-completeness header that drives URLab.Codegen.* automation +tests, so the order + composition must stay deterministic.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_emits_canon_property_first_then_per_attr_in_schema_order(): + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "canonicalizations": { + "spatial_pose": { + "absorbs_attrs": ["pos"], + "emits_property": {"name": "Pos", "type": "FVector"}, + "import_helper": "X", + "export_helper": "Y", + }, + }, + "element_rules": { + "joint": { + "applies_canonicalizations": ["spatial_pose"], + }, + }, + } + schema = {"joint": {"attrs": ["pos", "type", "axis", "limited"]}} + cat_rules = {"schema_common_block": "joint.attrs"} + out = gen.kept_props_for_category("joint", cat_rules, schema, rules) + # Pos comes first (canon-owned), then per-attr in schema order + # minus the canon-absorbed ``pos``. + assert out == ["Pos", "type", "axis", "limited"] + + +def test_disable_schema_emission_returns_empty(): + rules = {"global_exclusions": [], "canonicalizations": {}, + "element_rules": {}} + cat_rules = {"disable_schema_emission": True, + "schema_common_block": "joint.attrs"} + out = gen.kept_props_for_category("joint", cat_rules, {}, rules) + assert out == [] + + +def test_xml_enum_attr_lowers_to_ue_property(): + rules = { + "global_exclusions": [], + "property_renames": {}, + "canonicalizations": {}, + "element_rules": { + "camera": { + "xml_enum_attrs": { + "mode": { + "ue_property": "TrackingMode", + "ue_enum_type": "EMjCameraTrackingMode", + "value_map": {"fixed": ["Fixed", "mjCAMLIGHT_FIXED"]}, + }, + }, + }, + }, + } + schema = {"camera": {"attrs": ["mode", "fovy"]}} + cat_rules = {"schema_common_block": "camera.attrs"} + out = gen.kept_props_for_category("camera", cat_rules, schema, rules) + # ``mode`` -> ``TrackingMode``; ``fovy`` passes through. + assert out == ["TrackingMode", "fovy"] + + +def test_schema_common_extra_attrs_append_after_block(): + rules = {"global_exclusions": [], "property_renames": {}, + "canonicalizations": {}, "element_rules": {}} + schema = {"frame": {"attrs": []}} + cat_rules = { + "schema_common_block": "frame.attrs", + "schema_common_extra_attrs": ["pos", "quat", "childclass"], + } + out = gen.kept_props_for_category("frame", cat_rules, schema, rules) + assert out == ["pos", "quat", "childclass"] + + +def test_global_and_element_exclusions_drop_attrs(): + rules = { + "global_exclusions": ["type"], + "property_renames": {}, + "canonicalizations": {}, + "element_rules": { + "joint": {"exclude_attrs": ["limited"]}, + }, + } + schema = {"joint": {"attrs": ["type", "axis", "limited", "stiffness"]}} + cat_rules = {"schema_common_block": "joint.attrs"} + out = gen.kept_props_for_category("joint", cat_rules, schema, rules) + assert "type" not in out + assert "limited" not in out + assert out == ["axis", "stiffness"] + + +def test_property_rename_lowers_to_renamed_prop(): + rules = { + "global_exclusions": [], + "property_renames": {"qpos": "Qpos"}, + "canonicalizations": {}, + "element_rules": {}, + } + schema = {"keyframe": {"attrs": ["qpos", "time"]}} + cat_rules = {"schema_common_block": "keyframe.attrs"} + out = gen.kept_props_for_category("keyframe", cat_rules, schema, rules) + assert out == ["Qpos", "time"] diff --git a/Scripts/codegen/tests/test_libclang_hand_enum_scrape.py b/Scripts/codegen/tests/test_libclang_hand_enum_scrape.py new file mode 100644 index 0000000..15f929a --- /dev/null +++ b/Scripts/codegen/tests/test_libclang_hand_enum_scrape.py @@ -0,0 +1,164 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the libclang-backed EMj* hand-enum scrape in +``build_introspect_snapshot.py`` and the snapshot consumer +``_hand_enums_from_snapshot``. + +The scrape: + - extracts every ``enum class EMj* : uint8 { ... }`` block under + ``Source/URLab/Public``; + - strips UE-only macros (UMETA / UENUM) so a minimal libclang TU + can parse the block — including nested parens like + ``UMETA(DisplayName="Track (Centre of Mass)")``; + - lands the result under ``snapshot.hand_enums`` in + ``introspect_snapshot.json``. + +The hand-enum drift check prefers this over the fallback regex +scrape — the snapshot is byte-stable across machines because the +macro stripping is deterministic.""" + +from __future__ import annotations + +import json +import os + +import pytest +import generate_ue_components as gen +import _codegen_checks as _checks +gen._hand_enums_from_snapshot = _checks._hand_enums_from_snapshot + +# build_introspect_snapshot lives alongside generate_ue_components but is +# not always import-clean (it would try to load clang.cindex at import +# time). Test the strip helper via a tolerant import path. +import importlib.util +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +_BUILD_SNAP = os.path.join(_CODEGEN_DIR, "build_introspect_snapshot.py") + + +def _load_build_snapshot_module(): + spec = importlib.util.spec_from_file_location( + "_build_introspect_snapshot_for_test", _BUILD_SNAP, + ) + mod = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = mod + spec.loader.exec_module(mod) + return mod + + +@pytest.fixture(scope="module") +def build_snap(): + return _load_build_snapshot_module() + + +# ---------- macro stripper ------------------------------------------------- + +def test_strip_handles_nested_parens_in_umeta(build_snap): + """``UMETA(DisplayName="Track (Centre of Mass)")`` — the inner + ``(Centre`` opens a paren the regex must not bail on. The previous + naive ``UMETA\\([^)]*\\)`` regex stopped at the first ``)``, leaving + a stray ``)`` that broke libclang's enum-member walk for any member + after the first nested-paren UMETA.""" + src = ( + "enum class EMjSample : uint8 {\n" + " Fixed UMETA(DisplayName = \"Fixed\"),\n" + " TrackCom UMETA(DisplayName = \"Track (Centre of Mass)\"),\n" + " TargetBody UMETA(DisplayName = \"Target Body\"),\n" + " TargetBodyCom UMETA(DisplayName = \"Target Body (Centre of Mass)\"),\n" + "};\n" + ) + out = build_snap._strip_ue_macros_from_enum_block(src) + assert "UMETA" not in out + # No stray close-parens left behind after the strip. + assert ")" not in out + # All four members survive. + for m in ("Fixed", "TrackCom", "TargetBody", "TargetBodyCom"): + assert m in out, f"member {m} lost during strip; out={out!r}" + + +def test_strip_handles_uenum_header(build_snap): + src = ( + "UENUM(BlueprintType)\n" + "enum class EMjFoo : uint8 { A, B };\n" + ) + out = build_snap._strip_ue_macros_from_enum_block(src) + assert "UENUM" not in out + assert "enum class EMjFoo : uint8 { A, B };" in out + + +def test_strip_handles_line_and_block_comments(build_snap): + src = ( + "enum class EMjFoo : uint8 {\n" + " A, // first\n" + " B, /* second */\n" + " /* a multi\n" + " line */ C,\n" + "};\n" + ) + out = build_snap._strip_ue_macros_from_enum_block(src) + assert "first" not in out + assert "second" not in out + assert "multi" not in out + for m in ("A", "B", "C"): + assert m in out + + +def test_strip_balanced_call_terminates_on_unbalanced_input(build_snap): + """An open-paren without a matching close should consume to EOF + rather than infinite-loop the macro stripper.""" + src = "UMETA(unbalanced" + out = build_snap._strip_ue_macros_from_enum_block(src) + # Strip drove the cursor to EOF -> empty residue. + assert out == "" + + +# ---------- snapshot output ------------------------------------------------ + +def test_snapshot_contains_at_least_one_hand_enum(): + """If the shipped snapshot has hand_enums, we trust the build step + ran libclang against URLab's Public/ tree.""" + snap_path = os.path.join( + os.path.dirname(_CODEGEN_DIR), + "codegen", "snapshots", "introspect_snapshot.json", + ) + if not os.path.exists(snap_path): + pytest.skip("introspect_snapshot.json not present") + with open(snap_path, "r", encoding="utf-8") as f: + snap = json.load(f) + hand_enums = snap.get("hand_enums", {}) + if not hand_enums: + pytest.skip("hand_enums empty (libclang scrape disabled?)") + # At least one EMj* enum and every entry has members. + emj = [k for k in hand_enums if k.startswith("EMj")] + assert emj, f"hand_enums missing EMj* entries; keys={list(hand_enums)[:5]}" + for name, entry in hand_enums.items(): + assert "members" in entry, name + assert entry["members"], f"{name} has no members" + + +# ---------- runtime consumer ---------------------------------------------- + +def test_hand_enums_from_snapshot_returns_flat_member_list(): + """The runtime drift check expects ``{enum_name: [member,...]}`` — + the same shape the regex scrape produced. Confirm the converter + flattens the introspect dict shape correctly.""" + mjspec = { + "introspect": { + "hand_enums": { + "EMjSample": { + "members": {"A": 0, "B": 1, "C": 2}, + }, + }, + }, + } + out = gen._hand_enums_from_snapshot(mjspec) + assert out == {"EMjSample": ["A", "B", "C"]} + + +def test_hand_enums_from_snapshot_empty_when_missing(): + """No introspect / no hand_enums section -> empty dict (the drift + check then falls back to the regex scrape).""" + assert gen._hand_enums_from_snapshot({}) == {} + assert gen._hand_enums_from_snapshot({"introspect": {}}) == {} + assert gen._hand_enums_from_snapshot(None) == {} diff --git a/Scripts/codegen/tests/test_mjxmacro_snapshot.py b/Scripts/codegen/tests/test_mjxmacro_snapshot.py new file mode 100644 index 0000000..1ef3529 --- /dev/null +++ b/Scripts/codegen/tests/test_mjxmacro_snapshot.py @@ -0,0 +1,166 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the mjxmacro snapshot parser. + +The XNV-accepting regex was added after a silent-drop bug — every entry +listed AFTER an XNV line in the same block (e.g. ``geom_user``, ``geom_rgba`` +after ``XNV(mjtNum, geom_fluid, ...)`` in MJMODEL_POINTERS_GEOM) was +discarded because the body-collector treated XNV as a non-entry sentinel +and stopped the loop. These tests pin the regex behaviour so adding a +new tag is a deliberate change with a test failure to acknowledge. +""" + +from __future__ import annotations + +import textwrap + +from build_mjxmacro_snapshot import ( + _BODY_ENTRY_RE, + _X_ENTRY_RE, + _X_TAG_RE, + _parse_block_body, + _parse_pointer_entry, +) + + +# --------------------------------------------------------------------------- +# Regex behaviour +# --------------------------------------------------------------------------- + +def test_x_tag_re_accepts_known_tags(): + """X, XVEC, XNV are the three macro tags MuJoCo uses today.""" + import re + rx = re.compile(rf"^{_X_TAG_RE}$") + assert rx.match("X") + assert rx.match("XVEC") + assert rx.match("XNV") + # Future tags should fail until added (the failure is the canary). + assert not rx.match("XSEG") + assert not rx.match("XMODEL") + + +def test_body_entry_re_matches_all_three_tags(): + assert _BODY_ENTRY_RE.match(" X ( int, foo, nfoo, 1 )") + assert _BODY_ENTRY_RE.match(" XVEC( mjtNum, bar, nbar, 3 )") + assert _BODY_ENTRY_RE.match(" XNV ( mjtNum, baz, nbaz, mjNFLUID )") + # Tags that look similar but aren't in the set. + assert not _BODY_ENTRY_RE.match(" X3 ( ... )") + + +def test_x_entry_re_captures_payload_for_all_tags(): + m = _X_ENTRY_RE.match(" XNV ( mjtNum, geom_fluid, ngeom, mjNFLUID ) \\") + assert m + assert "geom_fluid" in m.group(1) + m2 = _X_ENTRY_RE.match(" X ( int, geom_type, ngeom, 1 ) \\") + assert m2 + assert "geom_type" in m2.group(1) + + +# --------------------------------------------------------------------------- +# End-to-end block parsing — the bug that motivated this file +# --------------------------------------------------------------------------- + +def _block_lines(block_body: str) -> list: + """Strip the leading newline + dedent so test bodies read naturally.""" + return textwrap.dedent(block_body).strip("\n").split("\n") + + +def test_block_body_does_not_stop_at_xnv(): + """The original regex matched (X|XVEC) only; XNV broke the body collector + so every subsequent entry in the block was silently dropped. This pins + the behaviour so MJMODEL_POINTERS_GEOM can never lose geom_user / + geom_rgba again.""" + lines = _block_lines(""" + X ( int, geom_type, ngeom, 1 ) + XNV ( mjtNum, geom_fluid, ngeom, mjNFLUID ) + X ( mjtNum, geom_user, ngeom, MJ_M(nuser_geom) ) + X ( float, geom_rgba, ngeom, 4 ) + """) + entries = _parse_block_body(lines, 0) + assert len(entries) == 4, "XNV must not abort the body collector" + parsed = [_parse_pointer_entry(e) for e in entries] + names = [p["name"] for p in parsed if p] + assert names == ["geom_type", "geom_fluid", "geom_user", "geom_rgba"] + + +def test_parse_pointer_entry_for_xnv(): + """XNV entries parse as 4-tuples identical to X entries.""" + entry = _parse_pointer_entry("XNV ( mjtNum, geom_fluid, ngeom, mjNFLUID )") + assert entry == { + "type": "mjtNum", + "name": "geom_fluid", + "outer_dim": "ngeom", + "stride": "mjNFLUID", + } + + +# --------------------------------------------------------------------------- +# Two-source fold-in: mjxmacro.h + mjspecmacro.h => one snapshot +# --------------------------------------------------------------------------- + +def test_shipped_snapshot_has_struct_field_sources(real_mjxmacro): + """The snapshot writer should record which header each struct-field + block came from so consumers can tell mjmodel-side from mjspec-side.""" + meta = real_mjxmacro.get("_meta", {}) + sources = meta.get("struct_field_sources") + assert isinstance(sources, dict) and sources, ( + "expected _meta.struct_field_sources to be populated" + ) + + +def test_shipped_snapshot_attributes_mjspec_blocks_to_mjspecmacro(real_mjxmacro): + """MJSCOMPILER_FIELDS + MJSPEC_FIELDS must come from mjspecmacro.h, + not mjxmacro.h — they only exist in the spec header.""" + sources = real_mjxmacro["_meta"]["struct_field_sources"] + for block in ("MJSCOMPILER_FIELDS", "MJSPEC_FIELDS"): + assert block in sources, f"snapshot missing {block} source attribution" + assert "mjspecmacro.h" in sources[block], ( + f"{block} should be sourced from mjspecmacro.h, got {sources[block]!r}" + ) + + +def test_shipped_snapshot_attributes_mjoption_blocks_to_mjxmacro(real_mjxmacro): + """MJOPTION_FIELDS / MJSTATISTIC_FIELDS live in mjxmacro.h.""" + sources = real_mjxmacro["_meta"]["struct_field_sources"] + for block in ("MJOPTION_FIELDS", "MJSTATISTIC_FIELDS"): + assert block in sources, f"snapshot missing {block} source attribution" + assert "mjxmacro.h" in sources[block], ( + f"{block} should be sourced from mjxmacro.h, got {sources[block]!r}" + ) + + +# --------------------------------------------------------------------------- +# Defensive block-coverage tripwire +# --------------------------------------------------------------------------- + +def test_shipped_snapshot_includes_arena_pointers_contact(real_mjxmacro): + """MJDATA_ARENA_POINTERS_CONTACT must round-trip. It was previously + dropped silently because POINTER_BLOCKS_MJDATA omitted it; the + unrecognised-block warning in build_mjxmacro_snapshot.py catches + similar gaps at parse time, and this test pins the result.""" + blocks = real_mjxmacro["mjdata_pointers"] + assert "MJDATA_ARENA_POINTERS_CONTACT" in blocks, ( + "MJDATA_ARENA_POINTERS_CONTACT was previously silently dropped — " + "if this fails again, check POINTER_BLOCKS_MJDATA in " + "build_mjxmacro_snapshot.py." + ) + assert blocks["MJDATA_ARENA_POINTERS_CONTACT"], ( + "block recognised but body collection produced 0 entries" + ) + + +def test_parse_mjxmacro_warns_on_unrecognised_block(tmp_path, capsys): + """An MJ-prefixed block not in any allow-list AND not in + KNOWN_UNCONSUMED_BLOCKS must print a stderr warning, NOT silently + appear in the snapshot output.""" + from build_mjxmacro_snapshot import parse_mjxmacro + fake = tmp_path / "fake_mjxmacro.h" + fake.write_text( + "#define MJMODEL_POINTERS_FROBNOZ \\\n" + " X ( int, frob_a, nfrob, 1 ) \\\n" + " X ( int, frob_b, nfrob, 1 )\n", + encoding="utf-8", + ) + parse_mjxmacro(str(fake)) + captured = capsys.readouterr() + assert "MJMODEL_POINTERS_FROBNOZ" in captured.err + assert "unrecognised" in captured.err.lower() diff --git a/Scripts/codegen/tests/test_new_rule_shapes.py b/Scripts/codegen/tests/test_new_rule_shapes.py new file mode 100644 index 0000000..f46cb22 --- /dev/null +++ b/Scripts/codegen/tests/test_new_rule_shapes.py @@ -0,0 +1,247 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Residual unit tests for rule shapes that don't have a dedicated +file: ``property_default`` (with value_map cross-check), +``_guarded_export(multiline=...)`` emission shapes, and the full-coverage +drift checks (value_map stale, orphan type_mappings, compiler attrs, +mjxmacro block coverage, mjs_array_caps_for). + +Larger concerns moved to dedicated files: see ``test_objtype_dispatch``, +``test_geom_final_type``, ``test_inject_helpers``, ``test_hand_enum_drift``, +``test_type_shape_drift``, ``test_property_units``. +""" + +from __future__ import annotations + +import generate_ue_components as gen +from generate_ue_components import _guarded_export + + +# ---------- property_default + cross-check --------------------------------- + +def test_property_default_emitted_on_base(): + """`property_default` ends up as the UPROPERTY initializer when + ``emit_property_decl: true`` is set on an xml_enum_attr.""" + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {}, + "canonicalizations": {}, + "element_rules": { + "actuator": { + "xml_enum_attrs": { + "gaintype": { + "ue_property": "GainType", + "ue_enum": "EMjGainType", + "ue_enum_type": "EMjGainType", + "override_toggle": "bOverride_GainType", + "default_lookup": "Default->GainType", + "emit_property_decl": True, + "property_default": "Fixed", + "value_map": { + "fixed": ["Fixed", "mjGAIN_FIXED"], + "affine": ["Affine", "mjGAIN_AFFINE"], + }, + }, + }, + }, + }, + } + out = gen.emit_schema_for_attrs( + ["gaintype"], rules, "actuator", "Actuator", + apply_canonicalizations=True, + ) + assert "EMjGainType GainType = EMjGainType::Fixed;" in out.properties_h + + +def test_property_default_cross_check_diagnoses_bad_member(): + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {}, + "canonicalizations": {}, + "element_rules": { + "actuator": { + "xml_enum_attrs": { + "gaintype": { + "ue_property": "GainType", + "ue_enum": "EMjGainType", + "ue_enum_type": "EMjGainType", + "override_toggle": "bOverride_GainType", + "default_lookup": "Default->GainType", + "emit_property_decl": True, + # NotAMember does not appear in value_map below. + "property_default": "NotAMember", + "value_map": { + "fixed": ["Fixed", "mjGAIN_FIXED"], + "affine": ["Affine", "mjGAIN_AFFINE"], + }, + }, + }, + }, + }, + } + gen.emit_schema_for_attrs( + ["gaintype"], rules, "actuator", "Actuator", + apply_canonicalizations=True, + ) + assert any("NotAMember" in d.message for d in gen._DIAGS_BUFFER.pending) + + +# ---------- _guarded_export(multiline=True) -------------------------------- + +def test_guarded_export_singleline_form(): + """Single-line form: ``if (toggle) `` on one line.""" + out = _guarded_export("bOverride_x", "Element->x = X;") + assert out == " if (bOverride_x) Element->x = X;\n" + + +def test_guarded_export_multiline_brace_layout(): + """Multiline form: brace on its own line; body is emitted verbatim + between braces (caller owns inner indentation).""" + body = " line_a;\n line_b;\n" + out = _guarded_export("bOverride_x", body, multiline=True) + expected = ( + " if (bOverride_x)\n" + " {\n" + " line_a;\n" + " line_b;\n" + " }\n" + ) + assert out == expected + + +def test_guarded_export_multiline_with_extra_cond(): + """``extra_cond`` (default order) appears after the toggle.""" + body = " do_thing();\n" + out = _guarded_export( + "bOverride_x", body, + extra_cond="ready", + multiline=True, + ) + assert out.startswith(" if (bOverride_x && ready)\n {\n") + assert " do_thing();\n" in out + assert out.endswith(" }\n") + + +def test_guarded_export_extra_cond_first_order(): + """``extra_cond_first=True`` flips the order and parenthesises + the extra cond.""" + out = _guarded_export( + "bOverride_x", "Element->x = X;", + extra_cond="ready", + extra_cond_first=True, + ) + assert out == " if ((ready) && bOverride_x) Element->x = X;\n" + + +# ---------- full-coverage drift checks ------------------------------------- + +def test_value_map_stale_mj_const_flagged(): + """A value_map entry referencing a constant NOT in any mjspec enum + is stale — surface it before the C++ compile fails.""" + rules = { + "element_rules": { + "joint": { + "xml_enum_attrs": { + "type": { + "value_map": { + "hinge": ["Hinge", "mjJNT_HINGE"], + "screwd": ["Screwd", "mjJNT_NONEXISTENT"], + }, + }, + }, + }, + }, + } + mjspec = {"enums": {"mjtJoint": {"mjJNT_HINGE": 0, "mjJNT_SLIDE": 1}}} + gen._check_value_map_stale_mj_consts(rules, mjspec) + assert any("mjJNT_NONEXISTENT" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_orphan_type_mappings_flagged(): + schema = {"joint": {"attrs": ["stiffness"]}} + rules = { + "type_mappings": { + "stiffness": "TArray", + "vanishedattr": "TArray", + }, + "categories": {"joint": {"schema_common_block": "joint.attrs"}}, + "element_rules": {}, + } + gen._check_orphan_rule_entries(schema, rules) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("'vanishedattr'" in m for m in msgs) + assert not any("'stiffness'" in m for m in msgs) + + +def test_compiler_attrs_coverage_flags_unhandled(): + schema = {"compiler": {"attrs": ["angle", "newflag2030", "eulerseq"]}} + rules = { + "compiler_attr_field_map": {"angle": "bAngleInDegrees", "eulerseq": "EulerSeq"}, + "intentionally_unmodeled_compiler_attrs": [], + } + gen._check_compiler_attrs_coverage(schema, rules) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("newflag2030" in m for m in msgs), msgs + assert not any("'angle'" in m for m in msgs) + + +def test_compiler_attrs_coverage_respects_intentional_skip(): + schema = {"compiler": {"attrs": ["angle", "balanceinertia"]}} + rules = { + "compiler_attr_field_map": {"angle": "bAngleInDegrees"}, + "intentionally_unmodeled_compiler_attrs": ["balanceinertia"], + } + gen._check_compiler_attrs_coverage(schema, rules) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_mjxmacro_block_coverage_forward(): + rules = { + "synthetic_categories": { + "MjOption": {"mjxmacro_block": "MJOPTION_FIELDS"}, + }, + } + mjxmacro = { + "struct_fields": { + "MJOPTION_FIELDS": [{"name": "timestep"}], + "MJNEW_FIELDS": [{"name": "wat"}], # no rule entry + }, + } + gen._check_mjxmacro_block_coverage(rules, mjxmacro) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("MJNEW_FIELDS" in m for m in msgs) + assert not any("MJOPTION_FIELDS" in m for m in msgs) + + +def test_mjxmacro_block_coverage_reverse(): + rules = { + "synthetic_categories": { + "MjGhost": {"mjxmacro_block": "MJGHOST_FIELDS"}, + }, + } + mjxmacro = {"struct_fields": {}} + gen._check_mjxmacro_block_coverage(rules, mjxmacro) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("MJGHOST_FIELDS" in m and "MjGhost" in m for m in msgs) + + +def test_mjs_array_caps_for_extracts_fixed_size_arrays(): + cat_rules = {"mjs_struct": "mjsActuator"} + mjspec = { + "introspect": { + "structs": { + "mjsActuator": { + "fields": [ + {"name": "gainprm", "c_type": "double [10]", "array_dim": 10}, + {"name": "scalar", "c_type": "double", "array_dim": None}, + {"name": "noslot", "c_type": "double [1]", "array_dim": 1}, + ], + }, + }, + }, + } + caps = gen._mjs_array_caps_for(cat_rules, mjspec) + assert caps == {"gainprm": 10} diff --git a/Scripts/codegen/tests/test_objtype_dispatch.py b/Scripts/codegen/tests/test_objtype_dispatch.py new file mode 100644 index 0000000..b633c8f --- /dev/null +++ b/Scripts/codegen/tests/test_objtype_dispatch.py @@ -0,0 +1,90 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the ``objtype_dispatch`` rule shape — emits a switch on a +UE enum that assigns each case's ``expr`` to ``target``.""" + +from __future__ import annotations + +import generate_ue_components as gen +from generate_ue_components import _emit_objtype_dispatch_block + + +def test_objtype_dispatch_emits_switch_with_default(): + cat_rules = { + "type_enum_name": "EMjEqualityType", + "objtype_dispatch": { + "discriminator": "Type", + "target": "Element->objtype", + "default": "mjOBJ_UNKNOWN", + "cases": [ + {"keys": ["Connect", "Weld"], "expr": "mjOBJ_BODY"}, + {"keys": ["Joint"], "expr": "mjOBJ_JOINT"}, + ], + }, + } + out = _emit_objtype_dispatch_block(cat_rules) + assert "switch (Type)" in out + assert "case EMjEqualityType::Connect:" in out + assert "case EMjEqualityType::Weld:" in out + assert "Element->objtype = mjOBJ_BODY;" in out + assert "case EMjEqualityType::Joint:" in out + assert "Element->objtype = mjOBJ_JOINT;" in out + assert "default:" in out + assert "Element->objtype = mjOBJ_UNKNOWN;" in out + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_objtype_dispatch_returns_none_when_no_rule(): + assert _emit_objtype_dispatch_block({}) is None + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_objtype_dispatch_diagnoses_missing_type_enum_name(): + out = _emit_objtype_dispatch_block({ + "objtype_dispatch": { + "discriminator": "Type", + "target": "Element->objtype", + "cases": [{"keys": ["A"], "expr": "X"}], + }, + }) + assert out is None + assert any("type_enum_name" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_objtype_dispatch_diagnoses_empty_cases(): + out = _emit_objtype_dispatch_block({ + "type_enum_name": "EMjEqualityType", + "objtype_dispatch": { + "discriminator": "Type", + "target": "Element->objtype", + "cases": [], + }, + }) + assert out is None + assert any("no cases" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_objtype_dispatch_diagnoses_empty_keys(): + out = _emit_objtype_dispatch_block({ + "type_enum_name": "EMjEqualityType", + "objtype_dispatch": { + "discriminator": "Type", + "target": "Element->objtype", + "cases": [{"keys": [], "expr": "mjOBJ_BODY"}], + }, + }) + assert out is None + assert any("empty" in d.message and "keys" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_objtype_dispatch_diagnoses_missing_expr(): + out = _emit_objtype_dispatch_block({ + "type_enum_name": "EMjEqualityType", + "objtype_dispatch": { + "discriminator": "Type", + "target": "Element->objtype", + "cases": [{"keys": ["Connect"]}], + }, + }) + assert out is None + assert any("missing 'expr'" in d.message for d in gen._DIAGS_BUFFER.pending) diff --git a/Scripts/codegen/tests/test_phase_2_6_checks.py b/Scripts/codegen/tests/test_phase_2_6_checks.py new file mode 100644 index 0000000..a9df2f8 --- /dev/null +++ b/Scripts/codegen/tests/test_phase_2_6_checks.py @@ -0,0 +1,221 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the three new drift checks: +``_check_apply_mode_validity``, ``_check_embedded_cpp_references``, +and ``_check_allowlist_staleness`` (narrowed to 4 of 6 allowlists per +the rule design).""" + +from __future__ import annotations + +import generate_ue_components as gen +import _codegen_checks as _checks +gen._collect_every_schema_attr = _checks._collect_every_schema_attr + + +# ---------- _check_apply_mode_validity ------------------------------------- + +def test_apply_mode_unknown_value_fires_diag(): + """A typo'd mode (``"guarderd"`` instead of ``"guarded"``) would + silently fall through to the unconditional branch — the check + surfaces it before the codegen emits a bad write path.""" + rules = { + "synthetic_categories": { + "MjOption": { + "field_apply_to_spec_mode": {"timestep": "guarderd"}, + }, + }, + } + gen._check_apply_mode_validity(rules) + assert any("guarderd" in d.message and "timestep" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_apply_mode_known_values_silent(): + rules = { + "synthetic_categories": { + "MjOption": { + "field_apply_to_spec_mode": { + "timestep": "unconditional", + "gravity": "guarded_pos", + "wind": "vec3_y_flip", + }, + }, + }, + } + gen._check_apply_mode_validity(rules) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_apply_mode_skips_note_keys(): + """The phase iterator must ignore ``_note_*`` sibling keys; they + appear as strings, not dicts.""" + rules = { + "synthetic_categories": { + "_note_intent": "doc string for the section", + "MjOption": { + "field_apply_to_spec_mode": {"timestep": "unconditional"}, + }, + }, + } + gen._check_apply_mode_validity(rules) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +# ---------- _check_embedded_cpp_references --------------------------------- + +def test_embedded_cpp_refs_flags_stale_mj_const(): + """``value_map[...][1]`` referencing a constant not in any mjspec + enum is a UHT-bound failure — the check moves it forward into + codegen-time.""" + rules = { + "element_rules": { + "joint": { + "xml_enum_attrs": { + "type": { + "value_map": { + "hinge": ["Hinge", "mjJNT_HINGE"], + "screw": ["Screw", "mjJNT_FXED"], # typo + }, + }, + }, + }, + }, + } + mjspec = {"enums": {"mjtJoint": {"mjJNT_HINGE": 0, "mjJNT_SLIDE": 1}}} + gen._check_embedded_cpp_references(rules, mjspec) + assert any("mjJNT_FXED" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_embedded_cpp_refs_silent_on_real_const(): + rules = { + "element_rules": { + "joint": { + "xml_enum_attrs": { + "type": { + "value_map": { + "hinge": ["Hinge", "mjJNT_HINGE"], + }, + }, + }, + }, + }, + } + mjspec = {"enums": {"mjtJoint": {"mjJNT_HINGE": 0}}} + gen._check_embedded_cpp_references(rules, mjspec) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_embedded_cpp_refs_flags_bad_geom_final_type_fallback(): + rules = { + "categories": { + "geom": { + "geom_final_type": { + "xml_enum_ref": "type", + "override_field": "bOverride_Type", + "default_lookup": "Default->Type", + "default_fallback": "mjGEOM_FXED", # typo + "name_field": "MeshName", + "name_export_for": "mjGEOM_MESH", + "name_target": "Element->mesh", + "name_setter": "MjSetString", + }, + }, + }, + } + mjspec = {"enums": {"mjtGeom": {"mjGEOM_SPHERE": 0, "mjGEOM_MESH": 7}}} + gen._check_embedded_cpp_references(rules, mjspec) + assert any("mjGEOM_FXED" in d.message for d in gen._DIAGS_BUFFER.pending) + + +def test_embedded_cpp_refs_quiet_without_snapshot(): + """No mjspec / no enums -> can't check; the helper no-ops without + crashing.""" + gen._check_embedded_cpp_references({}, None) + assert len(gen._DIAGS_BUFFER.pending) == 0 + gen._check_embedded_cpp_references({}, {"enums": {}}) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +# ---------- _check_allowlist_staleness ------------------------------------- + +def test_unmodeled_element_must_exist_in_schema(): + rules = { + "intentionally_unmodeled_elements": { + "skin": "URLab uses UE skeletal meshes instead", + "phantom_element": "no longer exists", # stale + }, + } + schema = {"body": {"attrs": ["pos"]}, "skin": {"attrs": []}} + gen._check_allowlist_staleness(schema, rules, None) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("phantom_element" in m and "no longer carries" in m for m in msgs) + assert not any("'skin'" in m for m in msgs) + + +def test_unmodeled_mjs_field_must_exist_on_struct(): + rules = { + "intentionally_unmodeled_mjs_fields": { + "mjsBody": ["explicitinertial", "phantom_field"], + "mjsGhost": ["any"], # stale struct + }, + } + mjspec = { + "structs": {"mjsBody": ["explicitinertial", "name", "parent"]}, + } + gen._check_allowlist_staleness({}, rules, mjspec) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("phantom_field" in m and "mjsBody" in m for m in msgs) + assert any("mjsGhost" in m for m in msgs) + assert not any("'explicitinertial'" in m and "mjsBody" in m for m in msgs) + + +def test_default_typed_attr_must_exist_somewhere_in_schema(): + rules = { + "intentionally_default_typed_attrs": [ + "kp", # in actuator_types.position list + "torquescale", # nested under equality.weld + "phantom_attr", # stale + ], + } + schema = { + "actuator_types": {"position": ["kp", "kv"]}, + "equality": {"weld": ["torquescale", "anchor"]}, + } + gen._check_allowlist_staleness(schema, rules, None) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("phantom_attr" in m for m in msgs) + assert not any("'kp'" in m for m in msgs) + assert not any("'torquescale'" in m for m in msgs) + + +def test_unmapped_mj_enum_must_exist_in_mjspec(): + rules = { + "intentionally_unmapped_mj_enum_values": { + "mjtJoint": ["mjJNT_SLIDE"], + "mjtGhost": ["mjGHOST_X"], + "__per_element__": {"site.type": ["mjGEOM_PLANE"]}, # skipped + }, + } + mjspec = {"enums": {"mjtJoint": {"mjJNT_HINGE": 0, "mjJNT_SLIDE": 1}}} + gen._check_allowlist_staleness({}, rules, mjspec) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("mjtGhost" in m for m in msgs) + assert not any("mjtJoint" in m for m in msgs) + # __per_element__ never fires its own staleness diag. + assert not any("__per_element__" in m for m in msgs) + + +# ---------- _collect_every_schema_attr ------------------------------------ + +def test_collect_every_schema_attr_picks_up_three_shapes(): + """Cover the three list shapes the walker handles: + nested-attrs key, flat list at any depth (actuator_types, + equality.weld), nested-attrs inside sensor_types entries.""" + schema = { + "body": {"attrs": ["pos", "quat"]}, + "actuator_types": {"position": ["kp", "kv"]}, + "equality": {"weld": ["torquescale"]}, + "sensor_types": [{"name": "accel", "attrs": ["cutoff"]}], + } + out = gen._collect_every_schema_attr(schema) + for needed in ("pos", "quat", "kp", "kv", "torquescale", "cutoff"): + assert needed in out, f"missing {needed} from {out}" diff --git a/Scripts/codegen/tests/test_phase_context.py b/Scripts/codegen/tests/test_phase_context.py new file mode 100644 index 0000000..ea87bce --- /dev/null +++ b/Scripts/codegen/tests/test_phase_context.py @@ -0,0 +1,39 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the ``PhaseContext``. Every +emission phase used to take 7 (or 8) positional args; they now take +one ``PhaseContext`` so adding a new field to the pipeline doesn't +touch a dozen signatures.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_every_emission_phase_accepts_phase_context(): + """Every entry in EMISSION_PHASES.fn must be callable with one + PhaseContext arg. Catches refactor drift where one phase keeps the + old 7-positional-arg signature.""" + ctx = gen.PhaseContext( + schema={}, rules={}, mjxmacro={}, mjspec={}, + public_root="", private_root="", bind_h_path="", + writes=[], + ) + for phase in gen.EMISSION_PHASES: + # No assertion on side effects — just that the call doesn't + # TypeError on signature mismatch. + phase.fn(ctx) + + +def test_phase_context_is_dataclass_with_writes_list(): + """Quick sanity: ``writes`` must be a mutable list, not a frozen + sequence — phases append to it.""" + ctx = gen.PhaseContext( + schema={}, rules={}, mjxmacro={}, mjspec={}, + public_root="", private_root="", bind_h_path="", + writes=[], + ) + ctx.writes.append("sentinel") + assert ctx.writes == ["sentinel"] + + +# Unknown-layout diagnostic is pinned in test_inject_helpers::test_layout_dispatch_diagnoses_unknown_layout. diff --git a/Scripts/codegen/tests/test_property_units.py b/Scripts/codegen/tests/test_property_units.py new file mode 100644 index 0000000..a7a904b --- /dev/null +++ b/Scripts/codegen/tests/test_property_units.py @@ -0,0 +1,130 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the editor display-unit rule shapes: ``property_units`` +(UE-native ``Units="m"`` meta on scalars, custom ``MjUnit="m"`` on +TArrays), ``hidden_attrs`` / ``hidden_canon_properties`` +(EditConditionHides), and the validity drift check.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_property_units_emits_units_meta_on_scalar(): + """Scalar/struct UE types get UE-native meta=(Units="...").""" + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {"margin": "float"}, + "canonicalizations": {}, + "element_rules": { + "geom": {"property_units": {"margin": "m"}}, + }, + } + out = gen.emit_schema_for_attrs(["margin"], rules, "geom", "Geom") + assert 'Units="m"' in out.properties_h, out.properties_h + assert out.properties_h.count('Units="m"') == 1 + + +def test_property_units_emits_mjunit_meta_on_tarray(): + """TArray UE types get MjUnit="..." — UHT rejects Units on arrays; + URLab's detail customization reads MjUnit at runtime.""" + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {"size": "TArray"}, + "canonicalizations": {}, + "element_rules": { + "geom": {"property_units": {"size": "m"}}, + }, + } + out = gen.emit_schema_for_attrs(["size"], rules, "geom", "Geom") + assert 'MjUnit="m"' in out.properties_h, out.properties_h + assert 'Units="m"' not in out.properties_h + + +def test_property_units_coexists_with_property_meta(): + """Units composes with existing property_meta (e.g. DisplayName) + without one clobbering the other.""" + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {}, + "canonicalizations": {}, + "element_rules": { + "geom": { + "property_meta": {"foo": 'DisplayName="Foo Bar"'}, + "property_units": {"foo": "m"}, + }, + }, + } + out = gen.emit_schema_for_attrs(["foo"], rules, "geom", "Geom") + assert 'DisplayName="Foo Bar"' in out.properties_h + assert 'Units="m"' in out.properties_h + + +def test_property_units_validity_diagnoses_bad_unit(): + rules = { + "element_rules": { + "geom": {"property_units": {"size": "meters"}}, + }, + } + gen._check_property_units_validity(rules) + assert any("'meters'" in d.message and "geom" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_property_units_validity_silent_on_known_units(): + rules = { + "element_rules": { + "geom": {"property_units": {"size": "m", "fovy": "deg"}}, + }, + } + gen._check_property_units_validity(rules) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +def test_hidden_attrs_emits_edit_condition_hides(): + """hidden_attrs entries emit EditCondition=false + EditConditionHides + so the field stays in C++ but the Details panel widget vanishes.""" + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {"size": "TArray"}, + "canonicalizations": {}, + "element_rules": { + "geom": {"hidden_attrs": ["size"]}, + }, + } + out = gen.emit_schema_for_attrs(["size"], rules, "geom", "Geom") + assert 'EditCondition="false"' in out.properties_h + assert 'EditConditionHides' in out.properties_h + + +def test_hidden_canon_properties_emits_edit_condition_hides(): + rules = { + "global_exclusions": [], + "default_type": "float", + "property_renames": {}, + "type_mappings": {}, + "canonicalizations": { + "spatial_pose": { + "absorbs_attrs": ["pos"], + "emits_property": {"name": "Pos", "type": "FVector"}, + "import_helper": "X", + "export_helper": "Y", + }, + }, + "element_rules": { + "geom": { + "applies_canonicalizations": ["spatial_pose"], + "hidden_canon_properties": ["spatial_pose"], + }, + }, + } + out = gen.emit_schema_for_attrs([], rules, "geom", "Geom") + assert 'FVector Pos' in out.properties_h + assert 'EditConditionHides' in out.properties_h diff --git a/Scripts/codegen/tests/test_regen_no_diff.py b/Scripts/codegen/tests/test_regen_no_diff.py new file mode 100644 index 0000000..fdea920 --- /dev/null +++ b/Scripts/codegen/tests/test_regen_no_diff.py @@ -0,0 +1,46 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Golden-file gate. + +Runs ``generate_ue_components.py --check`` against the real schema / +mjxmacro / rules / mjspec snapshots and asserts: + 1. Every emitted file is byte-identical to what's on disk (exit 0). + 2. The run produced zero diagnostics in stderr — catches new warn-mode + drift introduced by a rule change that the byte-identity check + can't see (drift fires on stderr without changing the emit output). +""" + +from __future__ import annotations + +import os +import subprocess +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_GENERATOR = os.path.normpath(os.path.join(_HERE, "..", "generate_ue_components.py")) + + +def test_codegen_check_clean() -> None: + """`generate_ue_components.py --check` exits 0 with no diagnostics.""" + proc = subprocess.run( + [sys.executable, _GENERATOR, "--check"], + capture_output=True, + text=True, + ) + stdout = proc.stdout or "" + stderr = proc.stderr or "" + assert proc.returncode == 0, ( + "codegen drift detected: re-running the generator would rewrite one or " + "more on-disk files. Re-run `python Scripts/codegen/generate_ue_components.py` " + "to regenerate, or update the emit functions if hand-edits to " + "CODEGEN_*_START/END regions slipped past the generator.\n" + f"--- stdout ---\n{stdout}\n--- stderr ---\n{stderr}" + ) + # Diagnostics fire on stderr without changing emit output — catches the + # warn-mode drift class that the byte-identity check is blind to. + assert "[diagnostic]" not in stderr, ( + "codegen ran clean (no file rewrites) but emitted one or more " + "diagnostics. A rule entry or snapshot likely drifted; rules JSON or " + "an intentionally_* allowlist needs updating.\n" + f"--- stderr ---\n{stderr}" + ) diff --git a/Scripts/codegen/tests/test_require_introspect.py b/Scripts/codegen/tests/test_require_introspect.py new file mode 100644 index 0000000..92c975d --- /dev/null +++ b/Scripts/codegen/tests/test_require_introspect.py @@ -0,0 +1,61 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Verifies the ``--require-introspect`` flag's exit-code contract. + +The clang-AST introspect snapshot drives the embedded-C++ drift checks +(value_map / hand-enum / mjs_array shape). Letting codegen silently fall +back to a stale or missing snapshot turned subtle rule typos into runtime +fall-through; this flag is the hard-fail gate. + +These tests shell out to ``generate_ue_components.py`` so the real +``main()`` arg-parsing + early-exit branches are exercised. +""" + +from __future__ import annotations + +import os +import subprocess +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +_PLUGIN_ROOT = os.path.dirname(os.path.dirname(_CODEGEN_DIR)) +_GENERATOR = os.path.join(_CODEGEN_DIR, "generate_ue_components.py") + + +def _run(extra_args: list[str], introspect_path: str) -> subprocess.CompletedProcess: + return subprocess.run( + [sys.executable, _GENERATOR, + "--check", "--introspect", introspect_path, + *extra_args], + capture_output=True, text=True, cwd=_PLUGIN_ROOT, + ) + + +def test_require_introspect_default_hard_fails_when_missing(tmp_path): + """Default behaviour (no flag = require_introspect=True) MUST exit + non-zero with the documented exit code (3) when the snapshot is + absent. Closes the silent-fallback path.""" + missing = str(tmp_path / "introspect_snapshot.json") + assert not os.path.exists(missing) + proc = _run([], missing) + assert proc.returncode == 3, ( + f"expected exit 3, got {proc.returncode}\n" + f"stdout={proc.stdout!r}\nstderr={proc.stderr!r}" + ) + assert "introspect snapshot missing" in proc.stderr + + +def test_no_require_introspect_skips_the_exit_3_gate(tmp_path): + """``--no-require-introspect`` skips the up-front exit-3 hard-fail + so the run reaches the codegen loop. The loop itself raises + downstream once it needs the setto signatures the introspect + carries — the flag isn't a way to make the codegen succeed + without introspect, it's a way to defer the failure for triage.""" + missing = str(tmp_path / "introspect_snapshot.json") + proc = _run(["--no-require-introspect"], missing) + # The up-front gate didn't fire (exit 3), and the run reached the + # loop. Exit 1 (the downstream RuntimeError) is the documented + # failure mode. + assert proc.returncode != 3 + assert "warning" in proc.stderr.lower() + assert "introspect snapshot missing" in proc.stderr diff --git a/Scripts/codegen/tests/test_resolve_mjs_field.py b/Scripts/codegen/tests/test_resolve_mjs_field.py new file mode 100644 index 0000000..8aa8042 --- /dev/null +++ b/Scripts/codegen/tests/test_resolve_mjs_field.py @@ -0,0 +1,91 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks ``_resolve_mjs_field``'s 5-step resolution chain and the +per-strategy helpers. Each strategy lives in +its own function and is composed via ``_MJS_FIELD_RESOLVERS``.""" + +from __future__ import annotations + +import _codegen_core as gen # private resolver surface lives in _codegen_core + + +# ---------- per-strategy resolvers ---------------------------------------- + +def test_resolve_direct_match(): + assert gen._resolve_direct("condim", {"condim", "type"}) == "condim" + assert gen._resolve_direct("absent", {"other"}) is None + + +def test_resolve_name_suffix(): + """MuJoCo name-ref fields uniformly append 'name'.""" + assert gen._resolve_name_suffix("mesh", {"meshname"}) == "meshname" + assert gen._resolve_name_suffix("scalar", {"scalarvalue"}) is None + + +def test_resolve_root_name_digits_variants(): + """``body1`` -> ``bodyname1`` and the underscore variant + ``body_name1`` both resolve.""" + assert gen._resolve_root_name_digits("body1", {"bodyname1"}) == "bodyname1" + assert gen._resolve_root_name_digits("body1", {"body_name1"}) == "body_name1" + # No-digit suffix -> no match. + assert gen._resolve_root_name_digits("body", {"bodyname"}) is None + + +def test_resolve_underscore_norm_matches_drop_underscores(): + assert gen._resolve_underscore_norm("solreflimit", {"solref_limit"}) == "solref_limit" + assert gen._resolve_underscore_norm("solreflimit", {"solref_friction"}) is None + + +def test_resolve_actuator_prefix_with_underscore_norm(): + """schema ``actuatorfrclimited`` -> mjs ``actfrclimited`` (direct) + or ``act_frc_limited`` (via underscore norm).""" + assert gen._resolve_actuator_prefix("actuatorfrclimited", {"actfrclimited"}) == "actfrclimited" + assert gen._resolve_actuator_prefix("actuatorfrclimited", {"act_frc_limited"}) == "act_frc_limited" + assert gen._resolve_actuator_prefix("notanactuator", {"anything"}) is None + + +# ---------- composition through _resolve_mjs_field ------------------------ + +def test_resolve_mjs_field_prefers_override_table(): + """Per-element ``attr_to_mjs_field`` rules ALWAYS win — no + convention can override a rule author's explicit mapping.""" + out = gen._resolve_mjs_field( + "target", {"target", "targetbody"}, + attr_to_mjs_field={"target": "targetbody"}, + ) + assert out == "targetbody" + + +def test_resolve_mjs_field_falls_through_strategy_order(): + """Each strategy fires in declared order; only the first match + wins. Strategies that don't apply return None and fall through.""" + # No direct match; falls through to root+name+digits. + out = gen._resolve_mjs_field("body1", {"bodyname1", "geomname1"}) + assert out == "bodyname1" + + +def test_resolve_mjs_field_falls_back_to_attr_when_nothing_matches(): + """If every strategy returns None, return the attr verbatim — the + downstream C++ build will fail loudly on the bad field name.""" + out = gen._resolve_mjs_field( + "novel_attr", {"unrelated_field"}, + ) + assert out == "novel_attr" + + +def test_resolve_mjs_field_empty_fields_returns_attr(): + """When ``mjs_fields`` is empty, no resolution is possible — the + attr passes through unchanged.""" + assert gen._resolve_mjs_field("any", set()) == "any" + + +def test_resolvers_tuple_is_module_constant(): + """The resolver chain order must be a module-level constant so a + test can assert it explicitly. Catches accidental reordering that + would change which strategy wins on ambiguous inputs.""" + assert gen._MJS_FIELD_RESOLVERS == ( + gen._resolve_direct, + gen._resolve_name_suffix, + gen._resolve_root_name_digits, + gen._resolve_underscore_norm, + gen._resolve_actuator_prefix, + ) diff --git a/Scripts/codegen/tests/test_rule_iter_helpers.py b/Scripts/codegen/tests/test_rule_iter_helpers.py new file mode 100644 index 0000000..d2e92c4 --- /dev/null +++ b/Scripts/codegen/tests/test_rule_iter_helpers.py @@ -0,0 +1,76 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the rule-iteration helpers ``compute_canon_absorbed`` / +``iter_canon_absorbed`` / ``iter_category_attrs``. They are the single +source of truth for the standard three-skip exclusion gate that every +per-attr emission site used to inline.""" + +from __future__ import annotations + +import generate_ue_components as gen +import _codegen_core as _core +gen.iter_canon_absorbed = _core.iter_canon_absorbed + + +# ---------- iter_canon_absorbed / compute_canon_absorbed ------------------- + +def test_compute_canon_absorbed_unions_applied_canons(): + canons = { + "spatial_pose": {"absorbs_attrs": ["pos", "quat", "euler", "axisangle"]}, + "fromto_decompose": {"absorbs_attrs": ["fromto"]}, + "unused": {"absorbs_attrs": ["other"]}, + } + got = gen.compute_canon_absorbed(["spatial_pose", "fromto_decompose"], canons) + assert got == {"pos", "quat", "euler", "axisangle", "fromto"} + # An unapplied canon stays out — gating is by applies_canonicalizations. + assert "other" not in got + + +def test_compute_canon_absorbed_silent_on_missing_canon(): + canons = {"spatial_pose": {"absorbs_attrs": ["pos"]}} + got = gen.compute_canon_absorbed(["spatial_pose", "ghost_canon"], canons) + assert got == {"pos"} + + +def test_compute_canon_absorbed_handles_empty_inputs(): + assert gen.compute_canon_absorbed([], {}) == set() + assert gen.compute_canon_absorbed(["any"], {}) == set() + assert gen.compute_canon_absorbed([], {"spatial_pose": {"absorbs_attrs": ["pos"]}}) == set() + + +def test_iter_canon_absorbed_is_lazy_view(): + canons = {"c": {"absorbs_attrs": ["a", "b"]}} + it = gen.iter_canon_absorbed(["c"], canons) + # Confirm it's an iterator, not a materialised list — call sites that + # only want a single membership check shouldn't pay for a list build. + assert iter(it) is it + assert list(it) == ["a", "b"] + + +# ---------- iter_category_attrs -------------------------------------------- + +def test_iter_category_attrs_filters_three_gates(): + attrs = ["a", "b", "c", "d", "e"] + got = list(gen.iter_category_attrs( + attrs, + global_excl={"a"}, + elem_excl={"b"}, + canon_absorbed={"c"}, + )) + assert got == ["d", "e"] + + +def test_iter_category_attrs_preserves_order(): + """Codegen output depends on attr order — schema order must survive + the filter so emitted .h/.cpp stay byte-identical to the schema.""" + attrs = ["zeta", "alpha", "mu"] + got = list(gen.iter_category_attrs( + attrs, global_excl=set(), elem_excl=set(), canon_absorbed=set(), + )) + assert got == ["zeta", "alpha", "mu"] + + +def test_iter_category_attrs_handles_empty_attrs(): + got = list(gen.iter_category_attrs( + [], global_excl={"a"}, elem_excl=set(), canon_absorbed=set(), + )) + assert got == [] diff --git a/Scripts/codegen/tests/test_rule_shape_contract.py b/Scripts/codegen/tests/test_rule_shape_contract.py new file mode 100644 index 0000000..fc1cd6f --- /dev/null +++ b/Scripts/codegen/tests/test_rule_shape_contract.py @@ -0,0 +1,326 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Contract tests for codegen_rules.json. The rules file is the +single source of truth for the codegen — these tests pin the +structural invariants every emitter depends on, so a hand-edit +that breaks them surfaces in pytest instead of as a UE compile +failure far downstream.""" + +from __future__ import annotations + +import generate_ue_components as gen # noqa: F401 (kept for module discovery) +from _codegen_core import _UE_TYPE_INFO + + +_KNOWN_TOP_LEVEL_KEYS = { + # data driving the emit path + "global_exclusions", + "default_type", + "property_renames", + "setto_param_defaults", + "type_mappings", + "categories", + "element_rules", + "canonicalizations", + "synthetic_categories", + "generated_enums", + "editor_option_helpers", + "views", + # drift-suppression allowlists + "intentionally_unmodeled_elements", + "intentionally_unmodeled_mjs_fields", + "intentionally_unmodeled_compiler_attrs", + "intentionally_default_typed_attrs", + "intentionally_unmapped_mj_enum_values", + # shared per-rule namespaces + "compiler_attr_field_map", +} + + +def test_top_level_keys_are_recognised(real_rules): + """Every top-level key in the rules JSON is either a known shape + or a ``_note_*`` sibling string. Catches typo'd renames at edit + time.""" + unknown = [] + for key in real_rules: + if key.startswith("_") or key in _KNOWN_TOP_LEVEL_KEYS: + continue + unknown.append(key) + assert not unknown, ( + f"unknown top-level keys in codegen_rules.json: {unknown}. " + f"Either add them to _KNOWN_TOP_LEVEL_KEYS in this test or " + f"_note_-prefix them to mark as documentation." + ) + + +def test_every_category_carries_required_keys(real_rules): + """Every entry under ``categories`` needs a schema_common_block. + Missing the block silently produces an empty emit; the test + surfaces the missing key at JSON-edit time.""" + for cat, cat_rules in real_rules.get("categories", {}).items(): + if cat.startswith("_"): + continue + assert "schema_common_block" in cat_rules, ( + f"category '{cat}' missing schema_common_block") + + +def test_canonicalisations_referenced_by_element_rules_exist(real_rules): + """element_rules[X].applies_canonicalizations must list canon + names that exist in the top-level ``canonicalizations`` block. + Otherwise per-element XML import silently drops absorbed attrs.""" + canon_keys = set(real_rules.get("canonicalizations", {}).keys()) + for elem, elem_rule in real_rules.get("element_rules", {}).items(): + for canon in elem_rule.get("applies_canonicalizations", []): + assert canon in canon_keys, ( + f"element_rules['{elem}'].applies_canonicalizations " + f"references '{canon}' which is not declared in the " + f"top-level canonicalizations block.") + + +def test_xml_enum_attr_value_maps_have_correct_shape(real_rules): + """Each ``value_map`` entry must be a 2-element ``[ue_member, + mj_const]`` list, non-empty xml key, and the map itself non-empty. + An empty map silently emits a dead block that toggles the override + flag without ever assigning the enum; empty xml keys match every + missing attr at runtime via ``GetAttribute()`` returning ``""``.""" + for elem, elem_rule in real_rules.get("element_rules", {}).items(): + for attr, enum_def in elem_rule.get("xml_enum_attrs", {}).items(): + value_map = enum_def.get("value_map", {}) + assert value_map, ( + f"element_rules['{elem}'].xml_enum_attrs['{attr}']" + f".value_map is empty — emit would set the override " + f"toggle without ever assigning the enum.") + for xml_val, mapping in value_map.items(): + assert xml_val != "", ( + f"element_rules['{elem}'].xml_enum_attrs['{attr}']" + f".value_map has an empty-string xml key — at " + f"runtime this matches every missing attr.") + assert isinstance(mapping, (list, tuple)), ( + f"element_rules['{elem}'].xml_enum_attrs['{attr}']" + f".value_map['{xml_val}'] must be a list, got " + f"{type(mapping).__name__}") + assert len(mapping) == 2, ( + f"element_rules['{elem}'].xml_enum_attrs['{attr}']" + f".value_map['{xml_val}'] must be " + f"[ue_member, mj_const]; got {mapping!r}") + + +def test_synthetic_categories_carry_block_or_skip_flag(real_rules): + """Every synthetic_categories entry must either name an + mjxmacro_block or carry a disabled flag. A bare entry would + silently emit nothing.""" + synth = real_rules.get("synthetic_categories", {}) + for cat_name, def_ in synth.items(): + if cat_name.startswith("_") or not isinstance(def_, dict): + continue + assert def_.get("mjxmacro_block") or def_.get("disabled"), ( + f"synthetic_categories['{cat_name}'] needs either an " + f"mjxmacro_block or a disabled flag") + + +# ---------- inner-key shape contracts ---------------------------------- +# +# The top-level allowlist catches typo'd renames at the rules root, but +# inner-key typos (e.g. ``attr_to_mjs_fields`` instead of +# ``attr_to_mjs_field``) silently fall through every reader's +# ``.get(..., {})``. The contracts below close that loop: every reader +# fetches by bracketed access against the keys listed here, so a typo +# surfaces in pytest instead of as a KeyError mid-emit (or worse — a +# silent no-op that ships wrong-runtime C++). + + +_CATEGORY_REQUIRED = {"schema_common_block", "base_class_name", "base_class_header", "mjs_struct"} +_CATEGORY_OPTIONAL = { + "subtypes", "layout", "subtype_setto", "type_enum_name", + "schema_subtypes_block", "schema_common_extra_attrs", + "objtype_dispatch", "geom_final_type", "applies_canonicalizations", + "subclass_directory_pub", "subclass_directory_priv", + "xml_passthrough_emission", "disable_mjs_export_emission", +} +_SUBTYPE_REQUIRED = {"key", "enum_value", "class_name"} +_SUBTYPE_OPTIONAL = { + "header", "fully_emitted", "case_body_override", "extra_constructor", +} +_ELEMENT_RULE_OPTIONAL = { + "exclude_attrs", "applies_canonicalizations", "xml_enum_attrs", + "attr_to_mjs_field", "property_renames", "property_meta", + "property_units", "property_defaults", "target_collations", + "common_imports", "mjs_data_packed_attrs", "mjs_double_vec_attrs", + "sentinel_skip_export", "export_skip_attrs", "unit_conversion", + "vec3_convert", "hidden_canon_properties", "hidden_attrs", + "canon_export_skip", "xml_passthrough_emission", "common_attrs", + "field_apply_to_spec_mode", "field_defaults", +} +_XML_ENUM_ATTR_REQUIRED = {"ue_property", "ue_enum_type", "value_map"} +_XML_ENUM_ATTR_OPTIONAL = { + "mjs_field", "mjs_cast", "has_override_toggle", + "emit_property_decl", "property_default", "property_meta", + "from_mj_enum", +} +_CANON_REQUIRED = {"absorbs_attrs"} +_CANON_OPTIONAL = { + "emits_property", "category_specifics", + "import_helper", "export_helper", +} + + +def _assert_inner_keys(path: str, obj: dict, required: set, optional: set): + for k in required: + assert k in obj, f"{path}: missing required key '{k}'" + allowed = required | optional + bad = [k for k in obj if not k.startswith("_") and k not in allowed] + assert not bad, ( + f"{path}: unknown key(s) {bad}. Either add to the contract " + f"allowlist in test_rule_shape_contract.py or _note_-prefix " + f"as documentation." + ) + + +def test_category_inner_keys_match_contract(real_rules): + for cat, cat_rules in real_rules.get("categories", {}).items(): + if cat.startswith("_"): + continue + _assert_inner_keys( + f"categories['{cat}']", cat_rules, + _CATEGORY_REQUIRED, _CATEGORY_OPTIONAL, + ) + + +def test_category_subtype_inner_keys_match_contract(real_rules): + for cat, cat_rules in real_rules.get("categories", {}).items(): + if cat.startswith("_"): + continue + for i, sub in enumerate(cat_rules.get("subtypes", [])): + if not isinstance(sub, dict): + continue + _assert_inner_keys( + f"categories['{cat}'].subtypes[{i}] ({sub.get('key', '?')})", + sub, _SUBTYPE_REQUIRED, _SUBTYPE_OPTIONAL, + ) + + +def test_element_rule_inner_keys_match_contract(real_rules): + for elem, elem_rule in real_rules.get("element_rules", {}).items(): + if elem.startswith("_"): + continue + _assert_inner_keys( + f"element_rules['{elem}']", elem_rule, + set(), _ELEMENT_RULE_OPTIONAL, + ) + + +def test_xml_enum_attr_inner_keys_match_contract(real_rules): + for elem, elem_rule in real_rules.get("element_rules", {}).items(): + for attr, enum_def in elem_rule.get("xml_enum_attrs", {}).items(): + if not isinstance(enum_def, dict): + continue + _assert_inner_keys( + f"element_rules['{elem}'].xml_enum_attrs['{attr}']", + enum_def, + _XML_ENUM_ATTR_REQUIRED, _XML_ENUM_ATTR_OPTIONAL, + ) + + +def test_canonicalisation_inner_keys_match_contract(real_rules): + for canon, canon_def in real_rules.get("canonicalizations", {}).items(): + if canon.startswith("_"): + continue + _assert_inner_keys( + f"canonicalizations['{canon}']", canon_def, + _CANON_REQUIRED, _CANON_OPTIONAL, + ) + + +def test_synthetic_category_required_public_header(real_rules): + """Every active synthetic_categories entry needs ``public_header`` + pointing under ``MuJoCo/Generated/``. Missing key would KeyError at + emit; a stray absolute path would write outside the plugin tree.""" + for cat_name, def_ in real_rules.get("synthetic_categories", {}).items(): + if cat_name.startswith("_") or not isinstance(def_, dict): + continue + if def_.get("disabled"): + continue + assert "public_header" in def_, ( + f"synthetic_categories['{cat_name}']: missing public_header" + ) + ph = def_["public_header"] + assert ph.startswith("MuJoCo/Generated/") and ph.endswith(".h"), ( + f"synthetic_categories['{cat_name}'].public_header = " + f"'{ph}' must be 'MuJoCo/Generated/*.h'" + ) + + +def test_generated_enums_carry_ue_name_and_mapping(real_rules): + """generated_enums entries must declare ue_name (starts with EMj) + and at least one mapping source (ue_member_from_mj or + extra_members).""" + for group, group_def in real_rules.get("generated_enums", {}).items(): + if group.startswith("_") or not isinstance(group_def, dict): + continue + for i, entry in enumerate(group_def.get("enums", [])): + if entry.get("disabled"): + continue + ue_name = entry.get("ue_name", "") + assert ue_name.startswith("EMj"), ( + f"generated_enums['{group}'].enums[{i}].ue_name = " + f"'{ue_name}' must start with 'EMj'" + ) + has_mj = entry.get("from_mj_enum") + has_members = entry.get("ue_member_from_mj") or entry.get("extra_members") + assert has_mj or has_members, ( + f"generated_enums['{group}'].enums[{i}] ({ue_name}): " + f"needs from_mj_enum or extra_members; otherwise emits " + f"nothing." + ) + + +def test_setto_param_defaults_are_finite_numeric_literals(real_rules): + """Values land VERBATIM in the generated C++ as a ternary's else + branch (see ``_emit_setto_call``). Allowed shapes: int / signed-or- + -unsigned float with optional decimal + exponent. Reject ``"inf"``, + ``"nan"``, hex, or empty strings — they compile to non-finite or + invalid C++.""" + import re + finite_re = re.compile(r"^-?\d+(\.\d*)?([eE][+-]?\d+)?$") + defaults = real_rules.get("setto_param_defaults", {}) + for fn_name, params in defaults.items(): + if fn_name.startswith("_") or not isinstance(params, dict): + continue + for pname, value in params.items(): + assert isinstance(value, str), ( + f"setto_param_defaults['{fn_name}']['{pname}'] = " + f"{value!r}: must be a string (drops verbatim into C++)" + ) + assert finite_re.match(value), ( + f"setto_param_defaults['{fn_name}']['{pname}'] = " + f"'{value}': must be a finite decimal literal " + f"('inf' / 'nan' / hex / empty rejected)" + ) + + +def test_type_mappings_use_known_ue_types(real_rules): + """Every type in type_mappings must be a UE type the codegen + can emit (i.e. resolves through _UE_TYPE_INFO or is a known + TArray<...>). Surfacing typo'd types here catches "TArray" + long before UHT fails.""" + known = set(_UE_TYPE_INFO.keys()) + for attr, ue_type in real_rules.get("type_mappings", {}).items(): + if attr.startswith("_"): + continue + if ue_type in known: + continue + if ue_type.startswith("TArray<") and ue_type.endswith(">"): + inner = ue_type[len("TArray<"):-1] + assert (inner in known or inner.startswith("U") + or inner.startswith("EMj")), ( + f"type_mappings['{attr}'] = '{ue_type}' has unknown " + f"inner type '{inner}'") + continue + # URLab-side hand-rolled enums (EMj*) are legitimate UPROPERTY + # types but live outside the registry's UE type universe. + if ue_type.startswith("EMj"): + continue + # Unrecognised types fall through to default_type with a diag; + # the test surfaces the JSON-edit-time intent. + assert False, ( + f"type_mappings['{attr}'] = '{ue_type}' is not a " + f"recognised UE type") diff --git a/Scripts/codegen/tests/test_sensor_per_type_extractor.py b/Scripts/codegen/tests/test_sensor_per_type_extractor.py new file mode 100644 index 0000000..3197e0c --- /dev/null +++ b/Scripts/codegen/tests/test_sensor_per_type_extractor.py @@ -0,0 +1,198 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Unit tests for the per-sensor objtype/reftype extractor in +build_mjcf_schema_snapshot.py. + +The extractor scrapes xml_native_reader.cc's ``Sensor()`` if/else cascade +so codegen rules don't have to hand-list each sensor's mjsSensor object +defaults. Tests cover the four shape classes the extractor produces: +literal default, from_xml, computed (multi-attr derivation), and the +nested-branch suppression case (distance/normal/fromto share an outer +branch whose inner ``if`` would otherwise overwrite the entry). +""" + +from __future__ import annotations + +import os +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +if _CODEGEN_DIR not in sys.path: + sys.path.insert(0, _CODEGEN_DIR) + +from build_mjcf_schema_snapshot import _extract_sensor_per_type # noqa: E402 + + +_FAKE_SOURCE = r""" +void mjXReader::Sensor(XMLElement* section) { + while (elem) { + mjsSensor* sensor = mjs_addSensor(spec); + string type = elem->Value(); + string text, name, objname, refname; + + if (type == "touch") { + sensor->type = mjSENS_TOUCH; + sensor->objtype = mjOBJ_SITE; + ReadAttrTxt(elem, "site", objname, true); + } else if (type == "framepos") { + sensor->type = mjSENS_FRAMEPOS; + ReadAttrTxt(elem, "objtype", text, true); + sensor->objtype = (mjtObj)mju_str2Type(text.c_str()); + ReadAttrTxt(elem, "objname", objname, true); + if (ReadAttrTxt(elem, "reftype", text)) { + sensor->reftype = (mjtObj)mju_str2Type(text.c_str()); + ReadAttrTxt(elem, "refname", refname, true); + } + } else if (type == "distance" || type == "normal" || type == "fromto") { + bool has_body1 = ReadAttrTxt(elem, "body1", objname); + sensor->objtype = has_body1 ? mjOBJ_BODY : mjOBJ_GEOM; + ReadAttrTxt(elem, "body2", refname); + sensor->reftype = mjOBJ_BODY; + if (type == "distance") { + sensor->type = mjSENS_GEOMDIST; + } else if (type == "normal") { + sensor->type = mjSENS_GEOMNORMAL; + } else { + sensor->type = mjSENS_GEOMFROMTO; + } + } else if (type == "clock") { + sensor->type = mjSENS_CLOCK; + sensor->objtype = mjOBJ_UNKNOWN; + } + elem = NextSiblingElement(elem); + } +} +""" + + +def test_literal_objtype_with_site_name_read(): + result = _extract_sensor_per_type(_FAKE_SOURCE) + assert result["touch"] == { + "mj_type": "mjSENS_TOUCH", + "objtype": "mjOBJ_SITE", + "reftype": None, + "obj_attr": "site", + "ref_attr": None, + "computed": False, + } + + +def test_from_xml_objtype_picks_up_objname_attr(): + result = _extract_sensor_per_type(_FAKE_SOURCE) + framepos = result["framepos"] + assert framepos["objtype"] == "from_xml" + assert framepos["obj_attr"] == "objname" + assert framepos["ref_attr"] == "refname" + assert framepos["computed"] is False + + +def test_multi_name_branch_emits_one_entry_per_name(): + result = _extract_sensor_per_type(_FAKE_SOURCE) + for name in ("distance", "normal", "fromto"): + assert name in result, f"missing {name}" + assert result[name]["computed"] is True + assert result[name]["objtype"] == "computed" + # All three share the same body1/body2 attr-read. + assert result[name]["obj_attr"] == "body1" + assert result[name]["ref_attr"] == "body2" + + +def test_inner_if_inside_multi_name_branch_does_not_overwrite(): + """Regression: the body of the distance/normal/fromto branch contains + ``if (type == "distance")`` and ``else if (type == "normal")`` which set + only ->type. Those inner matches would override the outer entry's + obj_attr/ref_attr with None if the extractor walked them naively.""" + result = _extract_sensor_per_type(_FAKE_SOURCE) + assert result["distance"]["obj_attr"] == "body1" + assert result["normal"]["obj_attr"] == "body1" + + +def test_clock_has_unknown_objtype_no_name_read(): + result = _extract_sensor_per_type(_FAKE_SOURCE) + assert result["clock"] == { + "mj_type": "mjSENS_CLOCK", + "objtype": "mjOBJ_UNKNOWN", + "reftype": None, + "obj_attr": None, + "ref_attr": None, + "computed": False, + } + + +def test_missing_sensor_method_returns_empty(): + assert _extract_sensor_per_type("// no Sensor method here") == {} + + +# ---------- sensor switch + TagToType codegen ---------------------------- + +def test_sensor_switch_body_emits_static_objtype_when_present(): + from generate_ue_components import _emit_sensor_switch_block # noqa + cat_rules = { + "type_enum_name": "EMjSensorType", + "subtypes": [ + {"key": "touch", "enum_value": "Touch"}, + {"key": "framepos", "enum_value": "FramePos"}, + ], + } + sensor_per_type = { + "touch": {"mj_type": "mjSENS_TOUCH", "objtype": "mjOBJ_SITE", "reftype": None}, + "framepos": {"mj_type": "mjSENS_FRAMEPOS", "objtype": "from_xml", "reftype": None}, + "accelerometer": {"mj_type": "mjSENS_ACCELEROMETER", "objtype": "mjOBJ_SITE", "reftype": None}, + } + out = _emit_sensor_switch_block(cat_rules, sensor_per_type) + # Touch gets static objtype literal. + assert "case EMjSensorType::Touch: Element->type = mjSENS_TOUCH; Element->objtype = mjOBJ_SITE; break;" in out + # framepos has objtype=from_xml -> NO static objtype emitted (handled in post-switch block). + assert "case EMjSensorType::FramePos: Element->type = mjSENS_FRAMEPOS; break;" in out + # Default fallback is hard-wired to accelerometer. + assert "default: Element->type = mjSENS_ACCELEROMETER; Element->objtype = mjOBJ_SITE; break;" in out + + +def test_sensor_switch_body_honours_case_override(): + from generate_ue_components import _emit_sensor_switch_block + cat_rules = { + "type_enum_name": "EMjSensorType", + "subtypes": [ + {"key": "rangefinder", "enum_value": "RangeFinder", + "case_body_override": "Element->type = mjSENS_RANGEFINDER; Element->objtype = X;"}, + ], + } + out = _emit_sensor_switch_block(cat_rules, {"rangefinder": {"mj_type": "mjSENS_RANGEFINDER"}}) + # Override appears verbatim; the emitter's automatic mj_type / objtype + # lines are SKIPPED for this case. + assert "Element->objtype = X;" in out + assert out.count("RangeFinder") >= 1 + + +def test_sensor_tag_to_type_map_uses_xml_key_verbatim(): + from generate_ue_components import _emit_sensor_tag_to_type_block + cat_rules = { + "type_enum_name": "EMjSensorType", + "subtypes": [ + {"key": "touch", "enum_value": "Touch"}, + {"key": "e_potential", "enum_value": "EPotential"}, + {"key": "jointactuatorfrc", "enum_value": "JointActFrc"}, + ], + } + out = _emit_sensor_tag_to_type_block(cat_rules) + assert '{TEXT("touch"), EMjSensorType::Touch},' in out + # Underscore-containing XML keys preserved literally. + assert '{TEXT("e_potential"), EMjSensorType::EPotential},' in out + # XML key and UE enum_value can diverge; map uses XML key. + assert '{TEXT("jointactuatorfrc"), EMjSensorType::JointActFrc},' in out + + +def test_real_snapshot_covers_every_schema_sensor(): + """End-to-end: the snapshot shipped in Scripts/ should have one + per_type entry for every sensor_types entry — and vice versa. Catches + drift between the static MJCF[] schema and the parser cascade.""" + import json + plugin_root = os.path.normpath(os.path.join(_HERE, "..", "..", "..")) + snap = json.load(open(os.path.join(plugin_root, "Scripts", "codegen", "snapshots", "mjcf_schema_snapshot.json"))) + schema_names = set(snap["sensor_types"]) + per_type_names = set(snap.get("sensor_per_type", {}).keys()) + assert schema_names == per_type_names, ( + f"schema/per_type drift: only-in-schema={sorted(schema_names - per_type_names)}; " + f"only-in-per_type={sorted(per_type_names - schema_names)}" + ) diff --git a/Scripts/codegen/tests/test_setto_introspection.py b/Scripts/codegen/tests/test_setto_introspection.py index ace30cc..9206fdf 100644 --- a/Scripts/codegen/tests/test_setto_introspection.py +++ b/Scripts/codegen/tests/test_setto_introspection.py @@ -3,17 +3,16 @@ The 9 hand-written C++ literal blocks that used to live in ``codegen_rules.json`` were replaced by ``_emit_setto_call``, which derives -the call body from the parsed mjs_setTo* signature in -``mjspec_snapshot.json``. This test makes sure the emission keeps producing -functional output for every actuator subtype that has a setTo rule. -""" +the call body from the parsed mjs_setTo* signature. The signature now +comes from the clang-AST introspect snapshot, projected into the +legacy mjspec shape via ``_mjspec_from_introspect``.""" from __future__ import annotations import json import os -from generate_ue_components import _emit_setto_call +from generate_ue_components import _emit_setto_call, _mjspec_from_introspect _HERE = os.path.dirname(os.path.abspath(__file__)) @@ -21,8 +20,8 @@ def _load_mjspec(): - with open(os.path.join(_PLUGIN_ROOT, "Scripts", "mjspec_snapshot.json"), "r") as f: - return json.load(f) + with open(os.path.join(_PLUGIN_ROOT, "Scripts", "codegen", "snapshots", "introspect_snapshot.json"), "r") as f: + return _mjspec_from_introspect(json.load(f)) def _setto_for(subtype_key, real_rules, real_schema, mjspec): diff --git a/Scripts/codegen/tests/test_should_emit_xml_enum_at_layer.py b/Scripts/codegen/tests/test_should_emit_xml_enum_at_layer.py new file mode 100644 index 0000000..8bff7f1 --- /dev/null +++ b/Scripts/codegen/tests/test_should_emit_xml_enum_at_layer.py @@ -0,0 +1,46 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks the two-case ``_should_emit_xml_enum_at_this_layer`` decision +the previous closure inside ``emit_schema_for_attrs`` encoded +implicitly: + - subtype-specific xml_enum attrs fire on the subtype's own emission + - "type"-like globally-excluded xml_enum attrs fire on the base + (apply_canonicalizations=True) layer.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_attr_in_attrs_list_fires_at_any_layer(): + """Subtype case — dcmotor.input is a subtype attr the base doesn't + carry; the subtype layer (apply_canonicalizations=False) owns it.""" + assert gen._should_emit_xml_enum_at_this_layer( + "input", attrs=["input"], global_excl=set(), + apply_canonicalizations=False, + ) + assert gen._should_emit_xml_enum_at_this_layer( + "input", attrs=["input"], global_excl=set(), + apply_canonicalizations=True, + ) + + +def test_globally_excluded_attr_fires_only_on_base_layer(): + """Always-at-base case — joint.type is globally excluded from + per-attr UPROPERTY emission but xml_enum still owns its import/ + export at the base. Subtype layer must NOT re-emit it (would cause + duplicate switch case + UHT shadowing).""" + assert gen._should_emit_xml_enum_at_this_layer( + "type", attrs=[], global_excl={"type"}, + apply_canonicalizations=True, + ) + assert not gen._should_emit_xml_enum_at_this_layer( + "type", attrs=[], global_excl={"type"}, + apply_canonicalizations=False, + ) + + +def test_unrelated_attr_never_fires(): + assert not gen._should_emit_xml_enum_at_this_layer( + "stranger", attrs=["unrelated"], global_excl={"other"}, + apply_canonicalizations=True, + ) diff --git a/Scripts/codegen/tests/test_strict_exit_code.py b/Scripts/codegen/tests/test_strict_exit_code.py new file mode 100644 index 0000000..08c9d0b --- /dev/null +++ b/Scripts/codegen/tests/test_strict_exit_code.py @@ -0,0 +1,42 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Verifies that ``--strict`` (the default) maps fired diagnostics to +exit code 2. ``--no-strict`` lets the same rules surface diagnostics +without failing the run — local-triage workflow. + +These tests drive the public DiagBuffer surface directly rather than +shelling out so they stay deterministic across CI without a libclang +install (the introspect snapshot is read from disk regardless of CI +state).""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def test_strict_exit_2_when_diagnostics_fire(): + """A single diagnostic + ``--strict`` semantics yields exit 2 in + main()'s gate path. We simulate by adding to the buffer, flushing, + and reading the gate's input — ``_DIAGS_BUFFER.fired_count``.""" + gen._reset_diags() + gen._diag_add("[diagnostic] test", source="unit_test") + gen._diag_flush() + fired = gen._DIAGS_BUFFER.fired_count + assert fired == 1 + # The gate in main() is: `if args.strict and fired: return 2`. + # That predicate is true here -> exit code would be 2. + assert fired > 0 + + +def test_strict_exit_0_when_no_diagnostics(): + gen._reset_diags() + gen._diag_flush() + assert gen._DIAGS_BUFFER.fired_count == 0 + + +def test_reset_diags_clears_both_pending_and_fired_count(): + gen._diag_add("[diagnostic] alpha", source="unit_test") + gen._diag_flush() + assert gen._DIAGS_BUFFER.fired_count >= 1 + gen._reset_diags() + assert gen._DIAGS_BUFFER.fired_count == 0 + assert gen._DIAGS_BUFFER.pending == [] diff --git a/Scripts/codegen/tests/test_subclass_emission.py b/Scripts/codegen/tests/test_subclass_emission.py index 01cd157..959bbed 100644 --- a/Scripts/codegen/tests/test_subclass_emission.py +++ b/Scripts/codegen/tests/test_subclass_emission.py @@ -16,13 +16,6 @@ _PLUGIN_ROOT = os.path.abspath(os.path.join(_HERE, "..", "..", "..")) -@pytest.fixture(scope="session") -def real_mjspec(): - """The mjspec snapshot (structs + setto_functions) shipped with the plugin.""" - with open(os.path.join(_PLUGIN_ROOT, "Scripts", "mjspec_snapshot.json"), "r") as f: - return json.load(f) - - def _find_writes(writes, suffix): return [w for w in writes if w.path.endswith(suffix)] diff --git a/Scripts/codegen/tests/test_sync_vendored.py b/Scripts/codegen/tests/test_sync_vendored.py new file mode 100644 index 0000000..95ea959 --- /dev/null +++ b/Scripts/codegen/tests/test_sync_vendored.py @@ -0,0 +1,71 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Unit tests for the manifest parser + formatter in sync_vendored.py. + +Network fetches are NOT exercised here — they need the real GitHub +endpoints. The tests cover only the deterministic-rewrite property +(re-parsing + re-formatting the same content produces the same bytes) +and the column-ordering / sort-by-dest invariants. +""" + +from __future__ import annotations + +import os +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +if _CODEGEN_DIR not in sys.path: + sys.path.insert(0, _CODEGEN_DIR) + +from sync_vendored import ( # noqa: E402 + _parse_manifest, + _format_manifest, + _extract_preamble, +) + + +_SAMPLE = """\ +# Vendored sources + +Preamble paragraph here. + +| file | upstream_url | upstream_sha | retrieved_date | license | local_dest | +|------|--------------|--------------|-----------------|---------|------------| +| foo.h | https://example.com/{sha}/foo.h | abc123 | 2026-01-01 | MIT | Scripts/codegen/_vendored/foo.h | +| bar.h | https://example.com/{sha}/bar.h | def456 | 2026-01-02 | Apache-2.0 | Scripts/codegen/_vendored/bar.h | +""" + + +def test_parse_skips_separator_and_preamble(): + rows = _parse_manifest(_SAMPLE) + assert len(rows) == 2 + assert rows[0]["file"] == "foo.h" + assert rows[0]["upstream_sha"] == "abc123" + assert rows[1]["file"] == "bar.h" + + +def test_extract_preamble_stops_at_first_row(): + pre = _extract_preamble(_SAMPLE) + assert "# Vendored sources" in pre + assert "abc123" not in pre + + +def test_format_sorts_by_local_dest(): + rows = _parse_manifest(_SAMPLE) + out = _format_manifest(rows, "# header\n") + # bar.h comes first because Scripts/.../bar.h < Scripts/.../foo.h + bar_idx = out.index("| bar.h |") + foo_idx = out.index("| foo.h |") + assert bar_idx < foo_idx + + +def test_format_is_deterministic_round_trip(): + """Parse + format + parse + format must produce identical bytes — + that's the merge-conflict-resistance property the manifest design + promises.""" + pre = _extract_preamble(_SAMPLE) + rows = _parse_manifest(_SAMPLE) + once = _format_manifest(rows, pre) + twice = _format_manifest(_parse_manifest(once), _extract_preamble(once)) + assert once == twice diff --git a/Scripts/codegen/tests/test_synthetic_categories.py b/Scripts/codegen/tests/test_synthetic_categories.py new file mode 100644 index 0000000..6ed0d6e --- /dev/null +++ b/Scripts/codegen/tests/test_synthetic_categories.py @@ -0,0 +1,219 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +""" +Tests for the synthetic_categories emitter. + +Emits one banner-mode .h file per entry from an mjxmacro X-macro field +list. Covers MjStatistic, MjOption, the 6 MjVisual_* structs, plus +MjsCompilerOptions and MjsSpec. +""" + +from __future__ import annotations + +import os +import sys + +_HERE = os.path.dirname(os.path.abspath(__file__)) +_CODEGEN_DIR = os.path.dirname(_HERE) +if _CODEGEN_DIR not in sys.path: + sys.path.insert(0, _CODEGEN_DIR) + +from generate_ue_components import ( # noqa: E402 + _emit_synthetic_struct_files, + _ue_field_name, +) + + +def test_ue_field_name_pascal_cases_snake_input(): + assert _ue_field_name("timestep") == "Timestep" + assert _ue_field_name("ls_iterations") == "LsIterations" + assert _ue_field_name("sleep_tolerance") == "SleepTolerance" + # Single component stays capitalised. + assert _ue_field_name("extent") == "Extent" + + +def test_synthetic_struct_emits_uproperty_per_field(): + mjxmacro = { + "struct_fields": { + "TEST_FIELDS": [ + {"type": "mjtNum", "name": "timestep", "count": "1", "is_vec": False}, + {"type": "int", "name": "iterations", "count": "1", "is_vec": False}, + {"type": "float", "name": "gravity", "count": "3", "is_vec": True}, + ], + }, + } + def_ = { + "ue_struct_name": "FTestStruct", + "mjxmacro_block": "TEST_FIELDS", + "c_struct_type": "mjTest", + "public_header": "MuJoCo/Generated/MjTest.h", + "private_source": "MuJoCo/Generated/MjTest.cpp", + "category_label": "Test", + "exclude_fields": [], + "per_field_meta": {}, + "urlab_extra_fields": [], + } + writes = _emit_synthetic_struct_files( + "MjTest", def_, mjxmacro, public_root="/tmp/pub", private_root="/tmp/priv", + ) + assert len(writes) == 1 + h = writes[0].content + # USTRUCT outline. + assert "USTRUCT(BlueprintType)" in h + assert "struct URLAB_API FTestStruct" in h + # Each field gets its toggle + value pair. + assert "bOverride_Timestep" in h + assert "double Timestep" in h + assert "bOverride_Iterations" in h + assert "int32 Iterations" in h + # is_vec + count==3 -> FVector. + assert "FVector Gravity" in h + # Category labels use the rule's category_label. + assert 'Category = "MuJoCo|Test"' in h + # ApplyTo body assigns each field with a static_cast. + assert "Dst.timestep = static_cast(Timestep);" in h + assert "Dst.gravity[0] = static_cast(Gravity.X);" in h + + +def test_synthetic_struct_skips_excluded_fields(): + mjxmacro = { + "struct_fields": { + "TEST_FIELDS": [ + {"type": "int", "name": "keep_me", "count": "1", "is_vec": False}, + {"type": "int", "name": "drop_me", "count": "1", "is_vec": False}, + ], + }, + } + def_ = { + "ue_struct_name": "F", + "mjxmacro_block": "TEST_FIELDS", + "public_header": "P/F.h", + "private_source": "P/F.cpp", + "category_label": "C", + "exclude_fields": ["drop_me"], + "per_field_meta": {}, + } + writes = _emit_synthetic_struct_files("X", def_, mjxmacro, "/tmp/pub", "/tmp/priv") + h = writes[0].content + assert "KeepMe" in h + assert "DropMe" not in h + + +def test_synthetic_struct_field_rename_overrides_default(): + """``field_renames`` lets rules pin a non-default UE name (e.g. URLab's + historical CCD_Iterations vs default CcdIterations).""" + mjxmacro = { + "struct_fields": { + "T_FIELDS": [ + {"type": "int", "name": "ccd_iterations", "count": "1", "is_vec": False}, + ], + }, + } + def_ = { + "ue_struct_name": "FT", + "mjxmacro_block": "T_FIELDS", + "public_header": "P/T.h", + "private_source": "P/T.cpp", + "category_label": "T", + "field_renames": {"ccd_iterations": "CCD_Iterations"}, + } + writes = _emit_synthetic_struct_files("MjT", def_, mjxmacro, "/tmp/pub", "/tmp/priv") + h = writes[0].content + assert "CCD_Iterations" in h + assert "CcdIterations" not in h + + +def test_synthetic_struct_skips_when_mjxmacro_block_missing(): + """Defensive: a typo in mjxmacro_block produces a diagnostic, not a + crash, and emits no file.""" + from generate_ue_components import _DIAGS_BUFFER, _reset_diags + _reset_diags() + mjxmacro = {"struct_fields": {}} + def_ = { + "ue_struct_name": "F", "mjxmacro_block": "NONEXISTENT", + "public_header": "P/F.h", "private_source": "P/F.cpp", + "category_label": "C", + } + writes = _emit_synthetic_struct_files("M", def_, mjxmacro, "/tmp/pub", "/tmp/priv") + assert writes == [] + assert any("NONEXISTENT" in d.message for d in _DIAGS_BUFFER.pending) + _reset_diags() + + +def test_generated_enum_emits_uenum_per_entry(): + from generate_ue_components import _emit_generated_enum_file + mjspec = {"enums": { + "mjtIntegrator": {"mjINT_EULER": 0, "mjINT_RK4": 1, "mjINT_IMPLICIT": 2}, + }} + def_ = { + "public_header": "Generated/MjOptionEnums.h", + "enums": [{ + "ue_name": "EMjIntegrator", + "from_mj_enum": "mjtIntegrator", + "ue_member_from_mj": { + "mjINT_EULER": "Euler", + "mjINT_RK4": "RK4", + "mjINT_IMPLICIT": "Implicit", + }, + }], + } + writes = _emit_generated_enum_file("MjOptionEnums", def_, mjspec, "/tmp/pub") + assert len(writes) == 1 + h = writes[0].content + assert "UENUM(BlueprintType)" in h + assert "enum class EMjIntegrator : uint8" in h + assert "Euler = 0" in h + assert "RK4 = 1" in h + assert "Implicit = 2" in h + + +def test_generated_enum_skips_when_mj_enum_missing(): + from generate_ue_components import _emit_generated_enum_file, _DIAGS_BUFFER, _reset_diags + _reset_diags() + mjspec = {"enums": {}} + def_ = { + "public_header": "P/H.h", + "enums": [{"ue_name": "E", "from_mj_enum": "mjtMissing", "ue_member_from_mj": {}}], + } + writes = _emit_generated_enum_file("X", def_, mjspec, "/tmp/pub") + assert writes == [] + assert any("mjtMissing" in d.message for d in _DIAGS_BUFFER.pending) + _reset_diags() + + +def test_generated_enum_member_without_mapping_silently_skipped(): + """C enums often have sentinel constants (mjNGEOMTYPES) that don't + map to UE. Rule author omits them from ue_member_from_mj; emitter + skips them without diagnostics.""" + from generate_ue_components import _emit_generated_enum_file + mjspec = {"enums": {"mjtX": {"mjX_A": 0, "mjX_SENTINEL": 1, "mjX_B": 2}}} + def_ = { + "public_header": "P/H.h", + "enums": [{ + "ue_name": "EMjX", "from_mj_enum": "mjtX", + "ue_member_from_mj": {"mjX_A": "A", "mjX_B": "B"}, + }], + } + h = _emit_generated_enum_file("X", def_, mjspec, "/tmp/pub")[0].content + assert "A = 0" in h + # B retains its original value 2 (skipped sentinel doesn't renumber). + assert "B = 2" in h + assert "Sentinel" not in h + + +def test_real_snapshot_mjstatistic_pilot(): + """End-to-end: the shipped rule produces a syntactically plausible + .h file. UE compile separately verifies it actually builds.""" + import json + plugin_root = os.path.normpath(os.path.join(_HERE, "..", "..", "..")) + h_path = os.path.join(plugin_root, "Source", "URLab", "Public", + "MuJoCo", "Generated", "MjStatistic.h") + assert os.path.exists(h_path), "MjStatistic.h was not generated" + with open(h_path, "r", encoding="utf-8") as f: + h = f.read() + # Pilot fields from MJSTATISTIC_FIELDS. + for ue_name in ("Meaninertia", "Meanmass", "Meansize", "Extent", "Center"): + assert ue_name in h, f"missing field {ue_name}" + # ApplyTo is templated so it works against both mjStatistic and any + # alias type. Compile correctness is verified by UE's build step. + assert "template " in h + assert "void ApplyTo(TDst& Dst) const" in h diff --git a/Scripts/codegen/tests/test_type_shape_drift.py b/Scripts/codegen/tests/test_type_shape_drift.py new file mode 100644 index 0000000..99c4fd5 --- /dev/null +++ b/Scripts/codegen/tests/test_type_shape_drift.py @@ -0,0 +1,168 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for the type-shape reconcile + new-attr fail-loud checks. + +Covers ``_classify_c_type`` (C-type kind classifier), ``_shapes_compatible`` +(UE-vs-C shape gate), ``_check_type_shape_drift`` (rule-vs-introspect +cross-check), and ``_check_new_attr_typing`` (every schema attr must +be typed or explicitly default-acknowledged).""" + +from __future__ import annotations + +import generate_ue_components as gen +import _codegen_core as _core +import _codegen_checks as _checks + +# Stitch test-only re-exports onto `gen` so the assertions below keep +# their compact ``gen._classify_c_type`` form. The orchestrator's import +# block intentionally no longer carries these — they're private to +# _codegen_core / _codegen_checks. +gen._classify_c_type = _core._classify_c_type +gen._shapes_compatible = _core._shapes_compatible +gen._check_type_shape_drift = _checks._check_type_shape_drift +gen._check_new_attr_typing = _checks._check_new_attr_typing + + +# ---------- _classify_c_type ------------------------------------------------ + +def test_classify_c_type_scalar_num(): + assert gen._classify_c_type("double", None) == ("scalar", "num") + assert gen._classify_c_type("mjtNum", None) == ("scalar", "num") + assert gen._classify_c_type("float", 1) == ("scalar", "num") + + +def test_classify_c_type_vec_dim(): + assert gen._classify_c_type("double [3]", 3) == ("vec", 3) + assert gen._classify_c_type("mjtNum [4]", 4) == ("vec", 4) + + +def test_classify_c_type_dynamic_vec_pointer(): + """mjFloatVec* / mjDoubleVec* are dynamic-length vectors, NOT + opaque pointers — must classify as ('array', None) so TArray + rules match cleanly.""" + assert gen._classify_c_type("mjDoubleVec *", None) == ("array", None) + assert gen._classify_c_type("mjFloatVec *", None) == ("array", None) + + +def test_classify_c_type_opaque_element_pointer(): + """mjsElement* is the parent-spec back-pointer URLab never models; + classify as opaque so the shape check skips it.""" + assert gen._classify_c_type("mjsElement *", None) == ("opaque", None) + + +def test_classify_c_type_string_pointer(): + assert gen._classify_c_type("mjString", None) == ("scalar", "string") + assert gen._classify_c_type("char *", None) == ("scalar", "string") + + +# ---------- _shapes_compatible ---------------------------------------------- + +def test_shapes_compatible_array_matches_vec(): + """TArray at the UE layer is the universal carrier for + fixed-size C arrays — codegen writes prop.Num() elements and the + common case is len(prop) <= C cap.""" + assert gen._shapes_compatible(("array", None), ("vec", 3)) + assert gen._shapes_compatible(("array", None), ("array", None)) + + +def test_shapes_compatible_scalar_vs_array_is_mismatch(): + assert not gen._shapes_compatible(("scalar", "num"), ("vec", 3)) + assert not gen._shapes_compatible(("array", None), ("scalar", "num")) + assert not gen._shapes_compatible(("vec", 3), ("vec", 4)) + + +# ---------- _check_type_shape_drift ---------------------------------------- + +def test_type_shape_drift_flags_scalar_vs_array_mismatch(): + """Rule says TArray but the introspect struct field is a + scalar mjtNum — diagnostic fires; emitted code would not compile + correctly.""" + rules = { + "type_mappings": {"stiffness": "TArray"}, + "categories": { + "joint": {"mjs_struct": "mjsJoint"}, + }, + } + mjspec = { + "introspect": { + "structs": { + "mjsJoint": { + "fields": [ + {"name": "stiffness", "c_type": "double", + "array_dim": None, "is_pointer": False}, + ], + }, + }, + }, + } + gen._check_type_shape_drift({}, rules, mjspec) + assert any("stiffness" in d.message and "mismatch" in d.message + for d in gen._DIAGS_BUFFER.pending) + + +def test_type_shape_drift_quiet_on_unmodeled_field(): + """A field listed in intentionally_unmodeled_mjs_fields is not + emitted by codegen — drift check must NOT fire on it.""" + rules = { + "type_mappings": {"damping": "TArray"}, + "categories": { + "flexcomp": {"mjs_struct": "mjsFlex"}, + }, + "intentionally_unmodeled_mjs_fields": { + "mjsFlex": ["damping"], + }, + } + mjspec = { + "introspect": { + "structs": { + "mjsFlex": { + "fields": [ + {"name": "damping", "c_type": "double", + "array_dim": None, "is_pointer": False}, + ], + }, + }, + }, + } + gen._check_type_shape_drift({}, rules, mjspec) + assert len(gen._DIAGS_BUFFER.pending) == 0 + + +# ---------- _check_new_attr_typing ----------------------------------------- + +def test_new_attr_typing_flags_unmapped_attr(): + schema = { + "joint": {"attrs": ["stiffness", "novel_attr"]}, + } + rules = { + "type_mappings": {"stiffness": "TArray"}, + "default_type": "float", + "global_exclusions": [], + "intentionally_default_typed_attrs": [], + "element_rules": {"joint": {}}, + "canonicalizations": {}, + "categories": { + "joint": {"schema_common_block": "joint.attrs"}, + }, + } + gen._check_new_attr_typing(schema, rules) + msgs = [d.message for d in gen._DIAGS_BUFFER.pending] + assert any("novel_attr" in m and "joint" in m for m in msgs), msgs + # stiffness is typed -> no diag. + assert not any("'stiffness'" in m for m in msgs) + + +def test_new_attr_typing_respects_intentional_default(): + schema = {"sensor": {"attrs": ["cutoff"]}} + rules = { + "type_mappings": {}, + "default_type": "float", + "global_exclusions": [], + "intentionally_default_typed_attrs": ["cutoff"], + "element_rules": {"sensor": {}}, + "canonicalizations": {}, + "categories": { + "sensor": {"schema_common_block": "sensor.attrs"}, + }, + } + gen._check_new_attr_typing(schema, rules) + assert len(gen._DIAGS_BUFFER.pending) == 0 diff --git a/Scripts/codegen/tests/test_ue_type_registry.py b/Scripts/codegen/tests/test_ue_type_registry.py new file mode 100644 index 0000000..2b938e5 --- /dev/null +++ b/Scripts/codegen/tests/test_ue_type_registry.py @@ -0,0 +1,44 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Locks the ``_UE_TYPE_INFO`` registry as the single source of truth +for every UE type codegen emits. Prevents the previous failure mode +where ``_attr_default_value`` / ``_UE_TYPE_FAMILY`` / ``Units``-meta +gates each declared their own type list and drifted apart.""" + +from __future__ import annotations + +from _codegen_core import ( + _UE_TYPE_INFO, _UE_TYPE_FAMILY, _UE_TYPES_ACCEPTING_UNITS_META, + _attr_default_value, _ue_type_accepts_units_meta, +) + + +def test_ue_type_family_is_view_over_registry(): + """``_UE_TYPE_FAMILY`` (drift-check input) must be a faithful view + over ``_UE_TYPE_INFO`` — same keys, same shape values.""" + assert set(_UE_TYPE_FAMILY.keys()) == set(_UE_TYPE_INFO.keys()) + for k, info in _UE_TYPE_INFO.items(): + assert _UE_TYPE_FAMILY[k] == info.shape, k + + +def test_units_meta_set_is_view_over_registry(): + expected = {k for k, v in _UE_TYPE_INFO.items() if v.accepts_units_meta} + assert _UE_TYPES_ACCEPTING_UNITS_META == expected + + +def test_attr_default_value_uses_registry(): + for ue_type, info in _UE_TYPE_INFO.items(): + assert _attr_default_value(ue_type) == info.default_init, ue_type + + +def test_attr_default_value_falls_back_for_novel_tarray(): + """Novel TArray<...> shapes (e.g. TArray) the registry + doesn't enumerate still default-construct empty — the catch-all + stays load-bearing for forward compatibility.""" + assert _attr_default_value("TArray") == "{}" + + +def test_ue_type_accepts_units_meta_matches_registry(): + for ue_type, info in _UE_TYPE_INFO.items(): + assert _ue_type_accepts_units_meta(ue_type) == info.accepts_units_meta, ue_type + # Unknown types must default to "no Units meta" — UHT would reject. + assert _ue_type_accepts_units_meta("UMjFoo*") is False diff --git a/Scripts/codegen/tests/test_view_struct.py b/Scripts/codegen/tests/test_view_struct.py index 8ba7449..52abd65 100644 --- a/Scripts/codegen/tests/test_view_struct.py +++ b/Scripts/codegen/tests/test_view_struct.py @@ -63,3 +63,58 @@ def test_view_has_one_field_per_mjxmacro_entry(real_rules, real_mjxmacro): name = entry["name"] view_name = field_renames.get(name, name) assert f" {view_name};" in fields, f"missing view field for {name} (-> {view_name})" + + +def test_stride_one_int_entries_emit_as_dereferenced_scalars(): + """Single-int entries (stride=="1", type=="int") emit as ``int X`` + with ``X = m->src[id]`` in the bind body — value semantics, not pointer.""" + rules = {"views": {"FooView": { + "obj_type": "mjOBJ_BODY", + "include_blocks": ["FOO_BLOCK"], + }}} + mjxmacro = {"mjmodel_pointers": {"FOO_BLOCK": [ + {"type": "int", "name": "foo_kind", "outer_dim": "nfoo", "stride": "1"}, + {"type": "int", "name": "foo_size_arr", "outer_dim": "nfoo", "stride": "3"}, + {"type": "mjtNum", "name": "foo_pos", "outer_dim": "nfoo", "stride": "3"}, + ]}} + views = emit_view_structs(rules, mjxmacro) + fields, bind = views["FooView"] + # Scalar int — dereferenced, not pointer. + assert " int foo_kind;" in fields + assert " foo_kind = m->foo_kind[id];" in bind + # Int but stride>1 — stays a pointer. + assert " int* foo_size_arr;" in fields + assert " foo_size_arr = m->foo_size_arr + id * 3;" in bind + # mjtNum stride>1 — pointer. + assert " mjtNum* foo_pos;" in fields + assert " foo_pos = m->foo_pos + id * 3;" in bind + + +def test_data_fields_bind_override(): + """``data_fields[name].bind_override`` short-circuits the standard + ``base + index_var * stride`` emit and drops the override verbatim + inside the BIND marker. Used by SensorView::sensordata (bounds-checked + slice) and ActuatorView::act (nullable lookup).""" + rules = {"views": {"BarView": { + "obj_type": "mjOBJ_GEOM", + "include_blocks": [], + "data_fields": { + "_note_skip_me": "comment-only; codegen must skip _note_* keys", + "plain": {"index_var": "id", "stride": "1"}, + "bounds_check": {"bind_override": + "bounds_check = (id < m->nfoo) ? d->bounds_check + id : nullptr;"}, + }, + }}} + mjxmacro = {"mjmodel_pointers": {}} + views = emit_view_structs(rules, mjxmacro) + fields, bind = views["BarView"] + # Standard data_field bind emitted. + assert " mjtNum* plain;" in fields + assert " plain = d->plain + id * 1;" in bind + # bind_override field still declared at the standard cpp_type. + assert " mjtNum* bounds_check;" in fields + # bind_override body dropped verbatim — no base+id*stride. + assert " bounds_check = (id < m->nfoo) ? d->bounds_check + id : nullptr;" in bind + # _note_* keys are documentation, not data fields. + assert "_note_skip_me" not in fields + assert "_note_skip_me" not in bind diff --git a/Scripts/codegen/tests/test_xml_passthrough_emit.py b/Scripts/codegen/tests/test_xml_passthrough_emit.py new file mode 100644 index 0000000..d01d5b3 --- /dev/null +++ b/Scripts/codegen/tests/test_xml_passthrough_emit.py @@ -0,0 +1,75 @@ +# Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +"""Tests for ``emit_xml_passthrough_body``. Categories with +``xml_passthrough_emission: true`` (flexcomp) build an MJCF XML string +instead of writing through the mjs spec API — the codegen owns the +per-attr formatter so a new schema attr flows end-to-end. The body +emits ``name="value"`` substrings for every override-tracked +UPROPERTY.""" + +from __future__ import annotations + +import generate_ue_components as gen + + +def _rules(attr: str, ue_type: str) -> dict: + return { + "default_type": "float", + "type_mappings": {attr: ue_type}, + "element_rules": {"thing": {}}, + } + + +def test_float_attr_emits_printf_with_toggle_guard(): + body = gen.emit_xml_passthrough_body(["stiffness"], _rules("stiffness", "float"), element_name="thing") + assert "FString Out;" in body + assert "if (bOverride_stiffness)" in body + assert '" stiffness=\\"%f\\""' in body + assert "return Out;" in body + + +def test_int32_attr_emits_printf_with_d_format(): + body = gen.emit_xml_passthrough_body(["group"], _rules("group", "int32"), element_name="thing") + assert "if (bOverride_group)" in body + assert '" group=\\"%d\\""' in body + + +def test_bool_attr_emits_ternary_string(): + body = gen.emit_xml_passthrough_body(["limited"], _rules("limited", "bool"), element_name="thing") + assert 'TEXT("true") : TEXT("false")' in body + assert '" limited=\\"%s\\""' in body + + +def test_tarray_float_emits_space_separated_loop(): + body = gen.emit_xml_passthrough_body(["range"], _rules("range", "TArray"), element_name="thing") + assert "if (bOverride_range && range.Num() > 0)" in body + assert "for (int32 i = 0; i < range.Num(); ++i)" in body + assert 'if (i > 0) Out += TEXT(" ");' in body + + +def test_flinearcolor_emits_four_component_format(): + body = gen.emit_xml_passthrough_body(["rgba"], _rules("rgba", "FLinearColor"), element_name="thing") + assert "rgba.R" in body and "rgba.G" in body and "rgba.B" in body and "rgba.A" in body + assert '" rgba=\\"%f %f %f %f\\""' in body + + +def test_name_attr_is_skipped_by_caller_owned_logic(): + """The caller handles ``name`` (prefix / MjName logic); the body must + not duplicate it.""" + body = gen.emit_xml_passthrough_body(["name", "stiffness"], _rules("stiffness", "float"), element_name="thing") + assert '" name=' not in body + assert "stiffness" in body + + +def test_global_exclusion_skips_attr(): + rules = {**_rules("stiffness", "float"), "global_exclusions": ["stiffness"]} + body = gen.emit_xml_passthrough_body(["stiffness", "group"], rules, element_name="thing") + assert "stiffness" not in body + # 'group' still passes if it's typed (it isn't here -> falls back to default_type 'float'). + + +def test_unsupported_type_emits_todo_marker(): + """Novel UE types produce a TODO comment so a reviewer sees the gap + instead of a silent missing attr.""" + body = gen.emit_xml_passthrough_body(["mystery"], _rules("mystery", "FQuat"), element_name="thing") + assert "TODO(xml_passthrough)" in body + assert '"mystery"' in body and "FQuat" in body diff --git a/Scripts/mjspec_snapshot.json b/Scripts/mjspec_snapshot.json deleted file mode 100644 index 64531d0..0000000 --- a/Scripts/mjspec_snapshot.json +++ /dev/null @@ -1,693 +0,0 @@ -{ - "structs": { - "mjsElement": [ - "elemtype", - "signature" - ], - "mjsCompiler": [ - "autolimits", - "boundmass", - "boundinertia", - "settotalmass", - "balanceinertia", - "fitaabb", - "degree", - "eulerseq", - "discardvisual", - "usethread", - "fusestatic", - "inertiafromgeom", - "inertiagrouprange", - "saveinertial", - "alignfree", - "LRopt", - "meshdir", - "texturedir" - ], - "mjsOrientation": [ - "type", - "axisangle", - "xyaxes", - "zaxis", - "euler" - ], - "mjsPlugin": [ - "element", - "name", - "plugin_name", - "active", - "info" - ], - "mjsBody": [ - "element", - "childclass", - "pos", - "quat", - "alt", - "mass", - "ipos", - "iquat", - "inertia", - "ialt", - "fullinertia", - "mocap", - "gravcomp", - "sleep", - "userdata", - "explicitinertial", - "plugin", - "info" - ], - "mjsFrame": [ - "element", - "childclass", - "pos", - "quat", - "alt", - "info" - ], - "mjsJoint": [ - "element", - "type", - "pos", - "axis", - "ref", - "align", - "stiffness", - "springref", - "springdamper", - "limited", - "range", - "margin", - "solref_limit", - "solimp_limit", - "actfrclimited", - "actfrcrange", - "armature", - "damping", - "frictionloss", - "solref_friction", - "solimp_friction", - "group", - "actgravcomp", - "userdata", - "info" - ], - "mjsGeom": [ - "element", - "type", - "pos", - "quat", - "alt", - "fromto", - "size", - "contype", - "conaffinity", - "condim", - "priority", - "friction", - "solmix", - "solref", - "solimp", - "margin", - "gap", - "mass", - "density", - "typeinertia", - "fluid_ellipsoid", - "fluid_coefs", - "material", - "rgba", - "group", - "hfieldname", - "meshname", - "fitscale", - "userdata", - "plugin", - "info" - ], - "mjsSite": [ - "element", - "pos", - "quat", - "alt", - "fromto", - "size", - "type", - "material", - "group", - "rgba", - "userdata", - "info" - ], - "mjsCamera": [ - "element", - "pos", - "quat", - "alt", - "mode", - "targetbody", - "proj", - "resolution", - "output", - "fovy", - "ipd", - "intrinsic", - "sensor_size", - "focal_length", - "focal_pixel", - "principal_length", - "principal_pixel", - "userdata", - "info" - ], - "mjsLight": [ - "element", - "pos", - "dir", - "mode", - "targetbody", - "active", - "type", - "texture", - "castshadow", - "bulbradius", - "intensity", - "range", - "attenuation", - "cutoff", - "exponent", - "ambient", - "diffuse", - "specular", - "info" - ], - "mjsFlex": [ - "element", - "contype", - "conaffinity", - "condim", - "priority", - "friction", - "solmix", - "solref", - "solimp", - "margin", - "gap", - "dim", - "radius", - "size", - "internal", - "flatskin", - "selfcollide", - "passive", - "activelayers", - "group", - "edgestiffness", - "edgedamping", - "rgba", - "material", - "young", - "poisson", - "damping", - "thickness", - "elastic2d", - "cellcount", - "order", - "nodebody", - "vertbody", - "node", - "vert", - "elem", - "texcoord", - "elemtexcoord", - "info" - ], - "mjsMesh": [ - "element", - "content_type", - "file", - "refpos", - "refquat", - "scale", - "inertia", - "smoothnormal", - "needsdf", - "maxhullvert", - "uservert", - "usernormal", - "usertexcoord", - "userface", - "userfacenormal", - "userfacetexcoord", - "plugin", - "material", - "octree_maxdepth", - "info" - ], - "mjsHField": [ - "element", - "content_type", - "file", - "size", - "nrow", - "ncol", - "userdata", - "info" - ], - "mjsSkin": [ - "element", - "file", - "material", - "rgba", - "inflate", - "group", - "vert", - "texcoord", - "face", - "bodyname", - "bindpos", - "bindquat", - "vertid", - "vertweight", - "info" - ], - "mjsTexture": [ - "element", - "type", - "colorspace", - "builtin", - "mark", - "rgb1", - "rgb2", - "markrgb", - "random", - "height", - "width", - "nchannel", - "content_type", - "file", - "gridsize", - "gridlayout", - "cubefiles", - "data", - "hflip", - "vflip", - "info" - ], - "mjsMaterial": [ - "element", - "textures", - "texuniform", - "texrepeat", - "emission", - "specular", - "shininess", - "reflectance", - "metallic", - "roughness", - "rgba", - "info" - ], - "mjsPair": [ - "element", - "geomname1", - "geomname2", - "condim", - "solref", - "solreffriction", - "solimp", - "margin", - "gap", - "friction", - "info" - ], - "mjsExclude": [ - "element", - "bodyname1", - "bodyname2", - "info" - ], - "mjsEquality": [ - "element", - "type", - "data", - "active", - "name1", - "name2", - "objtype", - "solref", - "solimp", - "info" - ], - "mjsTendon": [ - "element", - "stiffness", - "springlength", - "damping", - "frictionloss", - "solref_friction", - "solimp_friction", - "armature", - "limited", - "actfrclimited", - "range", - "actfrcrange", - "margin", - "solref_limit", - "solimp_limit", - "material", - "width", - "rgba", - "group", - "userdata", - "info" - ], - "mjsWrap": [ - "element", - "type", - "info" - ], - "mjsActuator": [ - "element", - "gaintype", - "gainprm", - "biastype", - "biasprm", - "dyntype", - "dynprm", - "actdim", - "actearly", - "trntype", - "gear", - "target", - "refsite", - "slidersite", - "cranklength", - "lengthrange", - "inheritrange", - "damping", - "armature", - "ctrllimited", - "ctrlrange", - "forcelimited", - "forcerange", - "actlimited", - "actrange", - "group", - "nsample", - "interp", - "delay", - "userdata", - "plugin", - "info" - ], - "mjsSensor": [ - "element", - "type", - "objtype", - "objname", - "reftype", - "refname", - "intprm", - "datatype", - "needstage", - "dim", - "cutoff", - "noise", - "nsample", - "interp", - "delay", - "interval", - "userdata", - "plugin", - "info" - ], - "mjsNumeric": [ - "element", - "data", - "size", - "info" - ], - "mjsText": [ - "element", - "data", - "info" - ], - "mjsTuple": [ - "element", - "objtype", - "objname", - "objprm", - "info" - ], - "mjsKey": [ - "element", - "time", - "qpos", - "qvel", - "act", - "mpos", - "mquat", - "ctrl", - "info" - ], - "mjsDefault": [ - "element", - "joint", - "geom", - "site", - "camera", - "light", - "flex", - "mesh", - "material", - "pair", - "equality", - "tendon", - "actuator" - ] - }, - "setto_functions": { - "mjs_setToMotor": { - "params": [] - }, - "mjs_setToPosition": { - "params": [ - { - "name": "kp", - "c_type": "double", - "array_dim": null - }, - { - "name": "kv", - "c_type": "double", - "array_dim": 1 - }, - { - "name": "dampratio", - "c_type": "double", - "array_dim": 1 - }, - { - "name": "timeconst", - "c_type": "double", - "array_dim": 1 - }, - { - "name": "inheritrange", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToIntVelocity": { - "params": [ - { - "name": "kp", - "c_type": "double", - "array_dim": null - }, - { - "name": "kv", - "c_type": "double", - "array_dim": 1 - }, - { - "name": "dampratio", - "c_type": "double", - "array_dim": 1 - }, - { - "name": "timeconst", - "c_type": "double", - "array_dim": 1 - }, - { - "name": "inheritrange", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToVelocity": { - "params": [ - { - "name": "kv", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToDamper": { - "params": [ - { - "name": "kv", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToCylinder": { - "params": [ - { - "name": "timeconst", - "c_type": "double", - "array_dim": null - }, - { - "name": "bias", - "c_type": "double", - "array_dim": null - }, - { - "name": "area", - "c_type": "double", - "array_dim": null - }, - { - "name": "diameter", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToMuscle": { - "params": [ - { - "name": "timeconst", - "c_type": "double", - "array_dim": 2 - }, - { - "name": "tausmooth", - "c_type": "double", - "array_dim": null - }, - { - "name": "range", - "c_type": "double", - "array_dim": 2 - }, - { - "name": "force", - "c_type": "double", - "array_dim": null - }, - { - "name": "scale", - "c_type": "double", - "array_dim": null - }, - { - "name": "lmin", - "c_type": "double", - "array_dim": null - }, - { - "name": "lmax", - "c_type": "double", - "array_dim": null - }, - { - "name": "vmax", - "c_type": "double", - "array_dim": null - }, - { - "name": "fpmax", - "c_type": "double", - "array_dim": null - }, - { - "name": "fvmax", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToAdhesion": { - "params": [ - { - "name": "gain", - "c_type": "double", - "array_dim": null - } - ] - }, - "mjs_setToDCMotor": { - "params": [ - { - "name": "motorconst", - "c_type": "double", - "array_dim": 2 - }, - { - "name": "resistance", - "c_type": "double", - "array_dim": null - }, - { - "name": "nominal", - "c_type": "double", - "array_dim": 3 - }, - { - "name": "saturation", - "c_type": "double", - "array_dim": 3 - }, - { - "name": "inductance", - "c_type": "double", - "array_dim": 2 - }, - { - "name": "cogging", - "c_type": "double", - "array_dim": 3 - }, - { - "name": "controller", - "c_type": "double", - "array_dim": 6 - }, - { - "name": "thermal", - "c_type": "double", - "array_dim": 6 - }, - { - "name": "lugre", - "c_type": "double", - "array_dim": 5 - }, - { - "name": "input_mode", - "c_type": "int", - "array_dim": null - } - ] - } - } -} \ No newline at end of file diff --git a/Source/URLab/Private/MuJoCo/Components/Actuators/MjActuator.cpp b/Source/URLab/Private/MuJoCo/Components/Actuators/MjActuator.cpp index eb41488..2205fb2 100644 --- a/Source/URLab/Private/MuJoCo/Components/Actuators/MjActuator.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Actuators/MjActuator.cpp @@ -21,6 +21,7 @@ // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. #include "MuJoCo/Components/Actuators/MjActuator.h" +#include "MuJoCo/Utils/MjUtils.h" #include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" #include "MuJoCo/Core/AMjManager.h" @@ -53,7 +54,7 @@ void UMjActuator::ExportTo(mjsActuator* Element, mjsDefault* Default) if (!Element) return; // --- CODEGEN_EXPORT_START --- - if (!TargetName.IsEmpty()) mjs_setString(Element->target, TCHAR_TO_UTF8(*TargetName)); + MjSetString(Element->target, TargetName); switch (TransmissionType) { case EMjActuatorTrnType::Joint: Element->trntype = mjTRN_JOINT; break; @@ -66,11 +67,11 @@ void UMjActuator::ExportTo(mjsActuator* Element, mjsDefault* Default) } if (TransmissionType == EMjActuatorTrnType::SliderCrank && !SliderSite.IsEmpty()) { - mjs_setString(Element->slidersite, TCHAR_TO_UTF8(*SliderSite)); + MjSetStringRaw(Element->slidersite, SliderSite); } if (TransmissionType == EMjActuatorTrnType::Site && !RefSite.IsEmpty()) { - mjs_setString(Element->refsite, TCHAR_TO_UTF8(*RefSite)); + MjSetStringRaw(Element->refsite, RefSite); } if (bOverride_GainType) { @@ -114,17 +115,17 @@ void UMjActuator::ExportTo(mjsActuator* Element, mjsDefault* Default) if (bOverride_ctrllimited) Element->ctrllimited = ctrllimited ? 1 : 0; if (bOverride_forcelimited) Element->forcelimited = forcelimited ? 1 : 0; if (bOverride_actlimited) Element->actlimited = actlimited ? 1 : 0; - if (bOverride_ctrlrange) { for (int32 i = 0; i < ctrlrange.Num(); ++i) Element->ctrlrange[i] = ctrlrange[i]; } - if (bOverride_forcerange) { for (int32 i = 0; i < forcerange.Num(); ++i) Element->forcerange[i] = forcerange[i]; } - if (bOverride_actrange) { for (int32 i = 0; i < actrange.Num(); ++i) Element->actrange[i] = actrange[i]; } - if (bOverride_lengthrange) { for (int32 i = 0; i < lengthrange.Num(); ++i) Element->lengthrange[i] = lengthrange[i]; } - if (bOverride_gear) { for (int32 i = 0; i < gear.Num(); ++i) Element->gear[i] = gear[i]; } - if (bOverride_damping) { for (int32 i = 0; i < damping.Num(); ++i) Element->damping[i] = damping[i]; } + if (bOverride_ctrlrange) { for (int32 i = 0; i < FMath::Min(ctrlrange.Num(), 2); ++i) Element->ctrlrange[i] = ctrlrange[i]; } + if (bOverride_forcerange) { for (int32 i = 0; i < FMath::Min(forcerange.Num(), 2); ++i) Element->forcerange[i] = forcerange[i]; } + if (bOverride_actrange) { for (int32 i = 0; i < FMath::Min(actrange.Num(), 2); ++i) Element->actrange[i] = actrange[i]; } + if (bOverride_lengthrange) { for (int32 i = 0; i < FMath::Min(lengthrange.Num(), 2); ++i) Element->lengthrange[i] = lengthrange[i]; } + if (bOverride_gear) { for (int32 i = 0; i < FMath::Min(gear.Num(), 6); ++i) Element->gear[i] = gear[i]; } + if (bOverride_damping) { for (int32 i = 0; i < FMath::Min(damping.Num(), 3); ++i) Element->damping[i] = damping[i]; } if (bOverride_armature) Element->armature = armature; if (bOverride_cranklength) Element->cranklength = cranklength; - if (bOverride_gainprm) { for (int32 i = 0; i < gainprm.Num(); ++i) Element->gainprm[i] = gainprm[i]; } - if (bOverride_biasprm) { for (int32 i = 0; i < biasprm.Num(); ++i) Element->biasprm[i] = biasprm[i]; } - if (bOverride_dynprm) { for (int32 i = 0; i < dynprm.Num(); ++i) Element->dynprm[i] = dynprm[i]; } + if (bOverride_gainprm) { for (int32 i = 0; i < FMath::Min(gainprm.Num(), 10); ++i) Element->gainprm[i] = gainprm[i]; } + if (bOverride_biasprm) { for (int32 i = 0; i < FMath::Min(biasprm.Num(), 10); ++i) Element->biasprm[i] = biasprm[i]; } + if (bOverride_dynprm) { for (int32 i = 0; i < FMath::Min(dynprm.Num(), 10); ++i) Element->dynprm[i] = dynprm[i]; } if (bOverride_actdim) Element->actdim = actdim; // --- CODEGEN_EXPORT_END --- } @@ -135,34 +136,38 @@ void UMjActuator::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& if (!Node) return; // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); { // xml_enum: gaintype -> EMjGainType FString S = Node->GetAttribute(TEXT("gaintype")); S = S.ToLower(); - if (S == TEXT("fixed")) GainType = EMjGainType::Fixed; - else if (S == TEXT("affine")) GainType = EMjGainType::Affine; - else if (S == TEXT("muscle")) GainType = EMjGainType::Muscle; - else if (S == TEXT("user")) GainType = EMjGainType::User; - if (!S.IsEmpty()) bOverride_GainType = true; + bool bMatched = false; + if (S == TEXT("fixed")) { GainType = EMjGainType::Fixed; bMatched = true; } + else if (S == TEXT("affine")) { GainType = EMjGainType::Affine; bMatched = true; } + else if (S == TEXT("muscle")) { GainType = EMjGainType::Muscle; bMatched = true; } + else if (S == TEXT("user")) { GainType = EMjGainType::User; bMatched = true; } + if (bMatched) bOverride_GainType = true; } { // xml_enum: biastype -> EMjBiasType FString S = Node->GetAttribute(TEXT("biastype")); S = S.ToLower(); - if (S == TEXT("none")) BiasType = EMjBiasType::None; - else if (S == TEXT("affine")) BiasType = EMjBiasType::Affine; - else if (S == TEXT("muscle")) BiasType = EMjBiasType::Muscle; - else if (S == TEXT("user")) BiasType = EMjBiasType::User; - if (!S.IsEmpty()) bOverride_BiasType = true; + bool bMatched = false; + if (S == TEXT("none")) { BiasType = EMjBiasType::None; bMatched = true; } + else if (S == TEXT("affine")) { BiasType = EMjBiasType::Affine; bMatched = true; } + else if (S == TEXT("muscle")) { BiasType = EMjBiasType::Muscle; bMatched = true; } + else if (S == TEXT("user")) { BiasType = EMjBiasType::User; bMatched = true; } + if (bMatched) bOverride_BiasType = true; } { // xml_enum: dyntype -> EMjDynType FString S = Node->GetAttribute(TEXT("dyntype")); S = S.ToLower(); - if (S == TEXT("none")) DynType = EMjDynType::None; - else if (S == TEXT("integrator")) DynType = EMjDynType::Integrator; - else if (S == TEXT("filter")) DynType = EMjDynType::Filter; - else if (S == TEXT("filterexact")) DynType = EMjDynType::FilterExact; - else if (S == TEXT("muscle")) DynType = EMjDynType::Muscle; - else if (S == TEXT("user")) DynType = EMjDynType::User; - if (!S.IsEmpty()) bOverride_DynType = true; + bool bMatched = false; + if (S == TEXT("none")) { DynType = EMjDynType::None; bMatched = true; } + else if (S == TEXT("integrator")) { DynType = EMjDynType::Integrator; bMatched = true; } + else if (S == TEXT("filter")) { DynType = EMjDynType::Filter; bMatched = true; } + else if (S == TEXT("filterexact")) { DynType = EMjDynType::FilterExact; bMatched = true; } + else if (S == TEXT("muscle")) { DynType = EMjDynType::Muscle; bMatched = true; } + else if (S == TEXT("user")) { DynType = EMjDynType::User; bMatched = true; } + if (bMatched) bOverride_DynType = true; } MjXmlUtils::ReadAttrInt(Node, TEXT("group"), group, bOverride_group); MjXmlUtils::ReadAttrInt(Node, TEXT("nsample"), nsample, bOverride_nsample); @@ -200,40 +205,33 @@ void UMjActuator::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& TransmissionType = EMjActuatorTrnType::Tendon; TargetName = TrnTarget; } - if (MjXmlUtils::ReadAttrString(Node, TEXT("slidersite"), SliderSite)) - { - TransmissionType = EMjActuatorTrnType::SliderCrank; - } if (MjXmlUtils::ReadAttrString(Node, TEXT("site"), TrnTarget)) { TransmissionType = EMjActuatorTrnType::Site; TargetName = TrnTarget; } - MjXmlUtils::ReadAttrString(Node, TEXT("refsite"), RefSite); if (MjXmlUtils::ReadAttrString(Node, TEXT("body"), TrnTarget)) { TransmissionType = EMjActuatorTrnType::Body; TargetName = TrnTarget; } + MjXmlUtils::ReadAttrString(Node, TEXT("refsite"), RefSite); + // SliderSite must run AFTER the main-target reads so it + // overrides the transmission type while preserving the + // TargetName captured above (per MJCF: slider-crank carries + // a main target attr PLUS slidersite). + if (MjXmlUtils::ReadAttrString(Node, TEXT("slidersite"), SliderSite)) + { + TransmissionType = EMjActuatorTrnType::SliderCrank; + } } // --- CODEGEN_IMPORT_END --- - - MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); } void UMjActuator::Bind(mjModel* Model, mjData* Data, const FString& Prefix) { Super::Bind(Model, Data, Prefix); - m_ActuatorView = BindToView(Prefix); - - if (m_ActuatorView.id != -1) - { - m_ID = m_ActuatorView.id; - } - else - { - UE_LOG(LogURLabBind, Warning, TEXT("[MjActuator] Actuator '%s' could not bind! Prefix: %s"), *GetName(), *Prefix); - } + BindAndCacheView(m_ActuatorView, Prefix); } // ---------------------------------------------------------------------------------- @@ -288,38 +286,38 @@ float UMjActuator::ResolveDesiredControl(uint8 Source) const float UMjActuator::GetForce() const { - if (m_ActuatorView.id != -1 && m_ActuatorView.force) + if (m_ActuatorView.id != -1 && m_ActuatorView.actuator_force) { - return (float)m_ActuatorView.force[0]; + return (float)m_ActuatorView.actuator_force[0]; } return 0.0f; } float UMjActuator::GetLength() const { - if (m_ActuatorView.id != -1 && m_ActuatorView.length) + if (m_ActuatorView.id != -1 && m_ActuatorView.actuator_length) { - return (float)m_ActuatorView.length[0]; + return (float)m_ActuatorView.actuator_length[0]; } return 0.0f; } float UMjActuator::GetVelocity() const { - if (m_ActuatorView.id != -1 && m_ActuatorView.velocity) + if (m_ActuatorView.id != -1 && m_ActuatorView.actuator_velocity) { - return (float)m_ActuatorView.velocity[0]; + return (float)m_ActuatorView.actuator_velocity[0]; } return 0.0f; } void UMjActuator::SetGear(const TArray& NewGear) { - if (m_ActuatorView.id != -1 && m_ActuatorView.gear) + if (m_ActuatorView.id != -1 && m_ActuatorView.actuator_gear) { for(int i=0; i& NewGear) TArray UMjActuator::GetGear() const { TArray Res; - if (m_ActuatorView.id != -1 && m_ActuatorView.gear) + if (m_ActuatorView.id != -1 && m_ActuatorView.actuator_gear) { - for(int i=0; i<6; ++i) Res.Add((float)m_ActuatorView.gear[i]); + for(int i=0; i<6; ++i) Res.Add((float)m_ActuatorView.actuator_gear[i]); } return Res; } FVector2D UMjActuator::GetControlRange() const { - if (m_ActuatorView.id < 0 || !m_ActuatorView.ctrlrange) return FVector2D::ZeroVector; - return FVector2D((float)m_ActuatorView.ctrlrange[0], (float)m_ActuatorView.ctrlrange[1]); + if (m_ActuatorView.id < 0 || !m_ActuatorView.actuator_ctrlrange) return FVector2D::ZeroVector; + return FVector2D((float)m_ActuatorView.actuator_ctrlrange[0], (float)m_ActuatorView.actuator_ctrlrange[1]); } float UMjActuator::GetActivation() const @@ -403,19 +401,10 @@ TArray UMjActuator::GetTargetNameOptions() const return GetSiblingComponentOptions(this, FilterClass); } -TArray UMjActuator::GetSliderSiteOptions() const -{ - return GetSiblingComponentOptions(this, UMjSite::StaticClass()); -} - -TArray UMjActuator::GetRefSiteOptions() const -{ - return GetSiblingComponentOptions(this, UMjSite::StaticClass()); -} - -TArray UMjActuator::GetDefaultClassOptions() const -{ - return GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjActuator::GetSliderSiteOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjSite::StaticClass()); } +TArray UMjActuator::GetRefSiteOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjSite::StaticClass()); } +TArray UMjActuator::GetDefaultClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Actuators/MjDcMotorActuator.cpp b/Source/URLab/Private/MuJoCo/Components/Actuators/MjDcMotorActuator.cpp index ac69092..36bc074 100644 --- a/Source/URLab/Private/MuJoCo/Components/Actuators/MjDcMotorActuator.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Actuators/MjDcMotorActuator.cpp @@ -79,10 +79,11 @@ void UMjDcMotorActuator::ImportFromXml(const FXmlNode* Node, const FMjCompilerSe { // xml_enum: input -> EMjDcMotorInput FString S = Node->GetAttribute(TEXT("input")); S = S.ToLower(); - if (S == TEXT("voltage")) input = EMjDcMotorInput::Voltage; - else if (S == TEXT("position")) input = EMjDcMotorInput::Position; - else if (S == TEXT("velocity")) input = EMjDcMotorInput::Velocity; - if (!S.IsEmpty()) bOverride_input = true; + bool bMatched = false; + if (S == TEXT("voltage")) { input = EMjDcMotorInput::Voltage; bMatched = true; } + else if (S == TEXT("position")) { input = EMjDcMotorInput::Position; bMatched = true; } + else if (S == TEXT("velocity")) { input = EMjDcMotorInput::Velocity; bMatched = true; } + if (bMatched) bOverride_input = true; } MjXmlUtils::ReadAttrFloatArray(Node, TEXT("motorconst"), motorconst, bOverride_motorconst); MjXmlUtils::ReadAttrFloat(Node, TEXT("resistance"), resistance, bOverride_resistance); diff --git a/Source/URLab/Private/MuJoCo/Components/Actuators/MjGeneralActuator.cpp b/Source/URLab/Private/MuJoCo/Components/Actuators/MjGeneralActuator.cpp index 1d664ce..23c5315 100644 --- a/Source/URLab/Private/MuJoCo/Components/Actuators/MjGeneralActuator.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Actuators/MjGeneralActuator.cpp @@ -41,7 +41,7 @@ void UMjGeneralActuator::ExportTo(mjsActuator* Element, mjsDefault* def) // --- CODEGEN_EXPORT_START --- if (bOverride_actearly) Element->actearly = actearly ? 1 : 0; - // --- CODEGEN_EXPORT_END --- + // --- CODEGEN_EXPORT_END --- } void UMjGeneralActuator::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) diff --git a/Source/URLab/Private/MuJoCo/Components/Actuators/MjMotorActuator.cpp b/Source/URLab/Private/MuJoCo/Components/Actuators/MjMotorActuator.cpp index 81d5efb..ec4fe36 100644 --- a/Source/URLab/Private/MuJoCo/Components/Actuators/MjMotorActuator.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Actuators/MjMotorActuator.cpp @@ -44,7 +44,6 @@ void UMjMotorActuator::ImportFromXml(const FXmlNode* Node, const FMjCompilerSett if (!Node) return; // --- CODEGEN_IMPORT_START --- - // --- CODEGEN_IMPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Bodies/MjBody.cpp b/Source/URLab/Private/MuJoCo/Components/Bodies/MjBody.cpp index 457b5e5..29bcfaf 100644 --- a/Source/URLab/Private/MuJoCo/Components/Bodies/MjBody.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Bodies/MjBody.cpp @@ -97,11 +97,11 @@ void UMjBody::ExportTo(mjsBody* Element, mjsDefault* Default) if (!Element) return; // --- CODEGEN_EXPORT_START --- - if (SleepPolicy != EMjBodySleepPolicy::Default) + if (bOverride_SleepPolicy) { Element->sleep = static_cast(static_cast(SleepPolicy)); } - if (bOverride_childclass && !childclass.IsEmpty()) mjs_setString(Element->childclass, TCHAR_TO_UTF8(*childclass)); + if (bOverride_childclass) MjSetString(Element->childclass, childclass); if (bOverride_mocap) Element->mocap = mocap ? 1 : 0; if (bOverride_gravcomp) Element->gravcomp = gravcomp; // --- CODEGEN_EXPORT_END --- @@ -228,6 +228,7 @@ void UMjBody::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com if (!Node) return; // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("name"), MjName); if (MjXmlUtils::ReadAttrString(Node, TEXT("childclass"), childclass)) bOverride_childclass = true; MjXmlUtils::ReadAttrBool(Node, TEXT("mocap"), mocap, bOverride_mocap); MjXmlUtils::ReadAttrFloat(Node, TEXT("gravcomp"), gravcomp, bOverride_gravcomp); @@ -240,19 +241,16 @@ void UMjBody::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com bOverride_Quat = true; } } - { // canonicalize body.sleep -> EMjBodySleepPolicy + { // canonicalize body.sleep -> EMjBodySleepPolicy + bOverride_SleepPolicy FString S = Node->GetAttribute(TEXT("sleep")); S = S.ToLower(); - if (S == TEXT("never")) SleepPolicy = EMjBodySleepPolicy::Never; - else if (S == TEXT("allowed")) SleepPolicy = EMjBodySleepPolicy::Allowed; - else if (S == TEXT("init")) SleepPolicy = EMjBodySleepPolicy::InitAsleep; + if (S == TEXT("never")) { SleepPolicy = EMjBodySleepPolicy::Never; bOverride_SleepPolicy = true; } + else if (S == TEXT("allowed")) { SleepPolicy = EMjBodySleepPolicy::Allowed; bOverride_SleepPolicy = true; } + else if (S == TEXT("init")) { SleepPolicy = EMjBodySleepPolicy::InitAsleep; bOverride_SleepPolicy = true; } } if (bOverride_Pos) SetRelativeLocation(Pos); if (bOverride_Quat) SetRelativeRotation(Quat); - // --- CODEGEN_IMPORT_END --- - - // name attribute → store in MjName for explicit override - MjXmlUtils::ReadAttrString(Node, TEXT("name"), MjName); + // --- CODEGEN_IMPORT_END --- } void UMjBody::Bind(mjModel* Model, mjData* Data, const FString& Prefix) @@ -261,22 +259,13 @@ void UMjBody::Bind(mjModel* Model, mjData* Data, const FString& Prefix) if (Model && Data) { - m_BodyView = BindToView(Prefix); + BindAndCacheView(m_BodyView, Prefix); - if (m_BodyView.id != -1) - { - m_ID = m_BodyView.id; - m_IsSetup = true; - SetComponentTickEnabled(true); - } - else - { - UE_LOG(LogURLabBind, Warning, TEXT("MjBody::Bind() - FAILED to find body '%s'"), *GetName()); - m_IsSetup = false; - SetComponentTickEnabled(false); - } + const bool bBound = m_BodyView.id != -1; + m_IsSetup = bBound; + SetComponentTickEnabled(bBound); - if (mocap && m_ID >= 0) + if (bBound && mocap) { int mocapid = Model->body_mocapid[m_ID]; if (mocapid >= 0) @@ -432,8 +421,7 @@ void UMjBody::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody) } #if WITH_EDITOR -TArray UMjBody::GetChildClassOptions() const -{ - return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjBody::GetChildClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Bodies/MjFrame.cpp b/Source/URLab/Private/MuJoCo/Components/Bodies/MjFrame.cpp index 5ca3fb0..7fa6093 100644 --- a/Source/URLab/Private/MuJoCo/Components/Bodies/MjFrame.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Bodies/MjFrame.cpp @@ -64,7 +64,7 @@ void UMjFrame::ExportTo(mjsFrame* Element, mjsDefault* Default) if (!Element) return; // --- CODEGEN_EXPORT_START --- - if (bOverride_childclass && !childclass.IsEmpty()) mjs_setString(Element->childclass, TCHAR_TO_UTF8(*childclass)); + if (bOverride_childclass) MjSetString(Element->childclass, childclass); // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Constraints/MjEquality.cpp b/Source/URLab/Private/MuJoCo/Components/Constraints/MjEquality.cpp index 547d11a..8023709 100644 --- a/Source/URLab/Private/MuJoCo/Components/Constraints/MjEquality.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Constraints/MjEquality.cpp @@ -103,6 +103,7 @@ void UMjEquality::ExportTo(mjsEquality* Element) // anchor) or site-to-site. URLab's parser collates site1/site2 into // Obj1/Obj2 alongside body1/body2; we use the non-empty site1 // UPROPERTY as the discriminator for "this was a site-mode equality". + // --- CODEGEN_OBJTYPE_DISPATCH_START --- switch (EqualityType) { case EMjEqualityType::Connect: @@ -124,11 +125,12 @@ void UMjEquality::ExportTo(mjsEquality* Element) Element->objtype = mjOBJ_UNKNOWN; break; } + // --- CODEGEN_OBJTYPE_DISPATCH_END --- // --- CODEGEN_EXPORT_START --- if (bOverride_active) Element->active = active; - if (bOverride_solref) { for (int32 i = 0; i < solref.Num(); ++i) Element->solref[i] = solref[i]; } - if (bOverride_solimp) { for (int32 i = 0; i < solimp.Num(); ++i) Element->solimp[i] = solimp[i]; } + if (bOverride_solref) { for (int32 i = 0; i < FMath::Min(solref.Num(), 2); ++i) Element->solref[i] = solref[i]; } + if (bOverride_solimp) { for (int32 i = 0; i < FMath::Min(solimp.Num(), 5); ++i) Element->solimp[i] = solimp[i]; } if (((EqualityType == EMjEqualityType::Connect) || (EqualityType == EMjEqualityType::Weld)) && bOverride_anchor) { for (int32 i = 0; i < anchor.Num() && i < 3; ++i) @@ -152,8 +154,8 @@ void UMjEquality::ExportTo(mjsEquality* Element) { Element->data[10] = (mjtNum)torquescale; } - if (!Obj1.IsEmpty()) mjs_setString(Element->name1, TCHAR_TO_UTF8(*Obj1)); - if (!Obj2.IsEmpty()) mjs_setString(Element->name2, TCHAR_TO_UTF8(*Obj2)); + MjSetString(Element->name1, Obj1); + MjSetString(Element->name2, Obj2); // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Deformable/MjFlexcomp.cpp b/Source/URLab/Private/MuJoCo/Components/Deformable/MjFlexcomp.cpp index 6367d5b..b9e6e2c 100644 --- a/Source/URLab/Private/MuJoCo/Components/Deformable/MjFlexcomp.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Deformable/MjFlexcomp.cpp @@ -62,27 +62,29 @@ void UMjFlexcomp::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& { // xml_enum: type -> EMjFlexcompType FString S = Node->GetAttribute(TEXT("type")); S = S.ToLower(); - if (S == TEXT("grid")) FlexcompType = EMjFlexcompType::Grid; - else if (S == TEXT("box")) FlexcompType = EMjFlexcompType::Box; - else if (S == TEXT("cylinder")) FlexcompType = EMjFlexcompType::Cylinder; - else if (S == TEXT("ellipsoid")) FlexcompType = EMjFlexcompType::Ellipsoid; - else if (S == TEXT("square")) FlexcompType = EMjFlexcompType::Square; - else if (S == TEXT("disc")) FlexcompType = EMjFlexcompType::Disc; - else if (S == TEXT("circle")) FlexcompType = EMjFlexcompType::Circle; - else if (S == TEXT("mesh")) FlexcompType = EMjFlexcompType::Mesh; - else if (S == TEXT("gmsh")) FlexcompType = EMjFlexcompType::Gmsh; - else if (S == TEXT("direct")) FlexcompType = EMjFlexcompType::Direct; - if (!S.IsEmpty()) bOverride_FlexcompType = true; + bool bMatched = false; + if (S == TEXT("grid")) { FlexcompType = EMjFlexcompType::Grid; bMatched = true; } + else if (S == TEXT("box")) { FlexcompType = EMjFlexcompType::Box; bMatched = true; } + else if (S == TEXT("cylinder")) { FlexcompType = EMjFlexcompType::Cylinder; bMatched = true; } + else if (S == TEXT("ellipsoid")) { FlexcompType = EMjFlexcompType::Ellipsoid; bMatched = true; } + else if (S == TEXT("square")) { FlexcompType = EMjFlexcompType::Square; bMatched = true; } + else if (S == TEXT("disc")) { FlexcompType = EMjFlexcompType::Disc; bMatched = true; } + else if (S == TEXT("circle")) { FlexcompType = EMjFlexcompType::Circle; bMatched = true; } + else if (S == TEXT("mesh")) { FlexcompType = EMjFlexcompType::Mesh; bMatched = true; } + else if (S == TEXT("gmsh")) { FlexcompType = EMjFlexcompType::Gmsh; bMatched = true; } + else if (S == TEXT("direct")) { FlexcompType = EMjFlexcompType::Direct; bMatched = true; } + if (bMatched) bOverride_FlexcompType = true; } { // xml_enum: dof -> EMjFlexcompDof FString S = Node->GetAttribute(TEXT("dof")); S = S.ToLower(); - if (S == TEXT("full")) FlexcompDof = EMjFlexcompDof::Full; - else if (S == TEXT("radial")) FlexcompDof = EMjFlexcompDof::Radial; - else if (S == TEXT("trilinear")) FlexcompDof = EMjFlexcompDof::Trilinear; - else if (S == TEXT("quadratic")) FlexcompDof = EMjFlexcompDof::Quadratic; - else if (S == TEXT("2d")) FlexcompDof = EMjFlexcompDof::TwoD; - if (!S.IsEmpty()) bOverride_FlexcompDof = true; + bool bMatched = false; + if (S == TEXT("full")) { FlexcompDof = EMjFlexcompDof::Full; bMatched = true; } + else if (S == TEXT("radial")) { FlexcompDof = EMjFlexcompDof::Radial; bMatched = true; } + else if (S == TEXT("trilinear")) { FlexcompDof = EMjFlexcompDof::Trilinear; bMatched = true; } + else if (S == TEXT("quadratic")) { FlexcompDof = EMjFlexcompDof::Quadratic; bMatched = true; } + else if (S == TEXT("2d")) { FlexcompDof = EMjFlexcompDof::TwoD; bMatched = true; } + if (bMatched) bOverride_FlexcompDof = true; } MjXmlUtils::ReadAttrInt(Node, TEXT("group"), group, bOverride_group); MjXmlUtils::ReadAttrInt(Node, TEXT("dim"), dim, bOverride_dim); diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/MjGeom.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/MjGeom.cpp index 6eb989c..67fec3d 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/MjGeom.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/MjGeom.cpp @@ -76,33 +76,37 @@ void UMjGeom::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com // on Type to pick size[1] vs size[2] for the half-length write. // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); { // xml_enum: type -> EMjGeomType FString S = Node->GetAttribute(TEXT("type")); S = S.ToLower(); - if (S == TEXT("plane")) Type = EMjGeomType::Plane; - else if (S == TEXT("hfield")) Type = EMjGeomType::Hfield; - else if (S == TEXT("sphere")) Type = EMjGeomType::Sphere; - else if (S == TEXT("capsule")) Type = EMjGeomType::Capsule; - else if (S == TEXT("ellipsoid")) Type = EMjGeomType::Ellipsoid; - else if (S == TEXT("cylinder")) Type = EMjGeomType::Cylinder; - else if (S == TEXT("box")) Type = EMjGeomType::Box; - else if (S == TEXT("mesh")) Type = EMjGeomType::Mesh; - else if (S == TEXT("sdf")) Type = EMjGeomType::SDF; - if (!S.IsEmpty()) bOverride_Type = true; + bool bMatched = false; + if (S == TEXT("plane")) { Type = EMjGeomType::Plane; bMatched = true; } + else if (S == TEXT("hfield")) { Type = EMjGeomType::Hfield; bMatched = true; } + else if (S == TEXT("sphere")) { Type = EMjGeomType::Sphere; bMatched = true; } + else if (S == TEXT("capsule")) { Type = EMjGeomType::Capsule; bMatched = true; } + else if (S == TEXT("ellipsoid")) { Type = EMjGeomType::Ellipsoid; bMatched = true; } + else if (S == TEXT("cylinder")) { Type = EMjGeomType::Cylinder; bMatched = true; } + else if (S == TEXT("box")) { Type = EMjGeomType::Box; bMatched = true; } + else if (S == TEXT("mesh")) { Type = EMjGeomType::Mesh; bMatched = true; } + else if (S == TEXT("sdf")) { Type = EMjGeomType::SDF; bMatched = true; } + if (bMatched) bOverride_Type = true; } { // xml_enum: shellinertia -> EMjGeomInertia FString S = Node->GetAttribute(TEXT("shellinertia")); S = S.ToLower(); - if (S == TEXT("false")) ShellInertia = EMjGeomInertia::Volume; - else if (S == TEXT("true")) ShellInertia = EMjGeomInertia::Shell; - if (!S.IsEmpty()) bOverride_ShellInertia = true; + bool bMatched = false; + if (S == TEXT("false")) { ShellInertia = EMjGeomInertia::Volume; bMatched = true; } + else if (S == TEXT("true")) { ShellInertia = EMjGeomInertia::Shell; bMatched = true; } + if (bMatched) bOverride_ShellInertia = true; } { // xml_enum: fluidshape -> EMjFluidShape FString S = Node->GetAttribute(TEXT("fluidshape")); S = S.ToLower(); - if (S == TEXT("none")) FluidShape = EMjFluidShape::None; - else if (S == TEXT("ellipsoid")) FluidShape = EMjFluidShape::Ellipsoid; - if (!S.IsEmpty()) bOverride_FluidShape = true; + bool bMatched = false; + if (S == TEXT("none")) { FluidShape = EMjFluidShape::None; bMatched = true; } + else if (S == TEXT("ellipsoid")) { FluidShape = EMjFluidShape::Ellipsoid; bMatched = true; } + if (bMatched) bOverride_FluidShape = true; } MjXmlUtils::ReadAttrInt(Node, TEXT("contype"), contype, bOverride_contype); MjXmlUtils::ReadAttrInt(Node, TEXT("conaffinity"), conaffinity, bOverride_conaffinity); @@ -121,7 +125,7 @@ void UMjGeom::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com MjXmlUtils::ReadAttrFloat(Node, TEXT("gap"), gap, bOverride_gap); if (MjXmlUtils::ReadAttrString(Node, TEXT("hfield"), hfield)) bOverride_hfield = true; if (MjXmlUtils::ReadAttrString(Node, TEXT("mesh"), mesh)) bOverride_mesh = true; - MjXmlUtils::ReadAttrBool(Node, TEXT("fitscale"), fitscale, bOverride_fitscale); + MjXmlUtils::ReadAttrDouble(Node, TEXT("fitscale"), fitscale, bOverride_fitscale); MjXmlUtils::ReadAttrColor(Node, TEXT("rgba"), rgba, bOverride_rgba); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("fluidcoef"), fluidcoef, bOverride_fluidcoef); MjUtils::ReadVec3InMeters(Node, TEXT("pos"), Pos, bOverride_Pos); @@ -148,10 +152,7 @@ void UMjGeom::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com } if (bOverride_Pos) SetRelativeLocation(Pos); if (bOverride_Quat) SetRelativeRotation(Quat); - // --- CODEGEN_IMPORT_END --- - - // MuJoCo class inheritance - MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); + // --- CODEGEN_IMPORT_END --- // Implicit mesh-type detection (mesh attr present but type wasn't set) if (!bOverride_Type && !mesh.IsEmpty()) @@ -179,29 +180,30 @@ void UMjGeom::ExportTo(mjsGeom* Element, mjsDefault* Default) // Type isn't overridden locally, fall back to the default's geom type. // (The codegen-owned xml_enum export below writes Element->type only when // bOverride_Type is true — exactly the desired behavior.) + // --- CODEGEN_GEOM_FINAL_TYPE_START --- int FinalType = bOverride_Type - ? static_cast(Type) /* placeholder; remapped below */ + ? mjGEOM_PLANE /* placeholder; remapped below */ : (Default ? Default->geom->type : mjGEOM_MESH); if (bOverride_Type) { - switch(Type) + switch (Type) { - case EMjGeomType::Plane: FinalType = mjGEOM_PLANE; break; - case EMjGeomType::Hfield: FinalType = mjGEOM_HFIELD; break; - case EMjGeomType::Sphere: FinalType = mjGEOM_SPHERE; break; - case EMjGeomType::Capsule: FinalType = mjGEOM_CAPSULE; break; - case EMjGeomType::Ellipsoid:FinalType = mjGEOM_ELLIPSOID;break; + case EMjGeomType::Plane: FinalType = mjGEOM_PLANE; break; + case EMjGeomType::Hfield: FinalType = mjGEOM_HFIELD; break; + case EMjGeomType::Sphere: FinalType = mjGEOM_SPHERE; break; + case EMjGeomType::Capsule: FinalType = mjGEOM_CAPSULE; break; + case EMjGeomType::Ellipsoid: FinalType = mjGEOM_ELLIPSOID; break; case EMjGeomType::Cylinder: FinalType = mjGEOM_CYLINDER; break; - case EMjGeomType::Box: FinalType = mjGEOM_BOX; break; - case EMjGeomType::Mesh: FinalType = mjGEOM_MESH; break; - case EMjGeomType::SDF: FinalType = mjGEOM_SDF; break; + case EMjGeomType::Box: FinalType = mjGEOM_BOX; break; + case EMjGeomType::Mesh: FinalType = mjGEOM_MESH; break; + case EMjGeomType::SDF: FinalType = mjGEOM_SDF; break; } } - if (FinalType == mjGEOM_MESH && !MeshName.IsEmpty()) { - mjs_setString(Element->meshname, TCHAR_TO_UTF8(*MeshName)); + MjSetStringRaw(Element->meshname, MeshName); } + // --- CODEGEN_GEOM_FINAL_TYPE_END --- // size: codegen-owned TArray; the default per-attr export writes // Element->size[i] = size[i] up to size.Num(). Clamped to 3 by mjsGeom's @@ -260,37 +262,29 @@ void UMjGeom::ExportTo(mjsGeom* Element, mjsDefault* Default) if (bOverride_condim) Element->condim = condim; if (bOverride_group) Element->group = group; if (bOverride_priority) Element->priority = priority; - if (bOverride_size) { for (int32 i = 0; i < size.Num(); ++i) { if (size[i] != -1.0f) Element->size[i] = size[i]; } } - if (bOverride_friction) { for (int32 i = 0; i < friction.Num(); ++i) Element->friction[i] = friction[i]; } + if (bOverride_size) { for (int32 i = 0; i < FMath::Min(size.Num(), 3); ++i) { if (size[i] != -1.0f) Element->size[i] = size[i]; } } + if (bOverride_friction) { for (int32 i = 0; i < FMath::Min(friction.Num(), 3); ++i) Element->friction[i] = friction[i]; } if (bOverride_mass) Element->mass = mass; if (bOverride_density) Element->density = density; if (bOverride_solmix) Element->solmix = solmix; - if (bOverride_solref) { for (int32 i = 0; i < solref.Num(); ++i) Element->solref[i] = solref[i]; } - if (bOverride_solimp) { for (int32 i = 0; i < solimp.Num(); ++i) Element->solimp[i] = solimp[i]; } + if (bOverride_solref) { for (int32 i = 0; i < FMath::Min(solref.Num(), 2); ++i) Element->solref[i] = solref[i]; } + if (bOverride_solimp) { for (int32 i = 0; i < FMath::Min(solimp.Num(), 5); ++i) Element->solimp[i] = solimp[i]; } if (bOverride_margin) Element->margin = margin; if (bOverride_gap) Element->gap = gap; - if (bOverride_mesh && !mesh.IsEmpty()) mjs_setString(Element->meshname, TCHAR_TO_UTF8(*mesh)); - if (bOverride_fitscale) Element->fitscale = fitscale ? 1 : 0; + if (bOverride_mesh) MjSetString(Element->meshname, mesh); + if (bOverride_fitscale) Element->fitscale = fitscale; if (bOverride_rgba) { Element->rgba[0] = rgba.R; Element->rgba[1] = rgba.G; Element->rgba[2] = rgba.B; Element->rgba[3] = rgba.A; } - if (bOverride_fluidcoef) { for (int32 i = 0; i < fluidcoef.Num(); ++i) Element->fluid_coefs[i] = fluidcoef[i]; } - // --- CODEGEN_EXPORT_END --- + if (bOverride_fluidcoef) { for (int32 i = 0; i < FMath::Min(fluidcoef.Num(), 5); ++i) Element->fluid_coefs[i] = fluidcoef[i]; } + // --- CODEGEN_EXPORT_END --- } void UMjGeom::Bind(mjModel* Model, mjData* Data, const FString& Prefix) { Super::Bind(Model, Data, Prefix); - m_GeomView = BindToView(Prefix); - + BindAndCacheView(m_GeomView, Prefix); if (m_GeomView.id != -1) { - m_ID = m_GeomView.id; SyncUnrealTransformFromMj(); - UE_LOG(LogURLabBind, Log, TEXT("[MjGeom] Successfully bound '%s' to ID %d (MjName: %s)"), *GetName(), m_ID, *MjName); - } - else - { - UE_LOG(LogURLabBind, Warning, TEXT("[MjGeom] Geom '%s' FAILED bind. Prefix: %s, MjName: %s"), - *GetName(), *Prefix, *MjName); } } @@ -299,10 +293,10 @@ void UMjGeom::UpdateGlobalTransform() if (m_GeomView._m && m_GeomView._d && m_GeomView.id >= 0) { // Get world position from MuJoCo - FVector WorldPos = MjUtils::MjToUEPosition(m_GeomView.xpos); + FVector WorldPos = MjUtils::MjToUEPosition(m_GeomView.geom_xpos); FQuat WorldRot; mjtNum quat[4]; - mju_mat2Quat(quat, m_GeomView.xmat); + mju_mat2Quat(quat, m_GeomView.geom_xmat); WorldRot = MjUtils::MjToUERotation(quat); SetWorldLocation(WorldPos); @@ -314,7 +308,7 @@ FVector UMjGeom::GetWorldLocation() const { if (m_GeomView._m && m_GeomView._d && m_GeomView.id >= 0) { - return MjUtils::MjToUEPosition(m_GeomView.xpos); + return MjUtils::MjToUEPosition(m_GeomView.geom_xpos); } return GetComponentLocation(); } @@ -325,9 +319,9 @@ void UMjGeom::SetFriction(float NewFriction) bOverride_friction = true; // Update runtime model if bound - if (m_GeomView._m && m_GeomView._d && m_GeomView.id >= 0 && m_GeomView.friction) + if (m_GeomView._m && m_GeomView._d && m_GeomView.id >= 0 && m_GeomView.geom_friction) { - m_GeomView.friction[0] = NewFriction; + m_GeomView.geom_friction[0] = NewFriction; } } @@ -935,8 +929,7 @@ void UMjGeom::RemoveDecomposition() {} #endif #if WITH_EDITOR -TArray UMjGeom::GetDefaultClassOptions() const -{ - return GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjGeom::GetDefaultClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/MjSite.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/MjSite.cpp index 5b27f4f..0896a87 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/MjSite.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/MjSite.cpp @@ -67,10 +67,12 @@ void UMjSite::ExportTo(mjsSite* Element, mjsDefault* def) case EMjSiteType::Ellipsoid: Element->type = (mjtGeom)mjGEOM_ELLIPSOID; break; case EMjSiteType::Cylinder: Element->type = (mjtGeom)mjGEOM_CYLINDER; break; case EMjSiteType::Box: Element->type = (mjtGeom)mjGEOM_BOX; break; + case EMjSiteType::Mesh: Element->type = (mjtGeom)mjGEOM_MESH; break; + case EMjSiteType::Hfield: Element->type = (mjtGeom)mjGEOM_HFIELD; break; default: break; } if (bOverride_group) Element->group = group; - if (bOverride_size) { for (int32 i = 0; i < size.Num(); ++i) { if (size[i] != -1.0f) Element->size[i] = size[i]; } } + if (bOverride_size) { for (int32 i = 0; i < FMath::Min(size.Num(), 3); ++i) { if (size[i] != -1.0f) Element->size[i] = size[i]; } } if (bOverride_rgba) { Element->rgba[0] = rgba.R; Element->rgba[1] = rgba.G; Element->rgba[2] = rgba.B; Element->rgba[3] = rgba.A; } // --- CODEGEN_EXPORT_END --- } @@ -89,11 +91,13 @@ void UMjSite::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com { // xml_enum: type -> EMjSiteType FString S = Node->GetAttribute(TEXT("type")); S = S.ToLower(); - if (S == TEXT("sphere")) Type = EMjSiteType::Sphere; - else if (S == TEXT("capsule")) Type = EMjSiteType::Capsule; - else if (S == TEXT("ellipsoid")) Type = EMjSiteType::Ellipsoid; - else if (S == TEXT("cylinder")) Type = EMjSiteType::Cylinder; - else if (S == TEXT("box")) Type = EMjSiteType::Box; + if (S == TEXT("sphere")) { Type = EMjSiteType::Sphere; } + else if (S == TEXT("capsule")) { Type = EMjSiteType::Capsule; } + else if (S == TEXT("ellipsoid")) { Type = EMjSiteType::Ellipsoid; } + else if (S == TEXT("cylinder")) { Type = EMjSiteType::Cylinder; } + else if (S == TEXT("box")) { Type = EMjSiteType::Box; } + else if (S == TEXT("mesh")) { Type = EMjSiteType::Mesh; } + else if (S == TEXT("hfield")) { Type = EMjSiteType::Hfield; } } MjXmlUtils::ReadAttrInt(Node, TEXT("group"), group, bOverride_group); if (MjXmlUtils::ReadAttrString(Node, TEXT("material"), material)) bOverride_material = true; @@ -123,7 +127,7 @@ void UMjSite::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Com } if (bOverride_Pos) SetRelativeLocation(Pos); if (bOverride_Quat) SetRelativeRotation(Quat); - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- } void UMjSite::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody) @@ -142,24 +146,13 @@ void UMjSite::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody) void UMjSite::Bind(mjModel* model, mjData* data, const FString& Prefix) { Super::Bind(model, data, Prefix); - m_SiteView = BindToView(Prefix); - - if (m_SiteView.id != -1) - { - m_ID = m_SiteView.id; - UE_LOG(LogURLabBind, Log, TEXT("[MjSite] Successfully bound '%s' to ID %d (MjName: %s)"), *GetName(), m_ID, *MjName); - } - else - { - UE_LOG(LogURLabBind, Warning, TEXT("[MjSite] Site '%s' FAILED bind. Prefix: %s, MjName: %s"), *GetName(), *Prefix, *MjName); - } + BindAndCacheView(m_SiteView, Prefix); } #if WITH_EDITOR -TArray UMjSite::GetDefaultClassOptions() const -{ - return GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjSite::GetDefaultClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif // --- Multi-UCLASS subclass constructors -------------------------------------- diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjBox.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjBox.cpp index f240359..fca024a 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjBox.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjBox.cpp @@ -94,8 +94,7 @@ void UMjBox::SetGeomVisibility(bool bNewVisibility) void UMjBox::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { // --- CODEGEN_IMPORT_START --- - - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- Super::ImportFromXml(Node, CompilerSettings); // MuJoCo box size is 3 half-extents in metres. @@ -126,8 +125,7 @@ void UMjBox::ExportTo(mjsGeom* Element, mjsDefault* def) Super::ExportTo(Element, def); // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + // --- CODEGEN_EXPORT_END --- } void UMjBox::ApplyOverrideMaterial(UMaterialInterface* Material) @@ -149,9 +147,9 @@ void UMjBox::SyncUnrealTransformFromMj() // MuJoCo box size is half-extents. Unreal Cube is 100 units. // Size 0.5 -> scale 1.0 float r[3]; - r[0] = m_GeomView.size[0]; - r[1] = m_GeomView.size[1]; - r[2] = m_GeomView.size[2]; + r[0] = m_GeomView.geom_size[0]; + r[1] = m_GeomView.geom_size[1]; + r[2] = m_GeomView.geom_size[2]; FVector NewScale = FVector(r[0], r[1], r[2]) * 2.0f; SetRelativeScale3D(NewScale); diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCapsule.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCapsule.cpp index fb508c4..3848ae6 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCapsule.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCapsule.cpp @@ -135,8 +135,7 @@ void UMjCapsule::UpdateCapTransforms() void UMjCapsule::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { // --- CODEGEN_IMPORT_START --- - - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- Super::ImportFromXml(Node, CompilerSettings); @@ -174,8 +173,7 @@ void UMjCapsule::ExportTo(mjsGeom* Element, mjsDefault* def) Super::ExportTo(Element, def); // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + // --- CODEGEN_EXPORT_END --- } void UMjCapsule::SyncUnrealTransformFromMj() @@ -184,8 +182,8 @@ void UMjCapsule::SyncUnrealTransformFromMj() if (!bOverride_size) { - const float RadiusVal = m_GeomView.size[0]; - const float HalfLengthVal = m_GeomView.size[1]; + const float RadiusVal = m_GeomView.geom_size[0]; + const float HalfLengthVal = m_GeomView.geom_size[1]; const FVector NewScale = FVector(RadiusVal * 2.0f, RadiusVal * 2.0f, HalfLengthVal * 2.0f); SetRelativeScale3D(NewScale); diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCylinder.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCylinder.cpp index 4035d2b..ed2fbf9 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCylinder.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjCylinder.cpp @@ -78,8 +78,7 @@ void UMjCylinder::OnRegister() void UMjCylinder::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { // --- CODEGEN_IMPORT_START --- - - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- Super::ImportFromXml(Node, CompilerSettings); // Clamp -1.0f sentinels (set by the fromto canon when slot is unset). @@ -113,8 +112,7 @@ void UMjCylinder::ExportTo(mjsGeom* Element, mjsDefault* def) Super::ExportTo(Element, def); // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + // --- CODEGEN_EXPORT_END --- } void UMjCylinder::ApplyOverrideMaterial(UMaterialInterface* Material) @@ -131,8 +129,8 @@ void UMjCylinder::SyncUnrealTransformFromMj() { // MuJoCo cylinder size: [radius, half-length] // Unreal Cylinder: diameter=100, Height=100 - float RadiusVal = m_GeomView.size[0]; - float HalfLengthVal = m_GeomView.size[1]; + float RadiusVal = m_GeomView.geom_size[0]; + float HalfLengthVal = m_GeomView.geom_size[1]; FVector NewScale = FVector(RadiusVal * 2.0f, RadiusVal * 2.0f, HalfLengthVal * 2.0f); SetRelativeScale3D(NewScale); diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.cpp index 674f5d0..8549126 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.cpp @@ -41,7 +41,7 @@ void UMjEllipsoid::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } @@ -52,6 +52,6 @@ void UMjEllipsoid::ExportTo(mjsGeom* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - + // (no type-specific schema exports) // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjPlane.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjPlane.cpp index d836d7a..00fbd43 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjPlane.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjPlane.cpp @@ -41,7 +41,7 @@ void UMjPlane::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Co if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } @@ -52,6 +52,6 @@ void UMjPlane::ExportTo(mjsGeom* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - + // (no type-specific schema exports) // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSdf.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSdf.cpp index 90eff86..318c2cd 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSdf.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSdf.cpp @@ -41,7 +41,7 @@ void UMjSdf::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Comp if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } @@ -52,6 +52,6 @@ void UMjSdf::ExportTo(mjsGeom* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - + // (no type-specific schema exports) // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSphere.cpp b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSphere.cpp index 80fa9e6..e143dbe 100644 --- a/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSphere.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Geometry/Primitives/MjSphere.cpp @@ -78,8 +78,7 @@ void UMjSphere::OnRegister() void UMjSphere::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { // --- CODEGEN_IMPORT_START --- - - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- Super::ImportFromXml(Node, CompilerSettings); Radius = size.Num() > 0 ? size[0] : 0.0f; @@ -109,8 +108,7 @@ void UMjSphere::ExportTo(mjsGeom* Element, mjsDefault* def) Super::ExportTo(Element, def); // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + // --- CODEGEN_EXPORT_END --- } void UMjSphere::ApplyOverrideMaterial(UMaterialInterface* Material) @@ -126,7 +124,7 @@ void UMjSphere::SyncUnrealTransformFromMj() if (!bOverride_size) { // MuJoCo sphere size is radius. Unreal Sphere is 100 units diameter. - float RadiusVal = m_GeomView.size[0]; + float RadiusVal = m_GeomView.geom_size[0]; FVector NewScale = FVector(RadiusVal * 2.0f); SetRelativeScale3D(NewScale); diff --git a/Source/URLab/Private/MuJoCo/Components/Joints/MjBallJoint.cpp b/Source/URLab/Private/MuJoCo/Components/Joints/MjBallJoint.cpp index 884f5a2..47f6fd2 100644 --- a/Source/URLab/Private/MuJoCo/Components/Joints/MjBallJoint.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Joints/MjBallJoint.cpp @@ -13,31 +13,27 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Joints/MjBallJoint.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjBallJoint::UMjBallJoint() { - bOverride_Type = true; Type = EMjJointType::Ball; -} - -void UMjBallJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + bOverride_Type = true; } void UMjBallJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) @@ -46,7 +42,17 @@ void UMjBallJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjBallJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Joints/MjFreeJoint.cpp b/Source/URLab/Private/MuJoCo/Components/Joints/MjFreeJoint.cpp index 49e865a..63d0752 100644 --- a/Source/URLab/Private/MuJoCo/Components/Joints/MjFreeJoint.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Joints/MjFreeJoint.cpp @@ -79,7 +79,6 @@ void UMjFreeJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - // --- CODEGEN_EXPORT_END --- } @@ -89,7 +88,6 @@ void UMjFreeJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings if (!Node) return; // --- CODEGEN_IMPORT_START --- - // --- CODEGEN_IMPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Joints/MjHingeJoint.cpp b/Source/URLab/Private/MuJoCo/Components/Joints/MjHingeJoint.cpp index f8077a3..3809256 100644 --- a/Source/URLab/Private/MuJoCo/Components/Joints/MjHingeJoint.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Joints/MjHingeJoint.cpp @@ -13,31 +13,27 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Joints/MjHingeJoint.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjHingeJoint::UMjHingeJoint() { - bOverride_Type = true; Type = EMjJointType::Hinge; -} - -void UMjHingeJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + bOverride_Type = true; } void UMjHingeJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) @@ -46,7 +42,17 @@ void UMjHingeJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSetting if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjHingeJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Joints/MjJoint.cpp b/Source/URLab/Private/MuJoCo/Components/Joints/MjJoint.cpp index 65b0d8f..5565e71 100644 --- a/Source/URLab/Private/MuJoCo/Components/Joints/MjJoint.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Joints/MjJoint.cpp @@ -42,26 +42,30 @@ void UMjJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Co if (!Node) return; // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); { // xml_enum: type -> EMjJointType FString S = Node->GetAttribute(TEXT("type")); S = S.ToLower(); - if (S == TEXT("hinge")) Type = EMjJointType::Hinge; - else if (S == TEXT("slide")) Type = EMjJointType::Slide; - else if (S == TEXT("ball")) Type = EMjJointType::Ball; - else if (S == TEXT("free")) Type = EMjJointType::Free; - if (!S.IsEmpty()) bOverride_Type = true; + bool bMatched = false; + if (S == TEXT("hinge")) { Type = EMjJointType::Hinge; bMatched = true; } + else if (S == TEXT("slide")) { Type = EMjJointType::Slide; bMatched = true; } + else if (S == TEXT("ball")) { Type = EMjJointType::Ball; bMatched = true; } + else if (S == TEXT("free")) { Type = EMjJointType::Free; bMatched = true; } + if (bMatched) bOverride_Type = true; } MjXmlUtils::ReadAttrInt(Node, TEXT("group"), group, bOverride_group); + MjXmlUtils::ReadAttrVec3(Node, TEXT("axis"), Axis, bOverride_Axis); + if (bOverride_Axis) Axis.Y = -Axis.Y; MjXmlUtils::ReadAttrFloatArray(Node, TEXT("springdamper"), springdamper, bOverride_springdamper); MjXmlUtils::ReadAttrBool(Node, TEXT("limited"), limited, bOverride_limited); - MjXmlUtils::ReadAttrBool(Node, TEXT("actuatorfrclimited"), actuatorfrclimited, bOverride_actuatorfrclimited); + MjXmlUtils::ReadAttrBool(Node, TEXT("actuatorfrclimited"), ActFrcLimited, bOverride_ActFrcLimited); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solreflimit"), solreflimit, bOverride_solreflimit); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solimplimit"), solimplimit, bOverride_solimplimit); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solreffriction"), solreffriction, bOverride_solreffriction); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solimpfriction"), solimpfriction, bOverride_solimpfriction); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("stiffness"), stiffness, bOverride_stiffness); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("range"), range, bOverride_range); - MjXmlUtils::ReadAttrFloatArray(Node, TEXT("actuatorfrcrange"), actuatorfrcrange, bOverride_actuatorfrcrange); + MjXmlUtils::ReadAttrFloatArray(Node, TEXT("actuatorfrcrange"), ActFrcRange, bOverride_ActFrcRange); MjXmlUtils::ReadAttrFloat(Node, TEXT("actuatorgravcomp"), actuatorgravcomp, bOverride_actuatorgravcomp); MjXmlUtils::ReadAttrFloat(Node, TEXT("margin"), margin, bOverride_margin); MjXmlUtils::ReadAttrFloat(Node, TEXT("ref"), ref, bOverride_ref); @@ -69,6 +73,8 @@ void UMjJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Co MjXmlUtils::ReadAttrFloat(Node, TEXT("armature"), armature, bOverride_armature); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("damping"), damping, bOverride_damping); MjXmlUtils::ReadAttrFloat(Node, TEXT("frictionloss"), frictionloss, bOverride_frictionloss); + MjUtils::ReadVec3InMeters(Node, TEXT("pos"), Pos, bOverride_Pos); + if (bOverride_Pos) SetRelativeLocation(Pos); if (bOverride_range) { if (Type == EMjJointType::Slide) { for (float& V : range) { V *= 100.0f; } } @@ -84,28 +90,10 @@ void UMjJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& Co if (Type == EMjJointType::Slide) { springref *= 100.0f; } else if ((Type == EMjJointType::Hinge) || (Type == EMjJointType::Ball)) { if (!CompilerSettings.bAngleInDegrees) { springref = FMath::RadiansToDegrees(springref); } } } - // --- CODEGEN_IMPORT_END --- - - // Class Name - MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); - - // Axis — convert from MuJoCo to UE direction-vector convention (negate Y, no scale) - FString AxisStr; - if (MjXmlUtils::ReadAttrString(Node, TEXT("axis"), AxisStr)) - { - bOverride_Axis = true; - FVector RawAxis = MjXmlUtils::ParseVector(AxisStr); - Axis = FVector(RawAxis.X, -RawAxis.Y, RawAxis.Z); - } + // --- CODEGEN_IMPORT_END --- - - FString PosStr; - if (MjXmlUtils::ReadAttrString(Node, TEXT("pos"), PosStr)) - { - FVector RawPos = MjXmlUtils::ParseVector(PosStr); - double p[3] = { (double)RawPos.X, (double)RawPos.Y, (double)RawPos.Z }; - SetRelativeLocation(MjUtils::MjToUEPosition(p)); - } + // axis (Y-negate vec3_convert) + pos (spatial_pose canon) are + // codegen-owned via the joint rule in codegen_rules.json. // Note: autolimits (limited inferred from range) is handled by the MuJoCo spec // compiler (mjLIMITED_AUTO default). We do not replicate that logic here. @@ -120,20 +108,19 @@ void UMjJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) { if (!Element) return; - FVector _pos = GetRelativeLocation(); - if (!_pos.IsZero()) MjUtils::UEToMjPosition(_pos, Element->pos); - - if (bOverride_Axis) - { - // Convert UE direction vector back to MuJoCo convention (negate Y, no scale) - Element->axis[0] = Axis.X; - Element->axis[1] = -Axis.Y; - Element->axis[2] = Axis.Z; - } + // axis + pos exports are codegen-emitted between the CODEGEN_EXPORT + // markers below (spatial_pose canon writes pos, vec3_convert.axis + // applies the Y-negate to the codegen-emitted axis write). // Slide joints: convert ref from cm (UE) back to meters (MuJoCo) // --- CODEGEN_EXPORT_START --- + if (bOverride_Pos) + { + double TmpPos[3]; + MjUtils::UEToMjPosition(Pos, TmpPos); + Element->pos[0] = TmpPos[0]; Element->pos[1] = TmpPos[1]; Element->pos[2] = TmpPos[2]; + } if (bOverride_Type) { switch (Type) @@ -146,19 +133,20 @@ void UMjJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) } } if (bOverride_group) Element->group = group; - if (bOverride_springdamper) { for (int32 i = 0; i < springdamper.Num(); ++i) Element->springdamper[i] = springdamper[i]; } + if (bOverride_Axis) { Element->axis[0] = Axis.X; Element->axis[1] = -Axis.Y; Element->axis[2] = Axis.Z; } + if (bOverride_springdamper) { for (int32 i = 0; i < FMath::Min(springdamper.Num(), 2); ++i) Element->springdamper[i] = springdamper[i]; } if (bOverride_limited) Element->limited = limited ? 1 : 0; - if (bOverride_actuatorfrclimited) Element->actfrclimited = actuatorfrclimited ? 1 : 0; - if (bOverride_solreflimit) { for (int32 i = 0; i < solreflimit.Num(); ++i) Element->solref_limit[i] = solreflimit[i]; } - if (bOverride_solimplimit) { for (int32 i = 0; i < solimplimit.Num(); ++i) Element->solimp_limit[i] = solimplimit[i]; } - if (bOverride_solreffriction) { for (int32 i = 0; i < solreffriction.Num(); ++i) Element->solref_friction[i] = solreffriction[i]; } - if (bOverride_solimpfriction) { for (int32 i = 0; i < solimpfriction.Num(); ++i) Element->solimp_friction[i] = solimpfriction[i]; } - if (bOverride_stiffness) { for (int32 i = 0; i < stiffness.Num(); ++i) Element->stiffness[i] = stiffness[i]; } - if (bOverride_actuatorfrcrange) { for (int32 i = 0; i < actuatorfrcrange.Num(); ++i) Element->actfrcrange[i] = actuatorfrcrange[i]; } + if (bOverride_ActFrcLimited) Element->actfrclimited = ActFrcLimited ? 1 : 0; + if (bOverride_solreflimit) { for (int32 i = 0; i < FMath::Min(solreflimit.Num(), 2); ++i) Element->solref_limit[i] = solreflimit[i]; } + if (bOverride_solimplimit) { for (int32 i = 0; i < FMath::Min(solimplimit.Num(), 5); ++i) Element->solimp_limit[i] = solimplimit[i]; } + if (bOverride_solreffriction) { for (int32 i = 0; i < FMath::Min(solreffriction.Num(), 2); ++i) Element->solref_friction[i] = solreffriction[i]; } + if (bOverride_solimpfriction) { for (int32 i = 0; i < FMath::Min(solimpfriction.Num(), 5); ++i) Element->solimp_friction[i] = solimpfriction[i]; } + if (bOverride_stiffness) { for (int32 i = 0; i < FMath::Min(stiffness.Num(), 3); ++i) Element->stiffness[i] = stiffness[i]; } + if (bOverride_ActFrcRange) { for (int32 i = 0; i < FMath::Min(ActFrcRange.Num(), 2); ++i) Element->actfrcrange[i] = ActFrcRange[i]; } if (bOverride_actuatorgravcomp) Element->actgravcomp = actuatorgravcomp; if (bOverride_margin) Element->margin = margin; if (bOverride_armature) Element->armature = armature; - if (bOverride_damping) { for (int32 i = 0; i < damping.Num(); ++i) Element->damping[i] = damping[i]; } + if (bOverride_damping) { for (int32 i = 0; i < FMath::Min(damping.Num(), 3); ++i) Element->damping[i] = damping[i]; } if (bOverride_frictionloss) Element->frictionloss = frictionloss; if (bOverride_range) { @@ -184,15 +172,13 @@ void UMjJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) else if ((Type == EMjJointType::Hinge) || (Type == EMjJointType::Ball)) { V = FMath::DegreesToRadians(V); } Element->springref = (mjtNum)V; } - // --- CODEGEN_EXPORT_END --- + // --- CODEGEN_EXPORT_END --- } void UMjJoint::Bind(mjModel* Model, mjData* Data, const FString& Prefix) { Super::Bind(Model, Data, Prefix); - m_JointView = BindToView(Prefix); - if (m_JointView.id != -1) m_ID = m_JointView.id; - else UE_LOG(LogURLabBind, Warning, TEXT("Failed to bind Joint %s"), *GetName()); + BindAndCacheView(m_JointView, Prefix); } float UMjJoint::GetPosition() const @@ -240,8 +226,8 @@ float UMjJoint::GetAcceleration() const FVector2D UMjJoint::GetJointRange() const { - if (m_JointView.id < 0 || !m_JointView.range) return FVector2D::ZeroVector; - return FVector2D((float)m_JointView.range[0], (float)m_JointView.range[1]); + if (m_JointView.id < 0 || !m_JointView.jnt_range) return FVector2D::ZeroVector; + return FVector2D((float)m_JointView.jnt_range[0], (float)m_JointView.jnt_range[1]); } FVector UMjJoint::GetWorldAnchor() const @@ -290,7 +276,7 @@ EMjJointType UMjJoint::GetResolvedType() const // Runtime: use compiled model if (m_JointView.id >= 0) { - switch (m_JointView.type) + switch (m_JointView.jnt_type) { case mjJNT_FREE: return EMjJointType::Free; case mjJNT_BALL: return EMjJointType::Ball; @@ -378,10 +364,10 @@ FVector2D UMjJoint::GetResolvedRange() const }; // Runtime: use compiled model (rad/m). - if (m_JointView.id >= 0 && m_JointView.range) + if (m_JointView.id >= 0 && m_JointView.jnt_range) { - return FVector2D(MjToUE((float)m_JointView.range[0]), - MjToUE((float)m_JointView.range[1])); + return FVector2D(MjToUE((float)m_JointView.jnt_range[0]), + MjToUE((float)m_JointView.jnt_range[1])); } // Editor: local override wins. Already in UE units. @@ -416,10 +402,10 @@ FVector2D UMjJoint::GetResolvedRange() const bool UMjJoint::GetResolvedLimited() const { // Runtime: use compiled model range - if (m_JointView.id >= 0 && m_JointView.range) + if (m_JointView.id >= 0 && m_JointView.jnt_range) { // MuJoCo sets range to (0,0) when unlimited - return m_JointView.range[0] != 0.0 || m_JointView.range[1] != 0.0; + return m_JointView.jnt_range[0] != 0.0 || m_JointView.jnt_range[1] != 0.0; } // Editor: local override wins @@ -465,13 +451,13 @@ void UMjJoint::BuildBinaryPayload(FBufferArchive& OutBuffer) const int32 JointID = m_ID; OutBuffer << JointID; - float Pos = GetPosition(); - float Vel = GetVelocity(); - float Acc = GetAcceleration(); + float JointPos = GetPosition(); + float JointVel = GetVelocity(); + float JointAcc = GetAcceleration(); - OutBuffer << Pos; - OutBuffer << Vel; - OutBuffer << Acc; + OutBuffer << JointPos; + OutBuffer << JointVel; + OutBuffer << JointAcc; } FString UMjJoint::GetTelemetryTopicName() const @@ -480,8 +466,7 @@ FString UMjJoint::GetTelemetryTopicName() const } #if WITH_EDITOR -TArray UMjJoint::GetDefaultClassOptions() const -{ - return GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjJoint::GetDefaultClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Joints/MjSlideJoint.cpp b/Source/URLab/Private/MuJoCo/Components/Joints/MjSlideJoint.cpp index 5c159b2..5946baf 100644 --- a/Source/URLab/Private/MuJoCo/Components/Joints/MjSlideJoint.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Joints/MjSlideJoint.cpp @@ -13,31 +13,27 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Joints/MjSlideJoint.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjSlideJoint::UMjSlideJoint() { - bOverride_Type = true; Type = EMjJointType::Slide; -} - -void UMjSlideJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- + bOverride_Type = true; } void UMjSlideJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) @@ -46,7 +42,17 @@ void UMjSlideJoint::ImportFromXml(const FXmlNode* Node, const FMjCompilerSetting if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjSlideJoint::ExportTo(mjsJoint* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Keyframes/MjKeyframe.cpp b/Source/URLab/Private/MuJoCo/Components/Keyframes/MjKeyframe.cpp index 7bdd43c..8e2a8d1 100644 --- a/Source/URLab/Private/MuJoCo/Components/Keyframes/MjKeyframe.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Keyframes/MjKeyframe.cpp @@ -26,6 +26,7 @@ #include "MuJoCo/Components/Joints/MjFreeJoint.h" #include "MuJoCo/Components/Actuators/MjActuator.h" #include "MuJoCo/Utils/MjXmlUtils.h" +#include "MuJoCo/Utils/MjUtils.h" #include "XmlNode.h" #include "Utils/URLabLogging.h" @@ -58,36 +59,12 @@ void UMjKeyframe::ExportTo(mjsKey* Element, mjsDefault* Default) // --- CODEGEN_EXPORT_START --- if (bOverride_Time) Element->time = Time; - if (bOverride_Qpos && Element->qpos) - { - Element->qpos->clear(); - for (float V : Qpos) Element->qpos->push_back((double)V); - } - if (bOverride_Qvel && Element->qvel) - { - Element->qvel->clear(); - for (float V : Qvel) Element->qvel->push_back((double)V); - } - if (bOverride_Act && Element->act) - { - Element->act->clear(); - for (float V : Act) Element->act->push_back((double)V); - } - if (bOverride_Ctrl && Element->ctrl) - { - Element->ctrl->clear(); - for (float V : Ctrl) Element->ctrl->push_back((double)V); - } - if (bOverride_Mpos && Element->mpos) - { - Element->mpos->clear(); - for (float V : Mpos) Element->mpos->push_back((double)V); - } - if (bOverride_Mquat && Element->mquat) - { - Element->mquat->clear(); - for (float V : Mquat) Element->mquat->push_back((double)V); - } + if (bOverride_Qpos) MjSetDoubleVec(Element->qpos, Qpos); + if (bOverride_Qvel) MjSetDoubleVec(Element->qvel, Qvel); + if (bOverride_Act) MjSetDoubleVec(Element->act, Act); + if (bOverride_Ctrl) MjSetDoubleVec(Element->ctrl, Ctrl); + if (bOverride_Mpos) MjSetDoubleVec(Element->mpos, Mpos); + if (bOverride_Mquat) MjSetDoubleVec(Element->mquat, Mquat); // --- CODEGEN_EXPORT_END --- } @@ -153,16 +130,8 @@ static FKeyframeDimensions CountDimensions(AActor* Owner) return D; } -namespace -{ - // Helper for overwriting an mjDoubleVec* with a TArray. - void SetVec(mjDoubleVec* Dest, const TArray& Src) - { - if (!Dest) return; - Dest->clear(); - for (float V : Src) Dest->push_back((double)V); - } -} +// SetVec is a thin alias for MjUtils::MjSetDoubleVec; kept here so the +// freejoint padding paths below read cleanly. void UMjKeyframe::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody) { @@ -199,7 +168,7 @@ void UMjKeyframe::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBod Padded.Append({0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f}); } Padded.Append(Qpos); - SetVec(Key->qpos, Padded); + MjSetDoubleVec(Key->qpos, Padded); UE_LOG(LogURLabImport, Log, TEXT("[MjKeyframe] '%s': padded qpos %d -> %d (%d free joints)"), *TName, Qpos.Num(), Padded.Num(), Dims.NumFreeJoints); } @@ -218,7 +187,7 @@ void UMjKeyframe::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBod Padded.Append({0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}); } Padded.Append(Qvel); - SetVec(Key->qvel, Padded); + MjSetDoubleVec(Key->qvel, Padded); UE_LOG(LogURLabImport, Log, TEXT("[MjKeyframe] '%s': padded qvel %d -> %d"), *TName, Qvel.Num(), Padded.Num()); } diff --git a/Source/URLab/Private/MuJoCo/Components/Physics/MjContactExclude.cpp b/Source/URLab/Private/MuJoCo/Components/Physics/MjContactExclude.cpp index a2da014..0907f90 100644 --- a/Source/URLab/Private/MuJoCo/Components/Physics/MjContactExclude.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Physics/MjContactExclude.cpp @@ -21,6 +21,7 @@ // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. #include "MuJoCo/Components/Physics/MjContactExclude.h" +#include "MuJoCo/Utils/MjUtils.h" #include "XmlFile.h" #include "mujoco/mujoco.h" #include "MuJoCo/Core/Spec/MjSpecWrapper.h" @@ -42,21 +43,15 @@ void UMjContactExclude::BeginPlay() void UMjContactExclude::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("name"), Name); if (MjXmlUtils::ReadAttrString(Node, TEXT("body1"), body1)) bOverride_body1 = true; if (MjXmlUtils::ReadAttrString(Node, TEXT("body2"), body2)) bOverride_body2 = true; - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- if (!Node) { return; } - - // Required attributes - body1 = Node->GetAttribute(TEXT("body1")); - body2 = Node->GetAttribute(TEXT("body2")); - - // Optional attributes - Name = Node->GetAttribute(TEXT("name")); } void UMjContactExclude::ExportTo(mjsExclude* Element) @@ -64,8 +59,8 @@ void UMjContactExclude::ExportTo(mjsExclude* Element) if (!Element) return; // --- CODEGEN_EXPORT_START --- - if (bOverride_body1 && !body1.IsEmpty()) mjs_setString(Element->bodyname1, TCHAR_TO_UTF8(*body1)); - if (bOverride_body2 && !body2.IsEmpty()) mjs_setString(Element->bodyname2, TCHAR_TO_UTF8(*body2)); + if (bOverride_body1) MjSetString(Element->bodyname1, body1); + if (bOverride_body2) MjSetString(Element->bodyname2, body2); // --- CODEGEN_EXPORT_END --- } @@ -76,14 +71,8 @@ void UMjContactExclude::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* Par UE_LOG(LogURLabWrapper, Log, TEXT("Added contact exclude: %s<->%s"), *body1, *body2); } -void UMjContactExclude::Bind(mjModel* model, mjData* data, const FString& Prefix) -{ - // Contact excludes are global static data. -} - #if WITH_EDITOR -TArray UMjContactExclude::GetBodyOptions() const -{ - return UMjComponent::GetSiblingComponentOptions(this, UMjBody::StaticClass()); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjContactExclude::GetBodyOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjBody::StaticClass()); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Physics/MjContactPair.cpp b/Source/URLab/Private/MuJoCo/Components/Physics/MjContactPair.cpp index 9035544..14439cb 100644 --- a/Source/URLab/Private/MuJoCo/Components/Physics/MjContactPair.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Physics/MjContactPair.cpp @@ -21,6 +21,7 @@ // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. #include "MuJoCo/Components/Physics/MjContactPair.h" +#include "MuJoCo/Utils/MjUtils.h" #include "XmlFile.h" #include "mujoco/mujoco.h" #include "MuJoCo/Core/Spec/MjSpecWrapper.h" @@ -43,6 +44,7 @@ void UMjContactPair::BeginPlay() void UMjContactPair::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("name"), Name); if (MjXmlUtils::ReadAttrString(Node, TEXT("geom1"), geom1)) bOverride_geom1 = true; if (MjXmlUtils::ReadAttrString(Node, TEXT("geom2"), geom2)) bOverride_geom2 = true; MjXmlUtils::ReadAttrInt(Node, TEXT("condim"), condim, bOverride_condim); @@ -52,30 +54,13 @@ void UMjContactPair::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettin MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solimp"), solimp, bOverride_solimp); MjXmlUtils::ReadAttrFloat(Node, TEXT("gap"), gap, bOverride_gap); MjXmlUtils::ReadAttrFloat(Node, TEXT("margin"), margin, bOverride_margin); - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- if (!Node) { return; } - // Required attributes - - // Optional attributes - MjXmlUtils::ReadAttrString(Node, TEXT("name"), Name); - - { - bool bCondimOverride = false; - } - - // Parse friction/solref/solimp arrays - { - bool bFrictionOverride = false, bSolrefOverride = false, bSolimpOverride = false; - } - - { - bool bGapOverride = false, bMarginOverride = false; - } } void UMjContactPair::ExportTo(mjsPair* Element) @@ -83,13 +68,13 @@ void UMjContactPair::ExportTo(mjsPair* Element) if (!Element) return; // --- CODEGEN_EXPORT_START --- - if (bOverride_geom1 && !geom1.IsEmpty()) mjs_setString(Element->geomname1, TCHAR_TO_UTF8(*geom1)); - if (bOverride_geom2 && !geom2.IsEmpty()) mjs_setString(Element->geomname2, TCHAR_TO_UTF8(*geom2)); + if (bOverride_geom1) MjSetString(Element->geomname1, geom1); + if (bOverride_geom2) MjSetString(Element->geomname2, geom2); if (bOverride_condim) Element->condim = condim; - if (bOverride_friction) { for (int32 i = 0; i < friction.Num(); ++i) Element->friction[i] = friction[i]; } - if (bOverride_solref) { for (int32 i = 0; i < solref.Num(); ++i) Element->solref[i] = solref[i]; } - if (bOverride_solreffriction) { for (int32 i = 0; i < solreffriction.Num(); ++i) Element->solreffriction[i] = solreffriction[i]; } - if (bOverride_solimp) { for (int32 i = 0; i < solimp.Num(); ++i) Element->solimp[i] = solimp[i]; } + if (bOverride_friction) { for (int32 i = 0; i < FMath::Min(friction.Num(), 5); ++i) Element->friction[i] = friction[i]; } + if (bOverride_solref) { for (int32 i = 0; i < FMath::Min(solref.Num(), 2); ++i) Element->solref[i] = solref[i]; } + if (bOverride_solreffriction) { for (int32 i = 0; i < FMath::Min(solreffriction.Num(), 2); ++i) Element->solreffriction[i] = solreffriction[i]; } + if (bOverride_solimp) { for (int32 i = 0; i < FMath::Min(solimp.Num(), 5); ++i) Element->solimp[i] = solimp[i]; } if (bOverride_gap) Element->gap = gap; if (bOverride_margin) Element->margin = margin; // --- CODEGEN_EXPORT_END --- @@ -106,14 +91,8 @@ void UMjContactPair::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* Parent UE_LOG(LogURLabWrapper, Log, TEXT("Added contact pair: %s->%s"), *geom1, *geom2); } -void UMjContactPair::Bind(mjModel* model, mjData* data, const FString& Prefix) -{ - // Contact pairs are global static data in MuJoCo, usually not bound to runtime indices easily or needed for runtime update. -} - #if WITH_EDITOR -TArray UMjContactPair::GetGeomOptions() const -{ - return UMjComponent::GetSiblingComponentOptions(this, UMjGeom::StaticClass()); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjContactPair::GetGeomOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjGeom::StaticClass()); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Physics/MjInertial.cpp b/Source/URLab/Private/MuJoCo/Components/Physics/MjInertial.cpp index 306ad7d..1c0813a 100644 --- a/Source/URLab/Private/MuJoCo/Components/Physics/MjInertial.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Physics/MjInertial.cpp @@ -54,7 +54,7 @@ void UMjInertial::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& } if (bOverride_Pos) SetRelativeLocation(Pos); if (bOverride_Quat) SetRelativeRotation(Quat); - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- } void UMjInertial::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody) @@ -86,6 +86,3 @@ void UMjInertial::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBod MjUtils::UEToMjRotation(RelTrans.GetRotation(), ParentBody->iquat); } -void UMjInertial::Bind(mjModel* model, mjData* data, const FString& Prefix) -{ -} diff --git a/Source/URLab/Private/MuJoCo/Components/QuickConvert/AMjHeightfieldActor.cpp b/Source/URLab/Private/MuJoCo/Components/QuickConvert/AMjHeightfieldActor.cpp index 6a4d0d1..d1e8c75 100644 --- a/Source/URLab/Private/MuJoCo/Components/QuickConvert/AMjHeightfieldActor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/QuickConvert/AMjHeightfieldActor.cpp @@ -21,6 +21,7 @@ // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. #include "MuJoCo/Components/QuickConvert/AMjHeightfieldActor.h" +#include "MuJoCo/Utils/MjUtils.h" #include "DrawDebugHelpers.h" #include "MuJoCo/Components/QuickConvert/MjQuickConvertComponent.h" @@ -340,7 +341,7 @@ void AMjHeightfieldActor::Setup(mjSpec* Spec, mjVFS* /*VFS*/) mjs_setName(Geom->element, TCHAR_TO_UTF8(*GeomName)); Geom->type = mjGEOM_HFIELD; - mjs_setString(Geom->hfieldname, TCHAR_TO_UTF8(*HFieldName)); + MjSetStringRaw(Geom->hfieldname, HFieldName); Geom->pos[0] = (Bounds.Min.X + Bounds.Max.X) / 200.0; Geom->pos[1] = -(Bounds.Min.Y + Bounds.Max.Y) / 200.0; diff --git a/Source/URLab/Private/MuJoCo/Components/QuickConvert/MjQuickConvertComponent.cpp b/Source/URLab/Private/MuJoCo/Components/QuickConvert/MjQuickConvertComponent.cpp index 8bd095d..495cbd1 100644 --- a/Source/URLab/Private/MuJoCo/Components/QuickConvert/MjQuickConvertComponent.cpp +++ b/Source/URLab/Private/MuJoCo/Components/QuickConvert/MjQuickConvertComponent.cpp @@ -76,10 +76,10 @@ void UMjQuickConvertComponent::DrawDebugCollision() { if (!World) return; for (auto geom_view : m_CreatedBody->GetMj().Geoms()) { - int meshId = geom_view.dataid; + int meshId = geom_view.geom_dataid; - mjtNum* pos = geom_view.xpos; - mjtNum* mat = geom_view.xmat; + mjtNum* pos = geom_view.geom_xpos; + mjtNum* mat = geom_view.geom_xmat; FVector Position = FVector(pos[0], -pos[1], pos[2]); Position *= Multiplier; diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjAccelerometer.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjAccelerometer.cpp index 6e61b1b..15aeed8 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjAccelerometer.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjAccelerometer.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjAccelerometer.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjAccelerometer::UMjAccelerometer() { Type = EMjSensorType::Accelerometer; } -void UMjAccelerometer::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjAccelerometer::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjAccelerometer::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorFrcSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorFrcSensor.cpp index 6da948f..8c1c1e1 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorFrcSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorFrcSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjActuatorFrcSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjActuatorFrcSensor::UMjActuatorFrcSensor() { Type = EMjSensorType::ActuatorFrc; } -void UMjActuatorFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjActuatorFrcSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjActuatorFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorPosSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorPosSensor.cpp index 7264c0b..2667c95 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorPosSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorPosSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjActuatorPosSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjActuatorPosSensor::UMjActuatorPosSensor() { Type = EMjSensorType::ActuatorPos; } -void UMjActuatorPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjActuatorPosSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjActuatorPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorVelSensor.cpp index 856142f..943ec91 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjActuatorVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjActuatorVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjActuatorVelSensor::UMjActuatorVelSensor() { Type = EMjSensorType::ActuatorVel; } -void UMjActuatorVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjActuatorVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjActuatorVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallAngVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallAngVelSensor.cpp index 40cb1a2..7b1e8a2 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallAngVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallAngVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjBallAngVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjBallAngVelSensor::UMjBallAngVelSensor() { Type = EMjSensorType::BallAngVel; } -void UMjBallAngVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjBallAngVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjBallAngVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallQuatSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallQuatSensor.cpp index 0da6eb5..b81903f 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallQuatSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjBallQuatSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjBallQuatSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjBallQuatSensor::UMjBallQuatSensor() { Type = EMjSensorType::BallQuat; } -void UMjBallQuatSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjBallQuatSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjBallQuatSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamProjectionSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamProjectionSensor.cpp index ce59afb..d7deabf 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamProjectionSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamProjectionSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjCamProjectionSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjCamProjectionSensor::UMjCamProjectionSensor() { Type = EMjSensorType::CamProjection; } -void UMjCamProjectionSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjCamProjectionSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjCamProjectionSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamera.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamera.cpp index b41cbf9..bb979c1 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamera.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjCamera.cpp @@ -690,14 +690,14 @@ void UMjCamera::ExportTo(mjsCamera* Element, mjsDefault* /*def*/) } if (bOverride_fovy) Element->fovy = fovy; if (bOverride_ipd) Element->ipd = ipd; - if (bOverride_resolution) { for (int32 i = 0; i < resolution.Num(); ++i) Element->resolution[i] = resolution[i]; } + if (bOverride_resolution) { for (int32 i = 0; i < FMath::Min(resolution.Num(), 2); ++i) Element->resolution[i] = resolution[i]; } if (bOverride_output) Element->output = output; - if (bOverride_target && !target.IsEmpty()) mjs_setString(Element->targetbody, TCHAR_TO_UTF8(*target)); - if (bOverride_focal) { for (int32 i = 0; i < focal.Num(); ++i) Element->focal_length[i] = focal[i]; } - if (bOverride_focalpixel) { for (int32 i = 0; i < focalpixel.Num(); ++i) Element->focal_pixel[i] = focalpixel[i]; } - if (bOverride_principal) { for (int32 i = 0; i < principal.Num(); ++i) Element->principal_length[i] = principal[i]; } - if (bOverride_principalpixel) { for (int32 i = 0; i < principalpixel.Num(); ++i) Element->principal_pixel[i] = principalpixel[i]; } - if (bOverride_sensorsize) { for (int32 i = 0; i < sensorsize.Num(); ++i) Element->sensor_size[i] = sensorsize[i]; } + if (bOverride_target) MjSetString(Element->targetbody, target); + if (bOverride_focal) { for (int32 i = 0; i < FMath::Min(focal.Num(), 2); ++i) Element->focal_length[i] = focal[i]; } + if (bOverride_focalpixel) { for (int32 i = 0; i < FMath::Min(focalpixel.Num(), 2); ++i) Element->focal_pixel[i] = focalpixel[i]; } + if (bOverride_principal) { for (int32 i = 0; i < FMath::Min(principal.Num(), 2); ++i) Element->principal_length[i] = principal[i]; } + if (bOverride_principalpixel) { for (int32 i = 0; i < FMath::Min(principalpixel.Num(), 2); ++i) Element->principal_pixel[i] = principalpixel[i]; } + if (bOverride_sensorsize) { for (int32 i = 0; i < FMath::Min(sensorsize.Num(), 2); ++i) Element->sensor_size[i] = sensorsize[i]; } // --- CODEGEN_EXPORT_END --- } @@ -712,22 +712,25 @@ void UMjCamera::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C if (!Node) return; // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("name"), MjName); { // xml_enum: mode -> EMjCameraTrackingMode FString S = Node->GetAttribute(TEXT("mode")); S = S.ToLower(); - if (S == TEXT("fixed")) TrackingMode = EMjCameraTrackingMode::Fixed; - else if (S == TEXT("track")) TrackingMode = EMjCameraTrackingMode::Track; - else if (S == TEXT("trackcom")) TrackingMode = EMjCameraTrackingMode::TrackCom; - else if (S == TEXT("targetbody")) TrackingMode = EMjCameraTrackingMode::TargetBody; - else if (S == TEXT("targetbodycom")) TrackingMode = EMjCameraTrackingMode::TargetBodyCom; - if (!S.IsEmpty()) bOverride_TrackingMode = true; + bool bMatched = false; + if (S == TEXT("fixed")) { TrackingMode = EMjCameraTrackingMode::Fixed; bMatched = true; } + else if (S == TEXT("track")) { TrackingMode = EMjCameraTrackingMode::Track; bMatched = true; } + else if (S == TEXT("trackcom")) { TrackingMode = EMjCameraTrackingMode::TrackCom; bMatched = true; } + else if (S == TEXT("targetbody")) { TrackingMode = EMjCameraTrackingMode::TargetBody; bMatched = true; } + else if (S == TEXT("targetbodycom")) { TrackingMode = EMjCameraTrackingMode::TargetBodyCom; bMatched = true; } + if (bMatched) bOverride_TrackingMode = true; } { // xml_enum: projection -> EMjCameraProjection FString S = Node->GetAttribute(TEXT("projection")); S = S.ToLower(); - if (S == TEXT("orthographic")) Projection = EMjCameraProjection::Orthographic; - else if (S == TEXT("perspective")) Projection = EMjCameraProjection::Perspective; - if (!S.IsEmpty()) bOverride_Projection = true; + bool bMatched = false; + if (S == TEXT("orthographic")) { Projection = EMjCameraProjection::Orthographic; bMatched = true; } + else if (S == TEXT("perspective")) { Projection = EMjCameraProjection::Perspective; bMatched = true; } + if (bMatched) bOverride_Projection = true; } MjXmlUtils::ReadAttrFloat(Node, TEXT("fovy"), fovy, bOverride_fovy); MjXmlUtils::ReadAttrFloat(Node, TEXT("ipd"), ipd, bOverride_ipd); @@ -750,11 +753,11 @@ void UMjCamera::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C } if (bOverride_Pos) SetRelativeLocation(Pos); if (bOverride_Quat) SetRelativeRotation(Quat); - // --- CODEGEN_IMPORT_END --- + // --- CODEGEN_IMPORT_END --- - // Name - if (!MjXmlUtils::ReadAttrString(Node, TEXT("name"), MjName)) - MjName = TEXT("Camera"); + // Name fallback (codegen above reads MjName from the "name" attribute; + // here we provide a sensible default if the user omitted it). + if (MjName.IsEmpty()) MjName = TEXT("Camera"); // fovy FString FovyStr = Node->GetAttribute(TEXT("fovy")); diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjClockSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjClockSensor.cpp index 68fffe2..c57125b 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjClockSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjClockSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjClockSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjClockSensor::UMjClockSensor() { Type = EMjSensorType::Clock; } -void UMjClockSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjClockSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjClockSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjContactSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjContactSensor.cpp index c1f3011..cde9646 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjContactSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjContactSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjContactSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjContactSensor::UMjContactSensor() { Type = EMjSensorType::Contact; } -void UMjContactSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjContactSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjContactSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjEKineticSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjEKineticSensor.cpp index 2542a32..01f7275 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjEKineticSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjEKineticSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjEKineticSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjEKineticSensor::UMjEKineticSensor() { Type = EMjSensorType::EKinetic; } -void UMjEKineticSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjEKineticSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjEKineticSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjEPotentialSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjEPotentialSensor.cpp index a8bd394..202cf62 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjEPotentialSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjEPotentialSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjEPotentialSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjEPotentialSensor::UMjEPotentialSensor() { Type = EMjSensorType::EPotential; } -void UMjEPotentialSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjEPotentialSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjEPotentialSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjForceSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjForceSensor.cpp index 3e140fc..3de8e3a 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjForceSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjForceSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjForceSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjForceSensor::UMjForceSensor() { Type = EMjSensorType::Force; } -void UMjForceSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjForceSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjForceSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngAccSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngAccSensor.cpp index b597799..9608dcc 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngAccSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngAccSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameAngAccSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameAngAccSensor::UMjFrameAngAccSensor() { Type = EMjSensorType::FrameAngAcc; } -void UMjFrameAngAccSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameAngAccSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameAngAccSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngVelSensor.cpp index bc614eb..b5952f0 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameAngVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameAngVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameAngVelSensor::UMjFrameAngVelSensor() { Type = EMjSensorType::FrameAngVel; } -void UMjFrameAngVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameAngVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameAngVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinAccSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinAccSensor.cpp index 5421170..925f269 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinAccSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinAccSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameLinAccSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameLinAccSensor::UMjFrameLinAccSensor() { Type = EMjSensorType::FrameLinAcc; } -void UMjFrameLinAccSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameLinAccSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameLinAccSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinVelSensor.cpp index 29a6c1a..3064df3 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameLinVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameLinVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameLinVelSensor::UMjFrameLinVelSensor() { Type = EMjSensorType::FrameLinVel; } -void UMjFrameLinVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameLinVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameLinVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFramePosSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFramePosSensor.cpp index 768fb3e..716a940 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFramePosSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFramePosSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFramePosSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFramePosSensor::UMjFramePosSensor() { Type = EMjSensorType::FramePos; } -void UMjFramePosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFramePosSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFramePosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameQuatSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameQuatSensor.cpp index 1d1b016..c16132b 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameQuatSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameQuatSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameQuatSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameQuatSensor::UMjFrameQuatSensor() { Type = EMjSensorType::FrameQuat; } -void UMjFrameQuatSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameQuatSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameQuatSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameXAxisSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameXAxisSensor.cpp index b5671a7..a9d2b56 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameXAxisSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameXAxisSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameXAxisSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameXAxisSensor::UMjFrameXAxisSensor() { Type = EMjSensorType::FrameXAxis; } -void UMjFrameXAxisSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameXAxisSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameXAxisSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameYAxisSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameYAxisSensor.cpp index 7de49a0..e9d237a 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameYAxisSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameYAxisSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameYAxisSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameYAxisSensor::UMjFrameYAxisSensor() { Type = EMjSensorType::FrameYAxis; } -void UMjFrameYAxisSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameYAxisSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameYAxisSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameZAxisSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameZAxisSensor.cpp index f12fa5d..79f8c0e 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameZAxisSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjFrameZAxisSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjFrameZAxisSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjFrameZAxisSensor::UMjFrameZAxisSensor() { Type = EMjSensorType::FrameZAxis; } -void UMjFrameZAxisSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjFrameZAxisSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjFrameZAxisSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomDistSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomDistSensor.cpp index f61fb61..72d8040 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomDistSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomDistSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjGeomDistSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjGeomDistSensor::UMjGeomDistSensor() { Type = EMjSensorType::GeomDist; } -void UMjGeomDistSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjGeomDistSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjGeomDistSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomFromToSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomFromToSensor.cpp index 822c0bf..220e01c 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomFromToSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomFromToSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjGeomFromToSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjGeomFromToSensor::UMjGeomFromToSensor() { Type = EMjSensorType::GeomFromTo; } -void UMjGeomFromToSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjGeomFromToSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjGeomFromToSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomNormalSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomNormalSensor.cpp index d30bf53..e7877aa 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomNormalSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGeomNormalSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjGeomNormalSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjGeomNormalSensor::UMjGeomNormalSensor() { Type = EMjSensorType::GeomNormal; } -void UMjGeomNormalSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjGeomNormalSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjGeomNormalSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGyro.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGyro.cpp index 020722e..1aa11ed 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjGyro.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjGyro.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjGyro.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjGyro::UMjGyro() { Type = EMjSensorType::Gyro; } -void UMjGyro::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjGyro::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjGyro::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjInsideSiteSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjInsideSiteSensor.cpp index d7323c9..a31eb6c 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjInsideSiteSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjInsideSiteSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjInsideSiteSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjInsideSiteSensor::UMjInsideSiteSensor() { Type = EMjSensorType::InsideSite; } -void UMjInsideSiteSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjInsideSiteSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjInsideSiteSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointActFrcSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointActFrcSensor.cpp index b8e2cba..1c4fc29 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointActFrcSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointActFrcSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjJointActFrcSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjJointActFrcSensor::UMjJointActFrcSensor() { Type = EMjSensorType::JointActFrc; } -void UMjJointActFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjJointActFrcSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjJointActFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.cpp index 62becfd..eb80d81 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjJointLimitFrcSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjJointLimitFrcSensor::UMjJointLimitFrcSensor() { Type = EMjSensorType::JointLimitFrc; } -void UMjJointLimitFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjJointLimitFrcSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjJointLimitFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitPosSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitPosSensor.cpp index 4217fc9..0276d0e 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitPosSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitPosSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjJointLimitPosSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjJointLimitPosSensor::UMjJointLimitPosSensor() { Type = EMjSensorType::JointLimitPos; } -void UMjJointLimitPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjJointLimitPosSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjJointLimitPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitVelSensor.cpp index c16ebbd..4916352 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointLimitVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjJointLimitVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjJointLimitVelSensor::UMjJointLimitVelSensor() { Type = EMjSensorType::JointLimitVel; } -void UMjJointLimitVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjJointLimitVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjJointLimitVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointPosSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointPosSensor.cpp index 2d14341..5f9b2e4 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointPosSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointPosSensor.cpp @@ -36,7 +36,6 @@ void UMjJointPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - // --- CODEGEN_EXPORT_END --- } @@ -46,7 +45,6 @@ void UMjJointPosSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSet if (!Node) return; // --- CODEGEN_IMPORT_START --- - // --- CODEGEN_IMPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointVelSensor.cpp index e0830f4..6e3c534 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjJointVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjJointVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjJointVelSensor::UMjJointVelSensor() { Type = EMjSensorType::JointVel; } -void UMjJointVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjJointVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjJointVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjMagnetometer.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjMagnetometer.cpp index 977cf39..41afa06 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjMagnetometer.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjMagnetometer.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjMagnetometer.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjMagnetometer::UMjMagnetometer() { Type = EMjSensorType::Magnetometer; } -void UMjMagnetometer::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjMagnetometer::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjMagnetometer::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjPluginSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjPluginSensor.cpp index 261c0ba..eba640b 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjPluginSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjPluginSensor.cpp @@ -41,7 +41,7 @@ void UMjPluginSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSetti if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } @@ -52,6 +52,6 @@ void UMjPluginSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - + // (no type-specific schema exports) // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjRangeFinderSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjRangeFinderSensor.cpp index 043f546..8fa9413 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjRangeFinderSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjRangeFinderSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjRangeFinderSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjRangeFinderSensor::UMjRangeFinderSensor() { Type = EMjSensorType::RangeFinder; } -void UMjRangeFinderSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjRangeFinderSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjRangeFinderSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSensor.cpp index b9e2f52..2c2d73d 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSensor.cpp @@ -110,8 +110,8 @@ void UMjSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) { if (!Element) return; - if (!TargetName.IsEmpty()) mjs_setString(Element->objname, TCHAR_TO_UTF8(*TargetName)); - if (!ReferenceName.IsEmpty()) mjs_setString(Element->refname, TCHAR_TO_UTF8(*ReferenceName)); + MjSetString(Element->objname, TargetName); + MjSetString(Element->refname, ReferenceName); // Most built-in sensor types have `dim` derived from the sensor type // during mj_compile (e.g. accelerometer dim=3). Writing 0 here zeros @@ -126,76 +126,66 @@ void UMjSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) switch(Type) { - case EMjSensorType::Touch: Element->type = mjSENS_TOUCH; Element->objtype = mjOBJ_SITE; break; - case EMjSensorType::Accelerometer: Element->type = mjSENS_ACCELEROMETER; Element->objtype = mjOBJ_SITE; break; - case EMjSensorType::Velocimeter: Element->type = mjSENS_VELOCIMETER; Element->objtype = mjOBJ_SITE; break; - case EMjSensorType::Gyro: Element->type = mjSENS_GYRO; Element->objtype = mjOBJ_SITE; break; - case EMjSensorType::Force: Element->type = mjSENS_FORCE; Element->objtype = mjOBJ_SITE; break; - case EMjSensorType::Torque: Element->type = mjSENS_TORQUE; Element->objtype = mjOBJ_SITE; break; - case EMjSensorType::Magnetometer: Element->type = mjSENS_MAGNETOMETER; Element->objtype = mjOBJ_SITE; break; - - case EMjSensorType::CamProjection: - Element->type = mjSENS_CAMPROJECTION; - Element->objtype = mjOBJ_SITE; - Element->reftype = mjOBJ_CAMERA; - break; - + // --- CODEGEN_SENSOR_TYPE_SWITCH_START --- + case EMjSensorType::Touch: Element->type = mjSENS_TOUCH; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::Accelerometer: Element->type = mjSENS_ACCELEROMETER; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::Velocimeter: Element->type = mjSENS_VELOCIMETER; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::Gyro: Element->type = mjSENS_GYRO; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::Force: Element->type = mjSENS_FORCE; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::Torque: Element->type = mjSENS_TORQUE; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::Magnetometer: Element->type = mjSENS_MAGNETOMETER; Element->objtype = mjOBJ_SITE; break; + case EMjSensorType::CamProjection: Element->type = mjSENS_CAMPROJECTION; Element->objtype = mjOBJ_SITE; Element->reftype = mjOBJ_CAMERA; break; case EMjSensorType::RangeFinder: - Element->type = mjSENS_RANGEFINDER; - Element->objtype = (ObjType == EMjObjType::Camera) ? mjOBJ_CAMERA : mjOBJ_SITE; - break; - - case EMjSensorType::JointPos: Element->type = mjSENS_JOINTPOS; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::JointVel: Element->type = mjSENS_JOINTVEL; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::JointActFrc: Element->type = mjSENS_JOINTACTFRC; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::BallQuat: Element->type = mjSENS_BALLQUAT; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::BallAngVel: Element->type = mjSENS_BALLANGVEL; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::JointLimitPos: Element->type = mjSENS_JOINTLIMITPOS; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::JointLimitVel: Element->type = mjSENS_JOINTLIMITVEL; Element->objtype = mjOBJ_JOINT; break; - case EMjSensorType::JointLimitFrc: Element->type = mjSENS_JOINTLIMITFRC; Element->objtype = mjOBJ_JOINT; break; - - case EMjSensorType::TendonPos: Element->type = mjSENS_TENDONPOS; Element->objtype = mjOBJ_TENDON; break; - case EMjSensorType::TendonVel: Element->type = mjSENS_TENDONVEL; Element->objtype = mjOBJ_TENDON; break; - case EMjSensorType::TendonActFrc: Element->type = mjSENS_TENDONACTFRC; Element->objtype = mjOBJ_TENDON; break; - case EMjSensorType::TendonLimitPos: Element->type = mjSENS_TENDONLIMITPOS; Element->objtype = mjOBJ_TENDON; break; - case EMjSensorType::TendonLimitVel: Element->type = mjSENS_TENDONLIMITVEL; Element->objtype = mjOBJ_TENDON; break; - case EMjSensorType::TendonLimitFrc: Element->type = mjSENS_TENDONLIMITFRC; Element->objtype = mjOBJ_TENDON; break; - - case EMjSensorType::ActuatorPos: Element->type = mjSENS_ACTUATORPOS; Element->objtype = mjOBJ_ACTUATOR; break; - case EMjSensorType::ActuatorVel: Element->type = mjSENS_ACTUATORVEL; Element->objtype = mjOBJ_ACTUATOR; break; - case EMjSensorType::ActuatorFrc: Element->type = mjSENS_ACTUATORFRC; Element->objtype = mjOBJ_ACTUATOR; break; - - case EMjSensorType::FramePos: Element->type = mjSENS_FRAMEPOS; break; - case EMjSensorType::FrameQuat: Element->type = mjSENS_FRAMEQUAT; break; - case EMjSensorType::FrameXAxis: Element->type = mjSENS_FRAMEXAXIS; break; - case EMjSensorType::FrameYAxis: Element->type = mjSENS_FRAMEYAXIS; break; - case EMjSensorType::FrameZAxis: Element->type = mjSENS_FRAMEZAXIS; break; - case EMjSensorType::FrameLinVel: Element->type = mjSENS_FRAMELINVEL; break; - case EMjSensorType::FrameAngVel: Element->type = mjSENS_FRAMEANGVEL; break; - case EMjSensorType::FrameLinAcc: Element->type = mjSENS_FRAMELINACC; break; - case EMjSensorType::FrameAngAcc: Element->type = mjSENS_FRAMEANGACC; break; - - case EMjSensorType::InsideSite: Element->type = mjSENS_INSIDESITE; Element->objtype = (mjtObj)EnumToMjObj(ObjType); Element->reftype = mjOBJ_SITE; break; - case EMjSensorType::SubtreeCom: Element->type = mjSENS_SUBTREECOM; Element->objtype = mjOBJ_BODY; break; - case EMjSensorType::SubtreeLinVel: Element->type = mjSENS_SUBTREELINVEL; Element->objtype = mjOBJ_BODY; break; - case EMjSensorType::SubtreeAngMom: Element->type = mjSENS_SUBTREEANGMOM; Element->objtype = mjOBJ_BODY; break; - - case EMjSensorType::GeomDist: Element->type = mjSENS_GEOMDIST; break; - case EMjSensorType::GeomNormal: Element->type = mjSENS_GEOMNORMAL; break; - case EMjSensorType::GeomFromTo: Element->type = mjSENS_GEOMFROMTO; break; - - case EMjSensorType::Contact: Element->type = mjSENS_CONTACT; break; - case EMjSensorType::EPotential: Element->type = mjSENS_E_POTENTIAL; break; - case EMjSensorType::EKinetic: Element->type = mjSENS_E_KINETIC; break; - case EMjSensorType::Clock: Element->type = mjSENS_CLOCK; break; - - case EMjSensorType::Tactile: Element->type = mjSENS_TACTILE; Element->objtype = mjOBJ_MESH; Element->reftype = mjOBJ_GEOM; break; - case EMjSensorType::Plugin: Element->type = mjSENS_PLUGIN; break; - case EMjSensorType::User: Element->type = mjSENS_USER; break; - - default: Element->type = mjSENS_ACCELEROMETER; Element->objtype = mjOBJ_SITE; break; + Element->type = mjSENS_RANGEFINDER; Element->objtype = (ObjType == EMjObjType::Camera) ? mjOBJ_CAMERA : mjOBJ_SITE; break; + case EMjSensorType::JointPos: Element->type = mjSENS_JOINTPOS; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::JointVel: Element->type = mjSENS_JOINTVEL; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::BallQuat: Element->type = mjSENS_BALLQUAT; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::BallAngVel: Element->type = mjSENS_BALLANGVEL; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::JointLimitPos: Element->type = mjSENS_JOINTLIMITPOS; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::JointLimitVel: Element->type = mjSENS_JOINTLIMITVEL; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::JointLimitFrc: Element->type = mjSENS_JOINTLIMITFRC; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::TendonPos: Element->type = mjSENS_TENDONPOS; Element->objtype = mjOBJ_TENDON; break; + case EMjSensorType::TendonVel: Element->type = mjSENS_TENDONVEL; Element->objtype = mjOBJ_TENDON; break; + case EMjSensorType::TendonLimitPos: Element->type = mjSENS_TENDONLIMITPOS; Element->objtype = mjOBJ_TENDON; break; + case EMjSensorType::TendonLimitVel: Element->type = mjSENS_TENDONLIMITVEL; Element->objtype = mjOBJ_TENDON; break; + case EMjSensorType::TendonLimitFrc: Element->type = mjSENS_TENDONLIMITFRC; Element->objtype = mjOBJ_TENDON; break; + case EMjSensorType::ActuatorPos: Element->type = mjSENS_ACTUATORPOS; Element->objtype = mjOBJ_ACTUATOR; break; + case EMjSensorType::ActuatorVel: Element->type = mjSENS_ACTUATORVEL; Element->objtype = mjOBJ_ACTUATOR; break; + case EMjSensorType::ActuatorFrc: Element->type = mjSENS_ACTUATORFRC; Element->objtype = mjOBJ_ACTUATOR; break; + case EMjSensorType::JointActFrc: Element->type = mjSENS_JOINTACTFRC; Element->objtype = mjOBJ_JOINT; break; + case EMjSensorType::TendonActFrc: Element->type = mjSENS_TENDONACTFRC; Element->objtype = mjOBJ_TENDON; break; + case EMjSensorType::FramePos: Element->type = mjSENS_FRAMEPOS; break; + case EMjSensorType::FrameQuat: Element->type = mjSENS_FRAMEQUAT; break; + case EMjSensorType::FrameXAxis: Element->type = mjSENS_FRAMEXAXIS; break; + case EMjSensorType::FrameYAxis: Element->type = mjSENS_FRAMEYAXIS; break; + case EMjSensorType::FrameZAxis: Element->type = mjSENS_FRAMEZAXIS; break; + case EMjSensorType::FrameLinVel: Element->type = mjSENS_FRAMELINVEL; break; + case EMjSensorType::FrameAngVel: Element->type = mjSENS_FRAMEANGVEL; break; + case EMjSensorType::FrameLinAcc: Element->type = mjSENS_FRAMELINACC; break; + case EMjSensorType::FrameAngAcc: Element->type = mjSENS_FRAMEANGACC; break; + case EMjSensorType::SubtreeCom: Element->type = mjSENS_SUBTREECOM; Element->objtype = mjOBJ_BODY; break; + case EMjSensorType::SubtreeLinVel: Element->type = mjSENS_SUBTREELINVEL; Element->objtype = mjOBJ_BODY; break; + case EMjSensorType::SubtreeAngMom: Element->type = mjSENS_SUBTREEANGMOM; Element->objtype = mjOBJ_BODY; break; + case EMjSensorType::InsideSite: Element->type = mjSENS_INSIDESITE; Element->reftype = mjOBJ_SITE; break; + case EMjSensorType::GeomDist: Element->type = mjSENS_GEOMDIST; break; + case EMjSensorType::GeomNormal: Element->type = mjSENS_GEOMNORMAL; break; + case EMjSensorType::GeomFromTo: Element->type = mjSENS_GEOMFROMTO; break; + case EMjSensorType::Contact: Element->type = mjSENS_CONTACT; break; + case EMjSensorType::EPotential: Element->type = mjSENS_E_POTENTIAL; Element->objtype = mjOBJ_UNKNOWN; break; + case EMjSensorType::EKinetic: Element->type = mjSENS_E_KINETIC; Element->objtype = mjOBJ_UNKNOWN; break; + case EMjSensorType::Clock: Element->type = mjSENS_CLOCK; Element->objtype = mjOBJ_UNKNOWN; break; + case EMjSensorType::Tactile: Element->type = mjSENS_TACTILE; Element->objtype = mjOBJ_MESH; Element->reftype = mjOBJ_GEOM; break; + case EMjSensorType::User: Element->type = mjSENS_USER; break; + case EMjSensorType::Plugin: Element->type = mjSENS_PLUGIN; break; + default: Element->type = mjSENS_ACCELEROMETER; Element->objtype = mjOBJ_SITE; break; + // --- CODEGEN_SENSOR_TYPE_SWITCH_END --- } + // Variable objtype / reftype handling. The codegen switch above sets + // STATIC objtype/reftype literals when sensor_per_type carries a + // mjOBJ_X value. For sensors whose objtype/reftype is "from_xml" or + // "computed" in MuJoCo, the UE side reads ObjType / RefType properties + // and translates them here AFTER the switch fires. if (Element->type >= mjSENS_FRAMEPOS && Element->type <= mjSENS_FRAMEANGACC) { Element->objtype = (mjtObj)EnumToMjObj(ObjType); @@ -206,8 +196,10 @@ void UMjSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) Element->objtype = (mjtObj)EnumToMjObj(ObjType); Element->reftype = (mjtObj)EnumToMjObj(RefType); } - else if (Type == EMjSensorType::User) + else if (Type == EMjSensorType::User || Type == EMjSensorType::InsideSite) { + // InsideSite's reftype = mjOBJ_SITE is already set by the codegen + // switch above; here we add the UE-driven objtype. Element->objtype = (mjtObj)EnumToMjObj(ObjType); } @@ -215,10 +207,12 @@ void UMjSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) if (bOverride_nsample) Element->nsample = nsample; if (bOverride_interp) Element->interp = interp; if (bOverride_delay) Element->delay = delay; - if (bOverride_interval) { for (int32 i = 0; i < interval.Num(); ++i) Element->interval[i] = interval[i]; } + if (bOverride_interval) { for (int32 i = 0; i < FMath::Min(interval.Num(), 2); ++i) Element->interval[i] = interval[i]; } if (bOverride_cutoff) Element->cutoff = cutoff; if (bOverride_noise) Element->noise = noise; - // --- CODEGEN_EXPORT_END --- + MjSetString(Element->objname, TargetName); + MjSetString(Element->refname, ReferenceName); + // --- CODEGEN_EXPORT_END --- } void UMjSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) @@ -226,72 +220,45 @@ void UMjSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C if (!Node) return; // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); + { // xml_enum: objtype -> EMjObjType + FString S = Node->GetAttribute(TEXT("objtype")); + S = S.ToLower(); + if (S == TEXT("body")) { ObjType = EMjObjType::Body; } + else if (S == TEXT("xbody")) { ObjType = EMjObjType::XBody; } + else if (S == TEXT("joint")) { ObjType = EMjObjType::Joint; } + else if (S == TEXT("dof")) { ObjType = EMjObjType::DoF; } + else if (S == TEXT("geom")) { ObjType = EMjObjType::Geom; } + else if (S == TEXT("site")) { ObjType = EMjObjType::Site; } + else if (S == TEXT("camera")) { ObjType = EMjObjType::Camera; } + else if (S == TEXT("light")) { ObjType = EMjObjType::Light; } + else if (S == TEXT("mesh")) { ObjType = EMjObjType::Mesh; } + else if (S == TEXT("hfield")) { ObjType = EMjObjType::HField; } + else if (S == TEXT("texture")) { ObjType = EMjObjType::Texture; } + else if (S == TEXT("material")) { ObjType = EMjObjType::Material; } + else if (S == TEXT("pair")) { ObjType = EMjObjType::Pair; } + else if (S == TEXT("exclude")) { ObjType = EMjObjType::Exclude; } + else if (S == TEXT("equality")) { ObjType = EMjObjType::Equality; } + else if (S == TEXT("tendon")) { ObjType = EMjObjType::Tendon; } + else if (S == TEXT("actuator")) { ObjType = EMjObjType::Actuator; } + } + { // xml_enum: reftype -> EMjObjType + FString S = Node->GetAttribute(TEXT("reftype")); + S = S.ToLower(); + if (S == TEXT("body")) { RefType = EMjObjType::Body; } + else if (S == TEXT("xbody")) { RefType = EMjObjType::XBody; } + else if (S == TEXT("joint")) { RefType = EMjObjType::Joint; } + else if (S == TEXT("geom")) { RefType = EMjObjType::Geom; } + else if (S == TEXT("site")) { RefType = EMjObjType::Site; } + else if (S == TEXT("camera")) { RefType = EMjObjType::Camera; } + } MjXmlUtils::ReadAttrInt(Node, TEXT("nsample"), nsample, bOverride_nsample); MjXmlUtils::ReadAttrInt(Node, TEXT("interp"), interp, bOverride_interp); MjXmlUtils::ReadAttrFloat(Node, TEXT("delay"), delay, bOverride_delay); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("interval"), interval, bOverride_interval); MjXmlUtils::ReadAttrFloat(Node, TEXT("cutoff"), cutoff, bOverride_cutoff); MjXmlUtils::ReadAttrFloat(Node, TEXT("noise"), noise, bOverride_noise); - // --- CODEGEN_IMPORT_END --- - - // Determine sensor type from the XML tag name - static const TMap TagToType = { - {TEXT("touch"), EMjSensorType::Touch}, - {TEXT("accelerometer"), EMjSensorType::Accelerometer}, - {TEXT("velocimeter"), EMjSensorType::Velocimeter}, - {TEXT("gyro"), EMjSensorType::Gyro}, - {TEXT("force"), EMjSensorType::Force}, - {TEXT("torque"), EMjSensorType::Torque}, - {TEXT("magnetometer"), EMjSensorType::Magnetometer}, - {TEXT("rangefinder"), EMjSensorType::RangeFinder}, - {TEXT("camprojection"), EMjSensorType::CamProjection}, - {TEXT("jointpos"), EMjSensorType::JointPos}, - {TEXT("jointvel"), EMjSensorType::JointVel}, - {TEXT("jointactfrc"), EMjSensorType::JointActFrc}, - {TEXT("tendonpos"), EMjSensorType::TendonPos}, - {TEXT("tendonvel"), EMjSensorType::TendonVel}, - {TEXT("tendonactfrc"), EMjSensorType::TendonActFrc}, - {TEXT("actuatorpos"), EMjSensorType::ActuatorPos}, - {TEXT("actuatorvel"), EMjSensorType::ActuatorVel}, - {TEXT("actuatorfrc"), EMjSensorType::ActuatorFrc}, - {TEXT("ballquat"), EMjSensorType::BallQuat}, - {TEXT("ballangvel"), EMjSensorType::BallAngVel}, - {TEXT("jointlimitpos"), EMjSensorType::JointLimitPos}, - {TEXT("jointlimitvel"), EMjSensorType::JointLimitVel}, - {TEXT("jointlimitfrc"), EMjSensorType::JointLimitFrc}, - {TEXT("tendonlimitpos"), EMjSensorType::TendonLimitPos}, - {TEXT("tendonlimitvel"), EMjSensorType::TendonLimitVel}, - {TEXT("tendonlimitfrc"), EMjSensorType::TendonLimitFrc}, - {TEXT("framepos"), EMjSensorType::FramePos}, - {TEXT("framequat"), EMjSensorType::FrameQuat}, - {TEXT("framexaxis"), EMjSensorType::FrameXAxis}, - {TEXT("frameyaxis"), EMjSensorType::FrameYAxis}, - {TEXT("framezaxis"), EMjSensorType::FrameZAxis}, - {TEXT("framelinvel"), EMjSensorType::FrameLinVel}, - {TEXT("frameangvel"), EMjSensorType::FrameAngVel}, - {TEXT("framelinacc"), EMjSensorType::FrameLinAcc}, - {TEXT("frameangacc"), EMjSensorType::FrameAngAcc}, - {TEXT("subtreecom"), EMjSensorType::SubtreeCom}, - {TEXT("subtreelinvel"), EMjSensorType::SubtreeLinVel}, - {TEXT("subtreeangmom"), EMjSensorType::SubtreeAngMom}, - {TEXT("insidesite"), EMjSensorType::InsideSite}, - {TEXT("geomdist"), EMjSensorType::GeomDist}, - {TEXT("geomnormal"), EMjSensorType::GeomNormal}, - {TEXT("geomfromto"), EMjSensorType::GeomFromTo}, - {TEXT("contact"), EMjSensorType::Contact}, - {TEXT("e_potential"), EMjSensorType::EPotential}, - {TEXT("e_kinetic"), EMjSensorType::EKinetic}, - {TEXT("clock"), EMjSensorType::Clock}, - {TEXT("tactile"), EMjSensorType::Tactile}, - {TEXT("plugin"), EMjSensorType::Plugin}, - {TEXT("user"), EMjSensorType::User}, - }; - const FString Tag = Node->GetTag().ToLower(); - const EMjSensorType* Found = TagToType.Find(Tag); - if (Found) Type = *Found; - - - // Object name: try each attribute in priority order + // target_collation: -> TargetName TargetName = Node->GetAttribute(TEXT("site")); if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("joint")); if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("tendon")); @@ -299,46 +266,77 @@ void UMjSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("body")); if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("geom")); if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("objname")); - - // Reference name (for frame sensors, camprojection, etc.) + if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("camera")); + if (TargetName.IsEmpty()) TargetName = Node->GetAttribute(TEXT("mesh")); + // target_collation: -> ReferenceName ReferenceName = Node->GetAttribute(TEXT("refname")); + // --- CODEGEN_IMPORT_END --- - // objtype / reftype — string attributes specifying object/reference type for frame, - // geomfromto, contact, user, and camprojection sensors. - // Map from MJCF string → EMjObjType so ExportTo() can write the correct mjtObj enum. - static const TMap ObjTypeStrMap = { - {TEXT("body"), EMjObjType::Body}, - {TEXT("xbody"), EMjObjType::XBody}, - {TEXT("joint"), EMjObjType::Joint}, - {TEXT("dof"), EMjObjType::DoF}, - {TEXT("geom"), EMjObjType::Geom}, - {TEXT("site"), EMjObjType::Site}, - {TEXT("camera"), EMjObjType::Camera}, - {TEXT("light"), EMjObjType::Light}, - {TEXT("mesh"), EMjObjType::Mesh}, - {TEXT("hfield"), EMjObjType::HField}, - {TEXT("texture"), EMjObjType::Texture}, - {TEXT("material"), EMjObjType::Material}, - {TEXT("pair"), EMjObjType::Pair}, - {TEXT("exclude"), EMjObjType::Exclude}, - {TEXT("equality"), EMjObjType::Equality}, - {TEXT("tendon"), EMjObjType::Tendon}, - {TEXT("actuator"), EMjObjType::Actuator}, + // Determine sensor type from the XML tag name + static const TMap TagToType = { + // --- CODEGEN_SENSOR_TAG_TO_TYPE_START --- + {TEXT("touch"), EMjSensorType::Touch}, + {TEXT("accelerometer"), EMjSensorType::Accelerometer}, + {TEXT("velocimeter"), EMjSensorType::Velocimeter}, + {TEXT("gyro"), EMjSensorType::Gyro}, + {TEXT("force"), EMjSensorType::Force}, + {TEXT("torque"), EMjSensorType::Torque}, + {TEXT("magnetometer"), EMjSensorType::Magnetometer}, + {TEXT("camprojection"), EMjSensorType::CamProjection}, + {TEXT("rangefinder"), EMjSensorType::RangeFinder}, + {TEXT("jointpos"), EMjSensorType::JointPos}, + {TEXT("jointvel"), EMjSensorType::JointVel}, + {TEXT("ballquat"), EMjSensorType::BallQuat}, + {TEXT("ballangvel"), EMjSensorType::BallAngVel}, + {TEXT("jointlimitpos"), EMjSensorType::JointLimitPos}, + {TEXT("jointlimitvel"), EMjSensorType::JointLimitVel}, + {TEXT("jointlimitfrc"), EMjSensorType::JointLimitFrc}, + {TEXT("tendonpos"), EMjSensorType::TendonPos}, + {TEXT("tendonvel"), EMjSensorType::TendonVel}, + {TEXT("tendonlimitpos"), EMjSensorType::TendonLimitPos}, + {TEXT("tendonlimitvel"), EMjSensorType::TendonLimitVel}, + {TEXT("tendonlimitfrc"), EMjSensorType::TendonLimitFrc}, + {TEXT("actuatorpos"), EMjSensorType::ActuatorPos}, + {TEXT("actuatorvel"), EMjSensorType::ActuatorVel}, + {TEXT("actuatorfrc"), EMjSensorType::ActuatorFrc}, + {TEXT("jointactuatorfrc"), EMjSensorType::JointActFrc}, + {TEXT("tendonactuatorfrc"), EMjSensorType::TendonActFrc}, + {TEXT("framepos"), EMjSensorType::FramePos}, + {TEXT("framequat"), EMjSensorType::FrameQuat}, + {TEXT("framexaxis"), EMjSensorType::FrameXAxis}, + {TEXT("frameyaxis"), EMjSensorType::FrameYAxis}, + {TEXT("framezaxis"), EMjSensorType::FrameZAxis}, + {TEXT("framelinvel"), EMjSensorType::FrameLinVel}, + {TEXT("frameangvel"), EMjSensorType::FrameAngVel}, + {TEXT("framelinacc"), EMjSensorType::FrameLinAcc}, + {TEXT("frameangacc"), EMjSensorType::FrameAngAcc}, + {TEXT("subtreecom"), EMjSensorType::SubtreeCom}, + {TEXT("subtreelinvel"), EMjSensorType::SubtreeLinVel}, + {TEXT("subtreeangmom"), EMjSensorType::SubtreeAngMom}, + {TEXT("insidesite"), EMjSensorType::InsideSite}, + {TEXT("distance"), EMjSensorType::GeomDist}, + {TEXT("normal"), EMjSensorType::GeomNormal}, + {TEXT("fromto"), EMjSensorType::GeomFromTo}, + {TEXT("contact"), EMjSensorType::Contact}, + {TEXT("e_potential"), EMjSensorType::EPotential}, + {TEXT("e_kinetic"), EMjSensorType::EKinetic}, + {TEXT("clock"), EMjSensorType::Clock}, + {TEXT("tactile"), EMjSensorType::Tactile}, + {TEXT("user"), EMjSensorType::User}, + {TEXT("plugin"), EMjSensorType::Plugin}, + // --- CODEGEN_SENSOR_TAG_TO_TYPE_END --- }; + const FString Tag = Node->GetTag().ToLower(); + const EMjSensorType* Found = TagToType.Find(Tag); + if (Found) Type = *Found; - FString ObjTypeStr = Node->GetAttribute(TEXT("objtype")).ToLower(); - if (!ObjTypeStr.IsEmpty()) - { - const EMjObjType* FoundObjType = ObjTypeStrMap.Find(ObjTypeStr); - if (FoundObjType) ObjType = *FoundObjType; - } - FString RefTypeStr = Node->GetAttribute(TEXT("reftype")).ToLower(); - if (!RefTypeStr.IsEmpty()) - { - const EMjObjType* FoundRefType = ObjTypeStrMap.Find(RefTypeStr); - if (FoundRefType) RefType = *FoundRefType; - } + // TargetName / ReferenceName (target_collations), ObjType / RefType + // (xml_enum_attrs), MjClassName (common_imports) are all codegen-emitted + // inside the CODEGEN_IMPORT block above. dim / adr remain hand-written + // here because they need bespoke handling: dim is conditionally written + // (only if XML provides it, preserving the compile-time default), and + // adr is an out-of-band override for user sensors only. // dim override — used by user sensors where the dimension is not fixed by type FString DimStr = Node->GetAttribute(TEXT("dim")); @@ -353,23 +351,12 @@ void UMjSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C bool bAdrOverride = false; MjXmlUtils::ReadAttrInt(Node, TEXT("adr"), UserAdr, bAdrOverride); } - - MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); } void UMjSensor::Bind(mjModel* Model, mjData* Data, const FString& Prefix) { Super::Bind(Model, Data, Prefix); - m_SensorView = BindToView(Prefix); - - if (m_SensorView.id != -1) - { - m_ID = m_SensorView.id; - } - else - { - UE_LOG(LogURLabBind, Warning, TEXT("[MjSensor] Sensor '%s' could not bind! Prefix: %s"), *GetName(), *Prefix); - } + BindAndCacheView(m_SensorView, Prefix); } // Apply the MuJoCo → UE coordinate transform appropriate for each sensor type. @@ -452,10 +439,10 @@ static void TransformSensorReading(TArray& R, EMjSensorType Type) TArray UMjSensor::GetReading() const { TArray Result; - if (m_SensorView.id != -1 && m_SensorView.data) + if (m_SensorView.id != -1 && m_SensorView.sensordata) { - for (int i = 0; i < m_SensorView.dim; ++i) - Result.Add((float)m_SensorView.data[i]); + for (int i = 0; i < m_SensorView.sensor_dim; ++i) + Result.Add((float)m_SensorView.sensordata[i]); TransformSensorReading(Result, Type); } return Result; @@ -463,9 +450,9 @@ TArray UMjSensor::GetReading() const float UMjSensor::GetScalarReading() const { - if (m_SensorView.id != -1 && m_SensorView.data && m_SensorView.dim > 0) + if (m_SensorView.id != -1 && m_SensorView.sensordata && m_SensorView.sensor_dim > 0) { - return (float)m_SensorView.data[0]; + return (float)m_SensorView.sensordata[0]; } return 0.0f; } @@ -473,7 +460,7 @@ float UMjSensor::GetScalarReading() const int UMjSensor::GetDimension() const { if (m_SensorView.id != -1) - return m_SensorView.dim; + return m_SensorView.sensor_dim; return 0; } @@ -502,11 +489,11 @@ void UMjSensor::BuildBinaryPayload(FBufferArchive& OutBuffer) const int32 NumElements = GetDimension(); OutBuffer << NumElements; - if (m_SensorView.id != -1 && m_SensorView.data && NumElements > 0) + if (m_SensorView.id != -1 && m_SensorView.sensordata && NumElements > 0) { for (int i = 0; i < NumElements; ++i) { - float Val = (float)m_SensorView.data[i]; + float Val = (float)m_SensorView.sensordata[i]; OutBuffer << Val; } } @@ -547,8 +534,7 @@ TArray UMjSensor::GetReferenceNameOptions() const return UMjComponent::GetSiblingComponentOptions(this, GetClassForObjType(RefType)); } -TArray UMjSensor::GetDefaultClassOptions() const -{ - return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjSensor::GetDefaultClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.cpp index 4f24533..9a43d3c 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjSubtreeAngMomSensor::UMjSubtreeAngMomSensor() { Type = EMjSensorType::SubtreeAngMom; } -void UMjSubtreeAngMomSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjSubtreeAngMomSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjSubtreeAngMomSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeComSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeComSensor.cpp index 5686734..de7e384 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeComSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeComSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjSubtreeComSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjSubtreeComSensor::UMjSubtreeComSensor() { Type = EMjSensorType::SubtreeCom; } -void UMjSubtreeComSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjSubtreeComSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjSubtreeComSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.cpp index 3368496..fdef06c 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjSubtreeLinVelSensor::UMjSubtreeLinVelSensor() { Type = EMjSensorType::SubtreeLinVel; } -void UMjSubtreeLinVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjSubtreeLinVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjSubtreeLinVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTactileSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTactileSensor.cpp index f7249b1..3a95606 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTactileSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTactileSensor.cpp @@ -44,7 +44,6 @@ void UMjTactileSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - // --- CODEGEN_EXPORT_END --- } @@ -54,7 +53,6 @@ void UMjTactileSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSett if (!Node) return; // --- CODEGEN_IMPORT_START --- - // --- CODEGEN_IMPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonActFrcSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonActFrcSensor.cpp index 35d1e69..7a0929f 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonActFrcSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonActFrcSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTendonActFrcSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTendonActFrcSensor::UMjTendonActFrcSensor() { Type = EMjSensorType::TendonActFrc; } -void UMjTendonActFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTendonActFrcSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTendonActFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.cpp index 6b070c1..c0863bc 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTendonLimitFrcSensor::UMjTendonLimitFrcSensor() { Type = EMjSensorType::TendonLimitFrc; } -void UMjTendonLimitFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTendonLimitFrcSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTendonLimitFrcSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.cpp index 9561b40..f5dfa90 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTendonLimitPosSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTendonLimitPosSensor::UMjTendonLimitPosSensor() { Type = EMjSensorType::TendonLimitPos; } -void UMjTendonLimitPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTendonLimitPosSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTendonLimitPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.cpp index fc06ebc..1b0574f 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTendonLimitVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTendonLimitVelSensor::UMjTendonLimitVelSensor() { Type = EMjSensorType::TendonLimitVel; } -void UMjTendonLimitVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTendonLimitVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTendonLimitVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonPosSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonPosSensor.cpp index c7898f8..0ed5e05 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonPosSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonPosSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTendonPosSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTendonPosSensor::UMjTendonPosSensor() { Type = EMjSensorType::TendonPos; } -void UMjTendonPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTendonPosSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTendonPosSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonVelSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonVelSensor.cpp index c3731b8..5cc0fc5 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonVelSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTendonVelSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTendonVelSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTendonVelSensor::UMjTendonVelSensor() { Type = EMjSensorType::TendonVel; } -void UMjTendonVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTendonVelSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTendonVelSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTorqueSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTorqueSensor.cpp index 1687d15..6153425 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTorqueSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTorqueSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTorqueSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTorqueSensor::UMjTorqueSensor() { Type = EMjSensorType::Torque; } -void UMjTorqueSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTorqueSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTorqueSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTouchSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTouchSensor.cpp index dea2e54..be4fc56 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjTouchSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjTouchSensor.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjTouchSensor.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjTouchSensor::UMjTouchSensor() { Type = EMjSensorType::Touch; } -void UMjTouchSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjTouchSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjTouchSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjUserSensor.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjUserSensor.cpp index e9b860b..1d2f578 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjUserSensor.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjUserSensor.cpp @@ -41,7 +41,7 @@ void UMjUserSensor::ImportFromXml(const FXmlNode* Node, const FMjCompilerSetting if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } @@ -52,6 +52,6 @@ void UMjUserSensor::ExportTo(mjsSensor* Element, mjsDefault* Default) Super::ExportTo(Element, Default); // --- CODEGEN_EXPORT_START --- - + // (no type-specific schema exports) // --- CODEGEN_EXPORT_END --- } diff --git a/Source/URLab/Private/MuJoCo/Components/Sensors/MjVelocimeter.cpp b/Source/URLab/Private/MuJoCo/Components/Sensors/MjVelocimeter.cpp index 7c7c1a4..ba10c86 100644 --- a/Source/URLab/Private/MuJoCo/Components/Sensors/MjVelocimeter.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Sensors/MjVelocimeter.cpp @@ -13,39 +13,45 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #include "MuJoCo/Components/Sensors/MjVelocimeter.h" +#include "MuJoCo/Utils/MjXmlUtils.h" #include "MuJoCo/Utils/MjOrientationUtils.h" +#include "MuJoCo/Utils/MjUtils.h" +#include "XmlNode.h" +#include "mujoco/mjspec.h" UMjVelocimeter::UMjVelocimeter() { Type = EMjSensorType::Velocimeter; } -void UMjVelocimeter::ExportTo(mjsSensor* Element, mjsDefault* Default) -{ - if (!Element) return; - - Super::ExportTo(Element, Default); - - // --- CODEGEN_EXPORT_START --- - - // --- CODEGEN_EXPORT_END --- -} - void UMjVelocimeter::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& CompilerSettings) { Super::ImportFromXml(Node, CompilerSettings); if (!Node) return; // --- CODEGEN_IMPORT_START --- - + // (no type-specific schema imports) // --- CODEGEN_IMPORT_END --- } +void UMjVelocimeter::ExportTo(mjsSensor* Element, mjsDefault* Default) +{ + if (!Element) return; + + Super::ExportTo(Element, Default); + + // --- CODEGEN_EXPORT_START --- + // (no type-specific schema exports) + // --- CODEGEN_EXPORT_END --- +} diff --git a/Source/URLab/Private/MuJoCo/Components/Tendons/MjTendon.cpp b/Source/URLab/Private/MuJoCo/Components/Tendons/MjTendon.cpp index 361f907..3f2f8c2 100644 --- a/Source/URLab/Private/MuJoCo/Components/Tendons/MjTendon.cpp +++ b/Source/URLab/Private/MuJoCo/Components/Tendons/MjTendon.cpp @@ -46,11 +46,12 @@ void UMjTendon::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C if (!Node) return; // --- CODEGEN_IMPORT_START --- + MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); MjXmlUtils::ReadAttrInt(Node, TEXT("group"), group, bOverride_group); MjXmlUtils::ReadAttrBool(Node, TEXT("limited"), limited, bOverride_limited); - MjXmlUtils::ReadAttrBool(Node, TEXT("actuatorfrclimited"), actuatorfrclimited, bOverride_actuatorfrclimited); + MjXmlUtils::ReadAttrBool(Node, TEXT("actuatorfrclimited"), ActFrcLimited, bOverride_ActFrcLimited); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("range"), range, bOverride_range); - MjXmlUtils::ReadAttrFloatArray(Node, TEXT("actuatorfrcrange"), actuatorfrcrange, bOverride_actuatorfrcrange); + MjXmlUtils::ReadAttrFloatArray(Node, TEXT("actuatorfrcrange"), ActFrcRange, bOverride_ActFrcRange); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solreflimit"), solreflimit, bOverride_solreflimit); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solimplimit"), solimplimit, bOverride_solimplimit); MjXmlUtils::ReadAttrFloatArray(Node, TEXT("solreffriction"), solreffriction, bOverride_solreffriction); @@ -64,16 +65,7 @@ void UMjTendon::ImportFromXml(const FXmlNode* Node, const FMjCompilerSettings& C MjXmlUtils::ReadAttrFloatArray(Node, TEXT("damping"), damping, bOverride_damping); MjXmlUtils::ReadAttrFloat(Node, TEXT("armature"), armature, bOverride_armature); MjXmlUtils::ReadAttrColor(Node, TEXT("rgba"), rgba, bOverride_rgba); - // --- CODEGEN_IMPORT_END --- - - // Class name - MjXmlUtils::ReadAttrString(Node, TEXT("class"), MjClassName); - - // --- Physics --- - - // --- Limits --- - MjXmlUtils::ReadAttrBool(Node, TEXT("actfrclimited"), bActFrcLimited, bOverride_ActFrcLimited); - MjXmlUtils::ReadAttrFloatArray(Node, TEXT("actfrcrange"), ActFrcRange, bOverride_ActFrcRange); + // --- CODEGEN_IMPORT_END --- // --- Solver --- @@ -131,35 +123,22 @@ void UMjTendon::ExportTo(mjsTendon* Element, mjsDefault* def) // --- Physics properties --- - // --- Limits --- - - if (bOverride_ActFrcLimited) Element->actfrclimited = bActFrcLimited ? mjLIMITED_TRUE : mjLIMITED_FALSE; - if (bOverride_ActFrcRange) - { - for (int i = 0; i < ActFrcRange.Num() && i < 2; ++i) - Element->actfrcrange[i] = ActFrcRange[i]; - } - - // --- Solver --- - - // --- Visuals --- - - // --- CODEGEN_EXPORT_START --- + // --- CODEGEN_EXPORT_START --- if (bOverride_group) Element->group = group; if (bOverride_limited) Element->limited = limited ? 1 : 0; - if (bOverride_actuatorfrclimited) Element->actfrclimited = actuatorfrclimited ? 1 : 0; - if (bOverride_range) { for (int32 i = 0; i < range.Num(); ++i) Element->range[i] = range[i]; } - if (bOverride_actuatorfrcrange) { for (int32 i = 0; i < actuatorfrcrange.Num(); ++i) Element->actfrcrange[i] = actuatorfrcrange[i]; } - if (bOverride_solreflimit) { for (int32 i = 0; i < solreflimit.Num(); ++i) Element->solref_limit[i] = solreflimit[i]; } - if (bOverride_solimplimit) { for (int32 i = 0; i < solimplimit.Num(); ++i) Element->solimp_limit[i] = solimplimit[i]; } - if (bOverride_solreffriction) { for (int32 i = 0; i < solreffriction.Num(); ++i) Element->solref_friction[i] = solreffriction[i]; } - if (bOverride_solimpfriction) { for (int32 i = 0; i < solimpfriction.Num(); ++i) Element->solimp_friction[i] = solimpfriction[i]; } + if (bOverride_ActFrcLimited) Element->actfrclimited = ActFrcLimited ? 1 : 0; + if (bOverride_range) { for (int32 i = 0; i < FMath::Min(range.Num(), 2); ++i) Element->range[i] = range[i]; } + if (bOverride_ActFrcRange) { for (int32 i = 0; i < FMath::Min(ActFrcRange.Num(), 2); ++i) Element->actfrcrange[i] = ActFrcRange[i]; } + if (bOverride_solreflimit) { for (int32 i = 0; i < FMath::Min(solreflimit.Num(), 2); ++i) Element->solref_limit[i] = solreflimit[i]; } + if (bOverride_solimplimit) { for (int32 i = 0; i < FMath::Min(solimplimit.Num(), 5); ++i) Element->solimp_limit[i] = solimplimit[i]; } + if (bOverride_solreffriction) { for (int32 i = 0; i < FMath::Min(solreffriction.Num(), 2); ++i) Element->solref_friction[i] = solreffriction[i]; } + if (bOverride_solimpfriction) { for (int32 i = 0; i < FMath::Min(solimpfriction.Num(), 5); ++i) Element->solimp_friction[i] = solimpfriction[i]; } if (bOverride_frictionloss) Element->frictionloss = frictionloss; - if (bOverride_springlength) { for (int32 i = 0; i < springlength.Num(); ++i) Element->springlength[i] = springlength[i]; } + if (bOverride_springlength) { for (int32 i = 0; i < FMath::Min(springlength.Num(), 2); ++i) Element->springlength[i] = springlength[i]; } if (bOverride_width) Element->width = width; if (bOverride_margin) Element->margin = margin; - if (bOverride_stiffness) { for (int32 i = 0; i < stiffness.Num(); ++i) Element->stiffness[i] = stiffness[i]; } - if (bOverride_damping) { for (int32 i = 0; i < damping.Num(); ++i) Element->damping[i] = damping[i]; } + if (bOverride_stiffness) { for (int32 i = 0; i < FMath::Min(stiffness.Num(), 3); ++i) Element->stiffness[i] = stiffness[i]; } + if (bOverride_damping) { for (int32 i = 0; i < FMath::Min(damping.Num(), 3); ++i) Element->damping[i] = damping[i]; } if (bOverride_armature) Element->armature = armature; if (bOverride_rgba) { Element->rgba[0] = rgba.R; Element->rgba[1] = rgba.G; Element->rgba[2] = rgba.B; Element->rgba[3] = rgba.A; } // --- CODEGEN_EXPORT_END --- @@ -248,16 +227,7 @@ void UMjTendon::RegisterToSpec(FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody) void UMjTendon::Bind(mjModel* model, mjData* data, const FString& Prefix) { Super::Bind(model, data, Prefix); - m_TendonView = BindToView(Prefix); - if (m_TendonView.id != -1) - { - m_ID = m_TendonView.id; - } - else - { - UE_LOG(LogURLabImport, Warning, TEXT("[MjTendon] Failed to bind tendon '%s' (prefix='%s')"), - *GetName(), *Prefix); - } + BindAndCacheView(m_TendonView, Prefix); } float UMjTendon::GetLength() const @@ -277,10 +247,9 @@ FString UMjTendon::GetMjName() const } #if WITH_EDITOR -TArray UMjTendon::GetDefaultClassOptions() const -{ - return GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); -} +// --- CODEGEN_EDITOR_OPTIONS_START --- +TArray UMjTendon::GetDefaultClassOptions() const { return UMjComponent::GetSiblingComponentOptions(this, UMjDefault::StaticClass(), true); } +// --- CODEGEN_EDITOR_OPTIONS_END --- #endif // --- Multi-UCLASS subclass constructors -------------------------------------- diff --git a/Source/URLab/Private/MuJoCo/Core/MjArticulation.cpp b/Source/URLab/Private/MuJoCo/Core/MjArticulation.cpp index ec7f8d9..235fd85 100644 --- a/Source/URLab/Private/MuJoCo/Core/MjArticulation.cpp +++ b/Source/URLab/Private/MuJoCo/Core/MjArticulation.cpp @@ -238,11 +238,30 @@ void AMjArticulation::UnPossessed() } +// Collapses 7 identical "GetComponents + for-loop + RegisterToSpec" +// category blocks into one call. Flex stays separate — it needs +// ParentSpecBody resolution. +template +static void RegisterAllOf(AActor* Owner, FMujocoSpecWrapper& Wrapper, + bool bSkipDefaults = true) +{ + if (!Owner) return; + TArray All; + Owner->GetComponents(All); + for (T* C : All) + { + if (!C) continue; + if (bSkipDefaults && C->bIsDefault) continue; + C->RegisterToSpec(Wrapper); + } +} + + void AMjArticulation::Setup(mjSpec* Spec, mjVFS* VFS) { m_spec = Spec; m_vfs = VFS; - + m_ChildSpec = mj_makeSpec(); m_ChildSpec->compiler.degree = false; @@ -410,60 +429,30 @@ void AMjArticulation::Setup(mjSpec* Spec, mjVFS* VFS) } // 4. Add Tendons (into child spec, after bodies so joint names are set) - TArray Tendons; - GetComponents(Tendons); - for (UMjTendon* Tendon : Tendons) - { - if (Tendon && !Tendon->bIsDefault) - Tendon->RegisterToSpec(*m_wrapper); - } + RegisterAllOf(this, *m_wrapper); - // 5. Add Sensors and Actuators (into child spec, after tendons strings might be referenced) - TArray Sensors; - GetComponents(Sensors); - for (UMjSensor* Sensor : Sensors) - { - if (Sensor && !Sensor->bIsDefault) - Sensor->RegisterToSpec(*m_wrapper); - } + // 5. Add Sensors / Actuators (after tendons so tendon names resolve). + RegisterAllOf(this, *m_wrapper); + RegisterAllOf(this, *m_wrapper); - TArray Actuators; - GetComponents(Actuators); - for (UMjActuator* Actuator : Actuators) + // 6. Contact pairs / excludes inherit from IMjSpecElement (not + // UMjComponent) so they have no bIsDefault field — register all. { - if (Actuator && !Actuator->bIsDefault) - Actuator->RegisterToSpec(*m_wrapper); + TArray Pairs; + GetComponents(Pairs); + for (UMjContactPair* Pair : Pairs) + if (Pair) Pair->RegisterToSpec(*m_wrapper); } - - TArray ContactPairs; - GetComponents(ContactPairs); - for (UMjContactPair* Pair : ContactPairs) { - Pair->RegisterToSpec(*m_wrapper); + TArray Excludes; + GetComponents(Excludes); + for (UMjContactExclude* Excl : Excludes) + if (Excl) Excl->RegisterToSpec(*m_wrapper); } - TArray ContactExcludes; - GetComponents(ContactExcludes); - for (UMjContactExclude* Exclude : ContactExcludes) - { - Exclude->RegisterToSpec(*m_wrapper); - } - - TArray Equalities; - GetComponents(Equalities); - for (UMjEquality* Equality : Equalities) - { - if (Equality && !Equality->bIsDefault) - Equality->RegisterToSpec(*m_wrapper); - } - - TArray Keyframes; - GetComponents(Keyframes); - for (UMjKeyframe* Keyframe : Keyframes) - { - if (Keyframe && !Keyframe->bIsDefault) - Keyframe->RegisterToSpec(*m_wrapper); - } + // 7. Equalities + Keyframes. + RegisterAllOf(this, *m_wrapper); + RegisterAllOf(this, *m_wrapper); mjsBody* parentWorld = mjs_findBody(Spec, "world"); mjsFrame* attachmentFrame = mjs_addFrame(parentWorld, 0); @@ -695,73 +684,16 @@ void AMjArticulation::ApplyControls() // Blueprint Runtime API — Discovery // ========================================================================= -TArray AMjArticulation::GetActuatorNames() const -{ - TArray Names; - for (auto& Elem : ActuatorIdMap) - { - if (Elem.Value) Names.Add(Elem.Value->GetMjName()); - } - return Names; -} - -TArray AMjArticulation::GetActuators() const -{ - TArray Components; - ActuatorIdMap.GenerateValueArray(Components); - return Components; -} - -TArray AMjArticulation::GetJointNames() const -{ - TArray Names; - for (auto& Elem : JointIdMap) - { - if (Elem.Value) Names.Add(Elem.Value->GetMjName()); - } - return Names; -} - -TArray AMjArticulation::GetJoints() const -{ - TArray Components; - JointIdMap.GenerateValueArray(Components); - return Components; -} - -TArray AMjArticulation::GetSensorNames() const -{ - TArray Names; - for (auto& Elem : SensorIdMap) - { - if (Elem.Value) Names.Add(Elem.Value->GetMjName()); - } - return Names; -} - -TArray AMjArticulation::GetSensors() const -{ - TArray Components; - SensorIdMap.GenerateValueArray(Components); - return Components; -} +// --- Templated map-lookup wrappers (v8: implementations in MjArticulation.h templates) --- -TArray AMjArticulation::GetBodyNames() const -{ - TArray Names; - for (auto& Elem : BodyIdMap) - { - if (Elem.Value) Names.Add(Elem.Value->GetMjName()); - } - return Names; -} - -TArray AMjArticulation::GetBodies() const -{ - TArray Components; - BodyIdMap.GenerateValueArray(Components); - return Components; -} +TArray AMjArticulation::GetActuatorNames() const { return GetComponentNamesFromMap(ActuatorIdMap); } +TArray AMjArticulation::GetActuators() const { return GetComponentsFromMap(ActuatorIdMap); } +TArray AMjArticulation::GetJointNames() const { return GetComponentNamesFromMap(JointIdMap); } +TArray AMjArticulation::GetJoints() const { return GetComponentsFromMap(JointIdMap); } +TArray AMjArticulation::GetSensorNames() const { return GetComponentNamesFromMap(SensorIdMap); } +TArray AMjArticulation::GetSensors() const { return GetComponentsFromMap(SensorIdMap); } +TArray AMjArticulation::GetBodyNames() const { return GetComponentNamesFromMap(BodyIdMap); } +TArray AMjArticulation::GetBodies() const { return GetComponentsFromMap(BodyIdMap); } void AMjArticulation::WakeAll() { @@ -786,60 +718,15 @@ TArray AMjArticulation::GetFrames() const return Components; } -TArray AMjArticulation::GetGeoms() const -{ - TArray Components; - GeomIdMap.GenerateValueArray(Components); - return Components; -} - +TArray AMjArticulation::GetGeoms() const { return GetComponentsFromMap(GeomIdMap); } +TArray AMjArticulation::GetTendons() const { return GetComponentsFromMap(TendonIdMap); } +TArray AMjArticulation::GetTendonNames() const { return GetComponentNamesFromMap(TendonIdMap); } -UMjActuator* AMjArticulation::GetActuator(const FString& Name) const -{ - if (const auto* Ptr = ActuatorComponentMap.Find(Name)) return *Ptr; - return nullptr; -} - -UMjJoint* AMjArticulation::GetJoint(const FString& Name) const -{ - if (const auto* Ptr = JointComponentMap.Find(Name)) return *Ptr; - return nullptr; -} - -UMjSensor* AMjArticulation::GetSensor(const FString& Name) const -{ - if (const auto* Ptr = SensorComponentMap.Find(Name)) return *Ptr; - return nullptr; -} - -UMjBody* AMjArticulation::GetBody(const FString& Name) const -{ - if (const auto* Ptr = BodyComponentMap.Find(Name)) return *Ptr; - return nullptr; -} - -TArray AMjArticulation::GetTendons() const -{ - TArray Components; - TendonIdMap.GenerateValueArray(Components); - return Components; -} - -TArray AMjArticulation::GetTendonNames() const -{ - TArray Names; - for (auto& Elem : TendonIdMap) - { - if (Elem.Value) Names.Add(Elem.Value->GetMjName()); - } - return Names; -} - -UMjTendon* AMjArticulation::GetTendon(const FString& Name) const -{ - if (const auto* Ptr = TendonComponentMap.Find(Name)) return *Ptr; - return nullptr; -} +UMjActuator* AMjArticulation::GetActuator(const FString& Name) const { return GetComponentByNameInMap(Name, ActuatorComponentMap); } +UMjJoint* AMjArticulation::GetJoint (const FString& Name) const { return GetComponentByNameInMap(Name, JointComponentMap); } +UMjSensor* AMjArticulation::GetSensor (const FString& Name) const { return GetComponentByNameInMap(Name, SensorComponentMap); } +UMjBody* AMjArticulation::GetBody (const FString& Name) const { return GetComponentByNameInMap(Name, BodyComponentMap); } +UMjTendon* AMjArticulation::GetTendon (const FString& Name) const { return GetComponentByNameInMap(Name, TendonComponentMap); } TArray AMjArticulation::GetEqualities() const { @@ -1013,28 +900,22 @@ void AMjArticulation::StopHoldKeyframe() UMjComponent* AMjArticulation::GetComponentByMjId(mjtObj type, int32 id) const { + // Single-lookup dispatch via GetComponentByIdInMap (v8). Each branch + // is a single Map.Find + nullptr-return, matching the standalone Get*ByMjId + // helpers below. switch (type) { - case mjOBJ_BODY: return GetBodyByMjId(id); - case mjOBJ_GEOM: return GetGeomByMjId(id); - case mjOBJ_JOINT: return JointIdMap.Contains(id) ? JointIdMap[id] : nullptr; - case mjOBJ_SENSOR: return SensorIdMap.Contains(id) ? SensorIdMap[id] : nullptr; - case mjOBJ_ACTUATOR: return ActuatorIdMap.Contains(id) ? ActuatorIdMap[id] : nullptr; + case mjOBJ_BODY: return GetComponentByIdInMap(id, BodyIdMap); + case mjOBJ_GEOM: return GetComponentByIdInMap(id, GeomIdMap); + case mjOBJ_JOINT: return GetComponentByIdInMap(id, JointIdMap); + case mjOBJ_SENSOR: return GetComponentByIdInMap(id, SensorIdMap); + case mjOBJ_ACTUATOR: return GetComponentByIdInMap(id, ActuatorIdMap); default: return nullptr; } } -UMjBody* AMjArticulation::GetBodyByMjId(int32 id) const -{ - if (const auto* Ptr = BodyIdMap.Find(id)) return *Ptr; - return nullptr; -} - -UMjGeom* AMjArticulation::GetGeomByMjId(int32 id) const -{ - if (const auto* Ptr = GeomIdMap.Find(id)) return *Ptr; - return nullptr; -} +UMjBody* AMjArticulation::GetBodyByMjId(int32 id) const { return GetComponentByIdInMap(id, BodyIdMap); } +UMjGeom* AMjArticulation::GetGeomByMjId(int32 id) const { return GetComponentByIdInMap(id, GeomIdMap); } bool AMjArticulation::SetActuatorControl(const FString& ActuatorName, float Value) { @@ -1140,14 +1021,14 @@ void AMjArticulation::DrawDebugJoints() { // Runtime mode: use compiled model data const JointView& JV = Joint->GetMj(); - MjType = JV.type; + MjType = JV.jnt_type; Anchor = Joint->GetWorldAnchor(); Axis = Joint->GetWorldAxis(); - if (JV.range) + if (JV.jnt_range) { - RangeMin = (float)JV.range[0]; - RangeMax = (float)JV.range[1]; + RangeMin = (float)JV.jnt_range[0]; + RangeMax = (float)JV.jnt_range[1]; bLimited = (RangeMin != 0.0f || RangeMax != 0.0f); } else @@ -1229,13 +1110,13 @@ void AMjArticulation::DrawDebugSites() { // Runtime: use compiled model data const SiteView& SV = Site->GetMj(); - if (!SV.xpos) continue; + if (!SV.site_xpos) continue; - Pos = MjUtils::MjToUEPosition(SV.xpos); - Radius = (SV.size) ? (float)SV.size[0] * 100.0f : 1.0f; // meters → cm - Color = (SV.rgba) ? FColor( - (uint8)(SV.rgba[0] * 255), (uint8)(SV.rgba[1] * 255), - (uint8)(SV.rgba[2] * 255), 200) : FColor(128, 128, 128, 200); + Pos = MjUtils::MjToUEPosition(SV.site_xpos); + Radius = (SV.site_size) ? (float)SV.site_size[0] * 100.0f : 1.0f; // meters → cm + Color = (SV.site_rgba) ? FColor( + (uint8)(SV.site_rgba[0] * 255), (uint8)(SV.site_rgba[1] * 255), + (uint8)(SV.site_rgba[2] * 255), 200) : FColor(128, 128, 128, 200); } else { diff --git a/Source/URLab/Private/MuJoCo/Core/MjDebugVisualizer.cpp b/Source/URLab/Private/MuJoCo/Core/MjDebugVisualizer.cpp index 5c32888..3fc5fef 100644 --- a/Source/URLab/Private/MuJoCo/Core/MjDebugVisualizer.cpp +++ b/Source/URLab/Private/MuJoCo/Core/MjDebugVisualizer.cpp @@ -495,7 +495,7 @@ void UMjDebugVisualizer::UpdateBodyOverlays() for (UMjGeom* Geom : Geoms) { if (!Geom || !Geom->IsBound()) continue; - const int32 BodyId = Geom->GetMj().body_id; + const int32 BodyId = Geom->GetMj().geom_bodyid; ApplyToMesh(Geom->GetVisualizerMesh(), BodyId, ArtHash); @@ -654,7 +654,7 @@ void UMjDebugVisualizer::BuildSegPool(EMjCameraMode mode) for (UMjGeom* Geom : Geoms) { if (!Geom || !Geom->IsBound()) continue; - const int32 BodyId = Geom->GetMj().body_id; + const int32 BodyId = Geom->GetMj().geom_bodyid; AddSibling(Geom->GetVisualizerMesh(), BodyId, ArtHash); diff --git a/Source/URLab/Private/MuJoCo/Core/MjSimOptions.cpp b/Source/URLab/Private/MuJoCo/Core/MjSimOptions.cpp deleted file mode 100644 index af9a63c..0000000 --- a/Source/URLab/Private/MuJoCo/Core/MjSimOptions.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are -// trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. -// -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), -// CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. -#include "MuJoCo/Core/MjSimOptions.h" -#include - -void FMuJoCoOptions::ApplyToSpec(mjSpec* Spec) const -{ - if (!Spec) return; - - if (bOverride_MemoryMB) - { - Spec->memory = static_cast(MemoryMB) * 1024 * 1024; - } - - Spec->option.timestep = Timestep; - - // Gravity: UE cm/s² → MuJoCo m/s², negate Y for handedness - Spec->option.gravity[0] = Gravity.X / 100.0; - Spec->option.gravity[1] = -Gravity.Y / 100.0; - Spec->option.gravity[2] = Gravity.Z / 100.0; - - Spec->option.wind[0] = Wind.X / 100.0; - Spec->option.wind[1] = -Wind.Y / 100.0; - Spec->option.wind[2] = Wind.Z / 100.0; - - Spec->option.magnetic[0] = Magnetic.X; - Spec->option.magnetic[1] = -Magnetic.Y; - Spec->option.magnetic[2] = Magnetic.Z; - - Spec->option.density = Density; - Spec->option.viscosity = Viscosity; - Spec->option.impratio = Impratio; - Spec->option.tolerance = Tolerance; - Spec->option.iterations = Iterations; - Spec->option.ls_iterations = LsIterations; - - if (bOverride_Integrator) Spec->option.integrator = (int)Integrator; - if (bOverride_Cone) Spec->option.cone = (int)Cone; - if (bOverride_Solver) Spec->option.solver = (int)Solver; - - if (bOverride_NoslipIterations) Spec->option.noslip_iterations = NoslipIterations; - if (bOverride_NoslipTolerance) Spec->option.noslip_tolerance = NoslipTolerance; - if (bOverride_CCD_Iterations) Spec->option.ccd_iterations = CCD_Iterations; - if (bOverride_CCD_Tolerance) Spec->option.ccd_tolerance = CCD_Tolerance; - - // MultiCCD - constexpr int MJ_ENBL_MULTICCD = 1 << 4; - if (bEnableMultiCCD) - Spec->option.enableflags |= MJ_ENBL_MULTICCD; - else - Spec->option.enableflags &= ~MJ_ENBL_MULTICCD; - - // Sleep - constexpr int MJ_ENBL_SLEEP = 1 << 5; - if (bEnableSleep) - { - Spec->option.enableflags |= MJ_ENBL_SLEEP; - Spec->option.sleep_tolerance = SleepTolerance; - } -} - -void FMuJoCoOptions::ApplyOverridesToModel(mjModel* Model) const -{ - if (!Model) return; - - if (bOverride_Timestep) Model->opt.timestep = Timestep; - - if (bOverride_Gravity) - { - Model->opt.gravity[0] = Gravity.X / 100.0; - Model->opt.gravity[1] = -Gravity.Y / 100.0; - Model->opt.gravity[2] = Gravity.Z / 100.0; - } - - if (bOverride_Wind) - { - Model->opt.wind[0] = Wind.X / 100.0; - Model->opt.wind[1] = -Wind.Y / 100.0; - Model->opt.wind[2] = Wind.Z / 100.0; - } - - if (bOverride_Magnetic) - { - Model->opt.magnetic[0] = Magnetic.X; - Model->opt.magnetic[1] = -Magnetic.Y; - Model->opt.magnetic[2] = Magnetic.Z; - } - - if (bOverride_Density) Model->opt.density = Density; - if (bOverride_Viscosity) Model->opt.viscosity = Viscosity; - if (bOverride_Impratio) Model->opt.impratio = Impratio; - if (bOverride_Tolerance) Model->opt.tolerance = Tolerance; - if (bOverride_Iterations) Model->opt.iterations = Iterations; - if (bOverride_LsIterations) Model->opt.ls_iterations = LsIterations; - - if (bOverride_Integrator) Model->opt.integrator = (int)Integrator; - if (bOverride_Cone) Model->opt.cone = (int)Cone; - if (bOverride_Solver) Model->opt.solver = (int)Solver; - - if (bOverride_NoslipIterations) Model->opt.noslip_iterations = NoslipIterations; - if (bOverride_NoslipTolerance) Model->opt.noslip_tolerance = NoslipTolerance; - if (bOverride_CCD_Iterations) Model->opt.ccd_iterations = CCD_Iterations; - if (bOverride_CCD_Tolerance) Model->opt.ccd_tolerance = CCD_Tolerance; - - // MultiCCD - constexpr int MJ_ENBL_MULTICCD = 1 << 4; - if (bEnableMultiCCD) - Model->opt.enableflags |= MJ_ENBL_MULTICCD; - else - Model->opt.enableflags &= ~MJ_ENBL_MULTICCD; - - // Sleep - constexpr int MJ_ENBL_SLEEP = 1 << 5; - if (bEnableSleep) - { - Model->opt.enableflags |= MJ_ENBL_SLEEP; - Model->opt.sleep_tolerance = SleepTolerance; - } - else - { - Model->opt.enableflags &= ~MJ_ENBL_SLEEP; - } -} diff --git a/Source/URLab/Private/MuJoCo/Core/Spec/MjSpecWrapper.cpp b/Source/URLab/Private/MuJoCo/Core/Spec/MjSpecWrapper.cpp index a9fbd4c..a1abd63 100644 --- a/Source/URLab/Private/MuJoCo/Core/Spec/MjSpecWrapper.cpp +++ b/Source/URLab/Private/MuJoCo/Core/Spec/MjSpecWrapper.cpp @@ -97,7 +97,7 @@ FString FMujocoSpecWrapper::AddMeshAsset(const FString& MeshName, const FString& mjsMesh* MeshAsset = mjs_addMesh(Spec, nullptr); mjs_setName(MeshAsset->element, TCHAR_TO_UTF8(*UniqueMeshName)); - mjs_setString(MeshAsset->file, TCHAR_TO_UTF8(*FilePath)); + MjSetStringRaw(MeshAsset->file, FilePath); MeshAsset->scale[0] = scale.X; MeshAsset->scale[1] = scale.Y; diff --git a/Source/URLab/Private/MuJoCo/Generated/MjOptionGenerated.cpp b/Source/URLab/Private/MuJoCo/Generated/MjOptionGenerated.cpp new file mode 100644 index 0000000..59c1c6b --- /dev/null +++ b/Source/URLab/Private/MuJoCo/Generated/MjOptionGenerated.cpp @@ -0,0 +1,79 @@ +// Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// --- LEGAL DISCLAIMER --- +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. +// +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. + +#include "MuJoCo/Generated/MjOptionGenerated.h" +#include + +void FMjOptionGenerated::ApplyToSpec(mjSpec* Spec) const +{ + if (!Spec) return; + if (bOverride_Timestep) { Spec->option.timestep = Timestep; } + if (bOverride_Impratio) { Spec->option.impratio = Impratio; } + if (bOverride_Tolerance) { Spec->option.tolerance = Tolerance; } + if (bOverride_LsTolerance) { Spec->option.ls_tolerance = LsTolerance; } + if (bOverride_NoslipTolerance) { Spec->option.noslip_tolerance = NoslipTolerance; } + if (bOverride_CCD_Tolerance) { Spec->option.ccd_tolerance = CCD_Tolerance; } + if (bOverride_Gravity) { Spec->option.gravity[0] = Gravity.X / 100.0; Spec->option.gravity[1] = -Gravity.Y / 100.0; Spec->option.gravity[2] = Gravity.Z / 100.0; } + if (bOverride_Wind) { Spec->option.wind[0] = Wind.X / 100.0; Spec->option.wind[1] = -Wind.Y / 100.0; Spec->option.wind[2] = Wind.Z / 100.0; } + if (bOverride_Magnetic) { Spec->option.magnetic[0] = Magnetic.X; Spec->option.magnetic[1] = -Magnetic.Y; Spec->option.magnetic[2] = Magnetic.Z; } + if (bOverride_Density) { Spec->option.density = Density; } + if (bOverride_Viscosity) { Spec->option.viscosity = Viscosity; } + if (bOverride_OMargin) { Spec->option.o_margin = OMargin; } + if (bOverride_Integrator) { Spec->option.integrator = static_cast(Integrator); } + if (bOverride_Cone) { Spec->option.cone = static_cast(Cone); } + if (bOverride_Jacobian) { Spec->option.jacobian = Jacobian; } + if (bOverride_Solver) { Spec->option.solver = static_cast(Solver); } + if (bOverride_Iterations) { Spec->option.iterations = Iterations; } + if (bOverride_LsIterations) { Spec->option.ls_iterations = LsIterations; } + if (bOverride_NoslipIterations) { Spec->option.noslip_iterations = NoslipIterations; } + if (bOverride_CCD_Iterations) { Spec->option.ccd_iterations = CCD_Iterations; } + ApplyMjOptionExtras(&Spec->option, *this, Spec); +} + +void FMjOptionGenerated::ApplyOverridesToModel(mjModel* Model) const +{ + if (!Model) return; + if (bOverride_Timestep) { Model->opt.timestep = Timestep; } + if (bOverride_Impratio) { Model->opt.impratio = Impratio; } + if (bOverride_Tolerance) { Model->opt.tolerance = Tolerance; } + if (bOverride_LsTolerance) { Model->opt.ls_tolerance = LsTolerance; } + if (bOverride_NoslipTolerance) { Model->opt.noslip_tolerance = NoslipTolerance; } + if (bOverride_CCD_Tolerance) { Model->opt.ccd_tolerance = CCD_Tolerance; } + if (bOverride_Gravity) { Model->opt.gravity[0] = Gravity.X / 100.0; Model->opt.gravity[1] = -Gravity.Y / 100.0; Model->opt.gravity[2] = Gravity.Z / 100.0; } + if (bOverride_Wind) { Model->opt.wind[0] = Wind.X / 100.0; Model->opt.wind[1] = -Wind.Y / 100.0; Model->opt.wind[2] = Wind.Z / 100.0; } + if (bOverride_Magnetic) { Model->opt.magnetic[0] = Magnetic.X; Model->opt.magnetic[1] = -Magnetic.Y; Model->opt.magnetic[2] = Magnetic.Z; } + if (bOverride_Density) { Model->opt.density = Density; } + if (bOverride_Viscosity) { Model->opt.viscosity = Viscosity; } + if (bOverride_OMargin) { Model->opt.o_margin = OMargin; } + if (bOverride_Integrator) { Model->opt.integrator = static_cast(Integrator); } + if (bOverride_Cone) { Model->opt.cone = static_cast(Cone); } + if (bOverride_Jacobian) { Model->opt.jacobian = Jacobian; } + if (bOverride_Solver) { Model->opt.solver = static_cast(Solver); } + if (bOverride_Iterations) { Model->opt.iterations = Iterations; } + if (bOverride_LsIterations) { Model->opt.ls_iterations = LsIterations; } + if (bOverride_NoslipIterations) { Model->opt.noslip_iterations = NoslipIterations; } + if (bOverride_CCD_Iterations) { Model->opt.ccd_iterations = CCD_Iterations; } + ApplyMjOptionExtras(&Model->opt, *this, nullptr, Model); +} diff --git a/Source/URLab/Private/MuJoCo/Generated/MjOptionGeneratedExtras.cpp b/Source/URLab/Private/MuJoCo/Generated/MjOptionGeneratedExtras.cpp new file mode 100644 index 0000000..79958ca --- /dev/null +++ b/Source/URLab/Private/MuJoCo/Generated/MjOptionGeneratedExtras.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2026 Jonathan Embley-Riches. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// URLab pseudo-field side of FMjOptionGenerated. The codegen emits the +// mjOption mirror struct + its ApplyToSpec / ApplyOverridesToModel +// bodies (in MjOptionGenerated.cpp) and ends each with a call to +// ApplyMjOptionExtras for the URLab-specific bits the spec/model layout +// doesn't carry (MemoryMB, MultiCCD bitflag, Sleep bitflag + tolerance). +// Edit this file directly — it is NOT codegen-managed. + +#include "MuJoCo/Generated/MjOptionGenerated.h" +#include + +// Bit positions in mjOption.enableflags. Match mjENBL_MULTICCD / mjENBL_SLEEP +// from mjmodel.h; hardcoded to avoid pulling mjtEnableBit into the header. +static constexpr int MJ_ENBL_MULTICCD = 1 << 4; +static constexpr int MJ_ENBL_SLEEP = 1 << 5; + +void ApplyMjOptionExtras(mjOption* Opt, const FMjOptionGenerated& Self, + mjSpec* Spec, mjModel* /*Model*/) +{ + if (!Opt) return; + + if (Spec && Self.bOverride_MemoryMB) + { + Spec->memory = static_cast(Self.MemoryMB) * 1024 * 1024; + } + + if (Self.bEnableMultiCCD) Opt->enableflags |= MJ_ENBL_MULTICCD; + else Opt->enableflags &= ~MJ_ENBL_MULTICCD; + + if (Self.bEnableSleep) + { + Opt->enableflags |= MJ_ENBL_SLEEP; + Opt->sleep_tolerance = Self.SleepTolerance; + } + else + { + Opt->enableflags &= ~MJ_ENBL_SLEEP; + } +} diff --git a/Source/URLab/Private/MuJoCo/Input/MjPerturbation.cpp b/Source/URLab/Private/MuJoCo/Input/MjPerturbation.cpp index 222371e..f2bf226 100644 --- a/Source/URLab/Private/MuJoCo/Input/MjPerturbation.cpp +++ b/Source/URLab/Private/MuJoCo/Input/MjPerturbation.cpp @@ -117,7 +117,7 @@ int32 UMjPerturbation::ResolveBodyIdFromActor(const AActor* Actor, const FVector if (!Actor) return -1; // Articulation path: find the nearest UMjGeom to the hit point (any geom - // on the actor belongs to a body via Geom->GetMj().body_id). + // on the actor belongs to a body via Geom->GetMj().geom_bodyid). TArray Geoms; const_cast(Actor)->GetComponents(Geoms); if (Geoms.Num() > 0) @@ -132,7 +132,7 @@ int32 UMjPerturbation::ResolveBodyIdFromActor(const AActor* Actor, const FVector } if (Best) { - return Best->GetMj().body_id; + return Best->GetMj().geom_bodyid; } } diff --git a/Source/URLab/Private/MuJoCo/Utils/MjOrientationUtils.cpp b/Source/URLab/Private/MuJoCo/Utils/MjOrientationUtils.cpp index 3e8d7b9..2c6878c 100644 --- a/Source/URLab/Private/MuJoCo/Utils/MjOrientationUtils.cpp +++ b/Source/URLab/Private/MuJoCo/Utils/MjOrientationUtils.cpp @@ -24,6 +24,7 @@ #include "XmlNode.h" #include "MuJoCo/Utils/MjXmlUtils.h" #include "Utils/URLabLogging.h" +#include "mujoco/mujoco.h" // ============================================================================ // Compiler Settings @@ -126,7 +127,7 @@ bool MjOrientationUtils::OrientationToMjQuat(const FXmlNode* Node, const FMjComp OutQuat[1] = (double)Parts[1]; OutQuat[2] = (double)Parts[2]; OutQuat[3] = (double)Parts[3]; - QuatNormalize(OutQuat); + mju_normalize4(OutQuat); return true; } } @@ -213,49 +214,19 @@ bool MjOrientationUtils::OrientationToMjQuat(const FXmlNode* Node, const FMjComp void MjOrientationUtils::AxisAngleToQuat(double x, double y, double z, double AngleRad, double OutQuat[4]) { - // Normalize axis - double Len = FMath::Sqrt(x * x + y * y + z * z); - if (Len < 1e-10) + double Axis[3] = { x, y, z }; + if (mju_normalize3(Axis) < 1e-10) { OutQuat[0] = 1.0; OutQuat[1] = 0.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; return; } - - double InvLen = 1.0 / Len; - double nx = x * InvLen; - double ny = y * InvLen; - double nz = z * InvLen; - - double HalfAngle = AngleRad * 0.5; - double s = FMath::Sin(HalfAngle); - double c = FMath::Cos(HalfAngle); - - OutQuat[0] = c; - OutQuat[1] = s * nx; - OutQuat[2] = s * ny; - OutQuat[3] = s * nz; - QuatNormalize(OutQuat); + mju_axisAngle2Quat(OutQuat, Axis, AngleRad); } // ============================================================================ // Euler → Quaternion // ============================================================================ -void MjOrientationUtils::ElementalRotQuat(int AxisIndex, double AngleRad, double OutQuat[4]) -{ - double HalfAngle = AngleRad * 0.5; - double s = FMath::Sin(HalfAngle); - double c = FMath::Cos(HalfAngle); - - OutQuat[0] = c; - OutQuat[1] = 0.0; - OutQuat[2] = 0.0; - OutQuat[3] = 0.0; - - // AxisIndex: 0=x, 1=y, 2=z - OutQuat[1 + AxisIndex] = s; -} - void MjOrientationUtils::EulerToQuat(double e1, double e2, double e3, const FString& EulerSeq, double OutQuat[4]) { if (EulerSeq.Len() != 3) @@ -265,62 +236,9 @@ void MjOrientationUtils::EulerToQuat(double e1, double e2, double e3, const FStr return; } - double Angles[3] = { e1, e2, e3 }; - int AxisIndices[3]; - bool bExtrinsic[3]; - - for (int i = 0; i < 3; ++i) - { - TCHAR Ch = EulerSeq[i]; - switch (Ch) - { - case 'x': AxisIndices[i] = 0; bExtrinsic[i] = false; break; - case 'y': AxisIndices[i] = 1; bExtrinsic[i] = false; break; - case 'z': AxisIndices[i] = 2; bExtrinsic[i] = false; break; - case 'X': AxisIndices[i] = 0; bExtrinsic[i] = true; break; - case 'Y': AxisIndices[i] = 1; bExtrinsic[i] = true; break; - case 'Z': AxisIndices[i] = 2; bExtrinsic[i] = true; break; - default: - UE_LOG(LogURLabImport, Warning, TEXT("[MjOrientationUtils] Invalid euler axis character '%c'"), Ch); - AxisIndices[i] = 0; bExtrinsic[i] = false; - break; - } - } - - // Build three elemental rotation quaternions - double Q1[4], Q2[4], Q3[4]; - ElementalRotQuat(AxisIndices[0], Angles[0], Q1); - ElementalRotQuat(AxisIndices[1], Angles[1], Q2); - ElementalRotQuat(AxisIndices[2], Angles[2], Q3); - - // Per-axis composition following MuJoCo convention (user_objects.cc): - // Lowercase (intrinsic): rotate in body-fixed frame → accumulate on the right: R = R_prev * Ri - // Uppercase (extrinsic): rotate in world-fixed frame → accumulate on the left: R = Ri * R_prev - // This handles pure intrinsic, pure extrinsic, and mixed sequences correctly. - - const double* Qi[3] = { Q1, Q2, Q3 }; - // Start with identity - double Result[4] = { 1.0, 0.0, 0.0, 0.0 }; - double Temp[4]; - - for (int i = 0; i < 3; ++i) - { - if (bExtrinsic[i]) - { - // Extrinsic: new = Qi * Result - QuatMul(Qi[i], Result, Temp); - } - else - { - // Intrinsic: new = Result * Qi - QuatMul(Result, Qi[i], Temp); - } - Result[0] = Temp[0]; Result[1] = Temp[1]; Result[2] = Temp[2]; Result[3] = Temp[3]; - } - - OutQuat[0] = Result[0]; OutQuat[1] = Result[1]; OutQuat[2] = Result[2]; OutQuat[3] = Result[3]; - - QuatNormalize(OutQuat); + double Euler[3] = { e1, e2, e3 }; + const auto SeqAnsi = StringCast(*EulerSeq); + mju_euler2Quat(OutQuat, Euler, SeqAnsi.Get()); } // ============================================================================ @@ -329,43 +247,37 @@ void MjOrientationUtils::EulerToQuat(double e1, double e2, double e3, const FStr void MjOrientationUtils::XYAxesToQuat(const double XYAxes[6], double OutQuat[4]) { - // X axis - double Xx = XYAxes[0], Xy = XYAxes[1], Xz = XYAxes[2]; - double XLen = FMath::Sqrt(Xx * Xx + Xy * Xy + Xz * Xz); - if (XLen < 1e-10) + double X[3] = { XYAxes[0], XYAxes[1], XYAxes[2] }; + if (mju_normalize3(X) < 1e-10) { OutQuat[0] = 1.0; OutQuat[1] = 0.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; return; } - Xx /= XLen; Xy /= XLen; Xz /= XLen; - - // Y axis (orthogonalize against X) - double Yx = XYAxes[3], Yy = XYAxes[4], Yz = XYAxes[5]; - double Dot = Xx * Yx + Xy * Yy + Xz * Yz; - Yx -= Dot * Xx; - Yy -= Dot * Xy; - Yz -= Dot * Xz; - double YLen = FMath::Sqrt(Yx * Yx + Yy * Yy + Yz * Yz); - if (YLen < 1e-10) + + double Y[3] = { XYAxes[3], XYAxes[4], XYAxes[5] }; + const double Dot = X[0]*Y[0] + X[1]*Y[1] + X[2]*Y[2]; + Y[0] -= Dot*X[0]; Y[1] -= Dot*X[1]; Y[2] -= Dot*X[2]; + if (mju_normalize3(Y) < 1e-10) { OutQuat[0] = 1.0; OutQuat[1] = 0.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; return; } - Yx /= YLen; Yy /= YLen; Yz /= YLen; - - // Z axis = X cross Y - double Zx = Xy * Yz - Xz * Yy; - double Zy = Xz * Yx - Xx * Yz; - double Zz = Xx * Yy - Xy * Yx; - - // Build rotation matrix (row-major): row 0 = X, row 1 = Y, row 2 = Z - double R[9] = { - Xx, Xy, Xz, - Yx, Yy, Yz, - Zx, Zy, Zz - }; - RotMatToQuat(R, OutQuat); + double Z[3]; + mju_cross(Z, X, Y); + if (mju_normalize3(Z) < 1e-10) + { + OutQuat[0] = 1.0; OutQuat[1] = 0.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; + return; + } + + // MuJoCo rotation matrix is row-major with COLUMNS = local axes (mjuu_frame2quat convention). + const double Mat[9] = { + X[0], Y[0], Z[0], + X[1], Y[1], Z[1], + X[2], Y[2], Z[2] + }; + mju_mat2Quat(OutQuat, Mat); } // ============================================================================ @@ -374,119 +286,27 @@ void MjOrientationUtils::XYAxesToQuat(const double XYAxes[6], double OutQuat[4]) void MjOrientationUtils::ZAxisToQuat(const double ZAxis[3], double OutQuat[4]) { - double Zx = ZAxis[0], Zy = ZAxis[1], Zz = ZAxis[2]; - double Len = FMath::Sqrt(Zx * Zx + Zy * Zy + Zz * Zz); - if (Len < 1e-10) + double Vec[3] = { ZAxis[0], ZAxis[1], ZAxis[2] }; + if (mju_normalize3(Vec) < 1e-10) { OutQuat[0] = 1.0; OutQuat[1] = 0.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; return; } - Zx /= Len; Zy /= Len; Zz /= Len; - - // Source direction: (0, 0, 1) - // target direction: (Zx, Zy, Zz) - // Rotation axis = cross(source, target), angle = acos(dot(source, target)) - - double DotVal = Zz; // dot((0,0,1), (Zx,Zy,Zz)) = Zz - if (DotVal > 0.9999999) + if (Vec[2] > 0.9999999) { - // Nearly identical — identity rotation OutQuat[0] = 1.0; OutQuat[1] = 0.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; return; } - - if (DotVal < -0.9999999) + if (Vec[2] < -0.9999999) { - // Nearly opposite — 180 degree rotation around any perpendicular axis - // Choose X axis as the rotation axis OutQuat[0] = 0.0; OutQuat[1] = 1.0; OutQuat[2] = 0.0; OutQuat[3] = 0.0; return; } - // cross((0,0,1), (Zx,Zy,Zz)) = (-Zy, Zx, 0) - double Ax = -Zy; - double Ay = Zx; - double Az = 0.0; - - double Angle = FMath::Acos(FMath::Clamp(DotVal, -1.0, 1.0)); - AxisAngleToQuat(Ax, Ay, Az, Angle, OutQuat); -} - -// ============================================================================ -// Quaternion Helpers -// ============================================================================ - -void MjOrientationUtils::QuatMul(const double A[4], const double B[4], double Result[4]) -{ - // Hamilton product: A * B with layout [w, x, y, z] - Result[0] = A[0]*B[0] - A[1]*B[1] - A[2]*B[2] - A[3]*B[3]; - Result[1] = A[0]*B[1] + A[1]*B[0] + A[2]*B[3] - A[3]*B[2]; - Result[2] = A[0]*B[2] - A[1]*B[3] + A[2]*B[0] + A[3]*B[1]; - Result[3] = A[0]*B[3] + A[1]*B[2] - A[2]*B[1] + A[3]*B[0]; -} - -void MjOrientationUtils::QuatNormalize(double Q[4]) -{ - double Len = FMath::Sqrt(Q[0]*Q[0] + Q[1]*Q[1] + Q[2]*Q[2] + Q[3]*Q[3]); - if (Len < 1e-10) - { - Q[0] = 1.0; Q[1] = 0.0; Q[2] = 0.0; Q[3] = 0.0; - return; - } - double InvLen = 1.0 / Len; - Q[0] *= InvLen; Q[1] *= InvLen; Q[2] *= InvLen; Q[3] *= InvLen; -} - -void MjOrientationUtils::RotMatToQuat(const double R[9], double OutQuat[4]) -{ - // Rotation matrix in row-major order: - // R[0] R[1] R[2] = row 0 (X axis) - // R[3] R[4] R[5] = row 1 (Y axis) - // R[6] R[7] R[8] = row 2 (Z axis) - // - // MuJoCo stores rotation matrices as 3x3 row-major where columns are frame axes. - // For xyaxes, we constructed R with rows = axes, so the rotation matrix for MuJoCo - // frame would have the columns as the axes. Since our R has rows as axes, - // the equivalent rotation matrix (transforms world to local) has columns as the axes. - // We need to convert from this rotation matrix to quaternion. - // - // Standard Shepperd method for robust matrix-to-quaternion conversion: - - double Trace = R[0] + R[4] + R[8]; - - if (Trace > 0.0) - { - double s = FMath::Sqrt(Trace + 1.0) * 2.0; // s = 4*w - OutQuat[0] = 0.25 * s; - OutQuat[1] = (R[5] - R[7]) / s; // (R[1][2] - R[2][1]) / s - OutQuat[2] = (R[6] - R[2]) / s; // (R[2][0] - R[0][2]) / s - OutQuat[3] = (R[1] - R[3]) / s; // (R[0][1] - R[1][0]) / s - } - else if (R[0] > R[4] && R[0] > R[8]) - { - double s = FMath::Sqrt(1.0 + R[0] - R[4] - R[8]) * 2.0; // s = 4*x - OutQuat[0] = (R[5] - R[7]) / s; - OutQuat[1] = 0.25 * s; - OutQuat[2] = (R[1] + R[3]) / s; - OutQuat[3] = (R[2] + R[6]) / s; - } - else if (R[4] > R[8]) - { - double s = FMath::Sqrt(1.0 + R[4] - R[0] - R[8]) * 2.0; // s = 4*y - OutQuat[0] = (R[6] - R[2]) / s; - OutQuat[1] = (R[1] + R[3]) / s; - OutQuat[2] = 0.25 * s; - OutQuat[3] = (R[5] + R[7]) / s; - } - else - { - double s = FMath::Sqrt(1.0 + R[8] - R[0] - R[4]) * 2.0; // s = 4*z - OutQuat[0] = (R[1] - R[3]) / s; - OutQuat[1] = (R[2] + R[6]) / s; - OutQuat[2] = (R[5] + R[7]) / s; - OutQuat[3] = 0.25 * s; - } - - QuatNormalize(OutQuat); + // axis = cross((0,0,1), Vec) = (-Vec[1], Vec[0], 0) + double Axis[3] = { -Vec[1], Vec[0], 0.0 }; + const double Angle = FMath::Acos(FMath::Clamp(Vec[2], -1.0, 1.0)); + mju_normalize3(Axis); + mju_axisAngle2Quat(OutQuat, Axis, Angle); } diff --git a/Source/URLab/Private/MuJoCo/Utils/MjUtils.cpp b/Source/URLab/Private/MuJoCo/Utils/MjUtils.cpp index 38b2061..5adb75c 100644 --- a/Source/URLab/Private/MuJoCo/Utils/MjUtils.cpp +++ b/Source/URLab/Private/MuJoCo/Utils/MjUtils.cpp @@ -142,9 +142,9 @@ void MjUtils::DrawDebugGeom(UWorld* World, const mjModel* m, const GeomView& geo { if (!World || !m) return; - mjtNum* pos = geom_view.xpos; - mjtNum* mat = geom_view.xmat; - mjtNum* size = geom_view.size; + mjtNum* pos = geom_view.geom_xpos; + mjtNum* mat = geom_view.geom_xmat; + mjtNum* size = geom_view.geom_size; // Draw if group 3 (collision convention) OR if both contype and conaffinity are non-zero (active collider) int group = geom_view._m->geom_group[geom_view.id]; @@ -163,7 +163,7 @@ void MjUtils::DrawDebugGeom(UWorld* World, const mjModel* m, const GeomView& geo mju_mat2Quat(_quat, mat); FQuat Rotation = MjToUERotation(_quat); - switch (geom_view.type) { + switch (geom_view.geom_type) { case mjGEOM_BOX: { FColor Color = DrawColor != FColor::Magenta ? DrawColor : FColor::Cyan; @@ -200,7 +200,7 @@ void MjUtils::DrawDebugGeom(UWorld* World, const mjModel* m, const GeomView& geo case mjGEOM_MESH: { FColor Color = DrawColor != FColor::Magenta ? DrawColor : FColor::Magenta; - int meshId = geom_view.dataid; + int meshId = geom_view.geom_dataid; if (meshId < 0) break; float* vertices = m->mesh_vert + m->mesh_vertadr[meshId] * 3; diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjActuator.h index a630ff5..8fbd64a 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjActuator.h @@ -29,6 +29,7 @@ #include "MuJoCo/Core/Spec/MjSpecElement.h" #include "MuJoCo/Components/MjComponent.h" #include "MuJoCo/Components/Defaults/MjDefault.h" +#include "MuJoCo/Generated/MjArticulationEnums.h" #include "MuJoCo/Utils/MjOrientationUtils.h" #include #include "MjActuator.generated.h" @@ -51,64 +52,8 @@ enum class EMjActuatorType : uint8 DcMotor }; -/** - * @enum EMjActuatorTrnType - * @brief Defines the type of transmission for the actuator. - */ -UENUM(BlueprintType) -enum class EMjActuatorTrnType : uint8 -{ - Joint, - JointInParent, - SliderCrank, - Tendon, - Site, - Body, - Undefined -}; - -/** - * @enum EMjGainType - * @brief MJCF actuator gain function. Mirrors MuJoCo's mjtGain. - * Most actuator subtypes hardcode this via mjs_setToX; useful on - * ```` to express the raw gainprm formula directly. - */ -UENUM(BlueprintType) -enum class EMjGainType : uint8 -{ - Fixed, - Affine, - Muscle, - User -}; - -/** - * @enum EMjBiasType - * @brief MJCF actuator bias function. Mirrors MuJoCo's mjtBias. - */ -UENUM(BlueprintType) -enum class EMjBiasType : uint8 -{ - None, - Affine, - Muscle, - User -}; - -/** - * @enum EMjDynType - * @brief MJCF actuator activation dynamics. Mirrors MuJoCo's mjtDyn. - */ -UENUM(BlueprintType) -enum class EMjDynType : uint8 -{ - None, - Integrator, - Filter, - FilterExact, - Muscle, - User -}; +// EMjActuatorTrnType, EMjGainType, EMjBiasType, EMjDynType moved to +// MuJoCo/Generated/MjArticulationEnums.h (codegen-owned). /** * @class UMjActuator @@ -124,137 +69,120 @@ class URLAB_API UMjActuator : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_group = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_group")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_group")) int32 group = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_nsample = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_nsample")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_nsample")) int32 nsample = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_interp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_interp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_interp")) int32 interp = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_delay = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_delay")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_delay")) float delay = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_ctrllimited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_ctrllimited")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_ctrllimited")) bool ctrllimited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_forcelimited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_forcelimited")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_forcelimited")) bool forcelimited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_actlimited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_actlimited")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_actlimited")) bool actlimited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_ctrlrange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_ctrlrange")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_ctrlrange")) TArray ctrlrange = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_forcerange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_forcerange")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_forcerange")) TArray forcerange = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_actrange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_actrange")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_actrange")) TArray actrange = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_lengthrange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_lengthrange")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_lengthrange")) TArray lengthrange = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_gear = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_gear")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_gear")) TArray gear = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_damping = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_damping")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_damping")) TArray damping = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_armature = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_armature")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_armature")) float armature = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_cranklength = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_cranklength")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_cranklength")) float cranklength = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_gainprm = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_gainprm")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_gainprm")) TArray gainprm = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_biasprm = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_biasprm")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_biasprm")) TArray biasprm = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_dynprm = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_dynprm")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_dynprm")) TArray dynprm = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_actdim = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_actdim")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_actdim")) int32 actdim = 0; - // --- CODEGEN_PROPERTIES_END --- - - UMjActuator(); - - /** @brief The type of actuator dynamics (e.g. Motor, Position). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator") - EMjActuatorType Type; - /** @brief The transmission type connecting the actuator to the system. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator") - EMjActuatorTrnType TransmissionType; - - // gaintype / biastype / dyntype: hand-declared because the UPROPERTY type - // is a URLab enum. Codegen owns the XML-string -> enum import and the - // enum -> mjtGain/mjtBias/mjtDyn export switch via xml_enum_attrs in - // codegen_rules.json. Useful primarily on actuators; for - // motor/position/velocity/etc. subtypes the mjs_setToX preset writes - // these fields and overrides the user's choice. UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_GainType = false; @@ -272,13 +200,32 @@ class URLAB_API UMjActuator : public UMjComponent UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_DynType")) EMjDynType DynType = EMjDynType::None; + // --- CODEGEN_PROPERTIES_END --- + + UMjActuator(); + + /** @brief The type of actuator dynamics (e.g. Motor, Position). */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator") + EMjActuatorType Type; + + /** @brief The transmission type connecting the actuator to the system. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator") + EMjActuatorTrnType TransmissionType; + + // gaintype / biastype / dyntype UPROPERTYs are codegen-emitted inside + // CODEGEN_PROPERTIES via xml_enum_attrs.emit_property_decl. Useful + // primarily on actuators; for motor/position/velocity/etc. + // subtypes the mjs_setToX preset writes these fields and overrides + // the user's choice. /** @brief Optional MuJoCo class name to inherit defaults from (string fallback). */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(GetOptions="GetDefaultClassOptions")) FString MjClassName; - /** @brief Reference to a UMjDefault component for default class inheritance. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator") + /** @brief Reference to a UMjDefault component for default class inheritance. Hidden from the + * Details panel — synced from MjClassName via the editor dropdown. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", + meta=(EditCondition="false", EditConditionHides)) UMjDefault* DefaultClass = nullptr; virtual FString GetMjClassName() const override diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjAdhesionActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjAdhesionActuator.h index eddad98..aebb876 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjAdhesionActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjAdhesionActuator.h @@ -36,10 +36,10 @@ class URLAB_API UMjAdhesionActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_gain = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_gain")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_gain")) float gain = 0.0f; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjCylinderActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjCylinderActuator.h index d9b20c9..263bb3b 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjCylinderActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjCylinderActuator.h @@ -36,28 +36,28 @@ class URLAB_API UMjCylinderActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_timeconst = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_timeconst")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_timeconst")) TArray timeconst = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_area = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_area")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_area")) float area = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_diameter = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_diameter")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_diameter")) float diameter = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_bias = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_bias")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_bias")) float bias = 0.0f; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjDamperActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjDamperActuator.h index eab9d3e..3a94e06 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjDamperActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjDamperActuator.h @@ -36,10 +36,10 @@ class URLAB_API UMjDamperActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_kv = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_kv")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_kv")) float kv = 0.0f; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjDcMotorActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjDcMotorActuator.h index 03255e3..eafe9e5 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjDcMotorActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjDcMotorActuator.h @@ -57,58 +57,58 @@ class URLAB_API UMjDcMotorActuator : public UMjActuator public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_motorconst = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_motorconst")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_motorconst")) TArray motorconst = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_resistance = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_resistance")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_resistance")) float resistance = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_nominal = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_nominal")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_nominal")) TArray nominal = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_saturation = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_saturation")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_saturation")) TArray saturation = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_inductance = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_inductance")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_inductance")) TArray inductance = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_cogging = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_cogging")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_cogging")) TArray cogging = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_controller = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_controller")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_controller")) TArray controller = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_thermal = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_thermal")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_thermal")) TArray thermal = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_lugre = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_lugre")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_lugre")) TArray lugre = {}; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjGeneralActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjGeneralActuator.h index 2ec662d..0d83b74 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjGeneralActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjGeneralActuator.h @@ -36,10 +36,10 @@ class URLAB_API UMjGeneralActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_actearly = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_actearly")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_actearly")) bool actearly = false; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjIntVelocityActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjIntVelocityActuator.h index 404890c..038ebd9 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjIntVelocityActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjIntVelocityActuator.h @@ -36,28 +36,28 @@ class URLAB_API UMjIntVelocityActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_inheritrange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_inheritrange")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_inheritrange")) float inheritrange = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_kp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_kp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_kp")) float kp = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_kv = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_kv")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_kv")) float kv = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_dampratio = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_dampratio")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_dampratio")) float dampratio = 0.0f; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjMotorActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjMotorActuator.h index 2fb077a..6a15df5 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjMotorActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjMotorActuator.h @@ -36,7 +36,6 @@ class URLAB_API UMjMotorActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjMotorActuator(); diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjMuscleActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjMuscleActuator.h index c140a8f..5bbd3e2 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjMuscleActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjMuscleActuator.h @@ -36,64 +36,64 @@ class URLAB_API UMjMuscleActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_timeconst = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_timeconst")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_timeconst")) TArray timeconst = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_tausmooth = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_tausmooth")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_tausmooth")) float tausmooth = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_range = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_range")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_range")) TArray range = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_force = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_force")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_force")) float force = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_scale = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_scale")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_scale")) TArray scale = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_lmin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_lmin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_lmin")) float lmin = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_lmax = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_lmax")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_lmax")) float lmax = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_vmax = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_vmax")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_vmax")) float vmax = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_fpmax = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_fpmax")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_fpmax")) float fpmax = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_fvmax = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_fvmax")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_fvmax")) float fvmax = 0.0f; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjPositionActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjPositionActuator.h index 837bad4..373d052 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjPositionActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjPositionActuator.h @@ -36,34 +36,34 @@ class URLAB_API UMjPositionActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_inheritrange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_inheritrange")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_inheritrange")) float inheritrange = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_kp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_kp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_kp")) float kp = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_kv = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_kv")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_kv")) float kv = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_dampratio = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_dampratio")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_dampratio")) float dampratio = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_timeconst = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_timeconst")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_timeconst")) TArray timeconst = {}; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Actuators/MjVelocityActuator.h b/Source/URLab/Public/MuJoCo/Components/Actuators/MjVelocityActuator.h index 78799f9..1d535b1 100644 --- a/Source/URLab/Public/MuJoCo/Components/Actuators/MjVelocityActuator.h +++ b/Source/URLab/Public/MuJoCo/Components/Actuators/MjVelocityActuator.h @@ -36,10 +36,10 @@ class URLAB_API UMjVelocityActuator : public UMjActuator GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjActuator", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Actuator", meta=(InlineEditConditionToggle)) bool bOverride_kv = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjActuator", meta=(EditCondition="bOverride_kv")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Actuator", meta=(EditCondition="bOverride_kv")) float kv = 0.0f; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Bodies/MjBody.h b/Source/URLab/Public/MuJoCo/Components/Bodies/MjBody.h index e8ad076..b1f1c7b 100644 --- a/Source/URLab/Public/MuJoCo/Components/Bodies/MjBody.h +++ b/Source/URLab/Public/MuJoCo/Components/Bodies/MjBody.h @@ -34,13 +34,20 @@ /** * @enum EMjBodySleepPolicy - * @brief Per-body sleep policy, matching MuJoCo's mjtSleepPolicy (user-settable subset). + * @brief Per-body sleep policy, matching MuJoCo's mjtSleepPolicy. + * + * The canonical way to opt out of per-body override is the + * bOverride_SleepPolicy toggle on UMjBody (toggle off => no per-body sleep + * value is written; mjsBody.sleep keeps the compiled default). The Auto + * entry exists because UHT requires UENUMs to have a 0-valued entry; it + * maps to mjSLEEP_AUTO so writing it explicitly is equivalent to not + * overriding at all. */ UENUM(BlueprintType) enum class EMjBodySleepPolicy : uint8 { - /** Let the compiler/global policy decide (mjSLEEP_AUTO). */ - Default = 0 UMETA(DisplayName="Default (Auto)"), + /** Use the global option (mjSLEEP_AUTO). Equivalent to leaving the override toggle off. */ + Auto = 0 UMETA(DisplayName="Auto (use global)"), /** This body's tree is never allowed to sleep (mjSLEEP_NEVER). */ Never = 3 UMETA(DisplayName="Never"), /** This body's tree is allowed to sleep (mjSLEEP_ALLOWED). */ @@ -56,34 +63,34 @@ class URLAB_API UMjBody : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjBody|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Body|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjBody|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Body|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjBody|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Body|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjBody|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Body|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjBody", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Body", meta=(InlineEditConditionToggle)) bool bOverride_childclass = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjBody", meta=(EditCondition="bOverride_childclass", GetOptions="GetChildClassOptions")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Body", meta=(EditCondition="bOverride_childclass", GetOptions="GetChildClassOptions")) FString childclass = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjBody", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Body", meta=(InlineEditConditionToggle)) bool bOverride_mocap = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjBody", meta=(EditCondition="bOverride_mocap", DisplayName="Driven By Unreal")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Body", meta=(EditCondition="bOverride_mocap", DisplayName="Driven By Unreal")) bool mocap = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjBody", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Body", meta=(InlineEditConditionToggle)) bool bOverride_gravcomp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjBody", meta=(EditCondition="bOverride_gravcomp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Body", meta=(EditCondition="bOverride_gravcomp")) float gravcomp = 0.0f; // --- CODEGEN_PROPERTIES_END --- @@ -97,10 +104,15 @@ class URLAB_API UMjBody : public UMjComponent TArray GetChildClassOptions() const; #endif - /** @brief Per-body sleep policy (MuJoCo 3.4+). Default lets the global option decide. */ + UPROPERTY(EditAnywhere, Category = "MuJoCo|Body|sleep", meta=(InlineEditConditionToggle)) + bool bOverride_SleepPolicy = false; + + /** @brief Per-body sleep policy (MuJoCo 3.4+). When the override toggle is off, + * the global option decides; when on, this value is written to mjsBody.sleep. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Body|sleep", - meta=(ToolTip="sleep policy for this body's kinematic tree. Only has effect when sleep is enabled in AMjManager Options.")) - EMjBodySleepPolicy SleepPolicy = EMjBodySleepPolicy::Default; + meta=(EditCondition="bOverride_SleepPolicy", + ToolTip="sleep policy for this body's kinematic tree. Only has effect when sleep is enabled in AMjManager Options.")) + EMjBodySleepPolicy SleepPolicy = EMjBodySleepPolicy::Never; /** * @brief Registers this body to the MuJoCo spec. diff --git a/Source/URLab/Public/MuJoCo/Components/Bodies/MjFrame.h b/Source/URLab/Public/MuJoCo/Components/Bodies/MjFrame.h index cdc2fbf..5d9eee8 100644 --- a/Source/URLab/Public/MuJoCo/Components/Bodies/MjFrame.h +++ b/Source/URLab/Public/MuJoCo/Components/Bodies/MjFrame.h @@ -45,22 +45,22 @@ class URLAB_API UMjFrame : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFrame|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Frame|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFrame|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Frame|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFrame|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Frame|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFrame|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Frame|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFrame", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Frame", meta=(InlineEditConditionToggle)) bool bOverride_childclass = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFrame", meta=(EditCondition="bOverride_childclass")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Frame", meta=(EditCondition="bOverride_childclass")) FString childclass = TEXT(""); // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Constraints/MjEquality.h b/Source/URLab/Public/MuJoCo/Components/Constraints/MjEquality.h index ef60903..56abc66 100644 --- a/Source/URLab/Public/MuJoCo/Components/Constraints/MjEquality.h +++ b/Source/URLab/Public/MuJoCo/Components/Constraints/MjEquality.h @@ -58,58 +58,58 @@ class URLAB_API UMjEquality : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_relpose = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_relpose")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_relpose")) TArray relpose = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_anchor = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_anchor")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_anchor", MjUnit="cm")) TArray anchor = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_site1 = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_site1")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_site1")) FString site1 = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_site2 = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_site2")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_site2")) FString site2 = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_active = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_active")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_active")) float active = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_solref = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_solref")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_solref")) TArray solref = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_solimp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_solimp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_solimp")) TArray solimp = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_torquescale = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_torquescale")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_torquescale")) float torquescale = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjEquality", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Equality", meta=(InlineEditConditionToggle)) bool bOverride_polycoef = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjEquality", meta=(EditCondition="bOverride_polycoef")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Equality", meta=(EditCondition="bOverride_polycoef")) TArray polycoef = {}; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Defaults/MjDefault.h b/Source/URLab/Public/MuJoCo/Components/Defaults/MjDefault.h index 0956192..3bab9ed 100644 --- a/Source/URLab/Public/MuJoCo/Components/Defaults/MjDefault.h +++ b/Source/URLab/Public/MuJoCo/Components/Defaults/MjDefault.h @@ -55,12 +55,16 @@ class URLAB_API UMjDefault : public UMjComponent /** @brief Default constructor. */ UMjDefault(); - /** @brief Name of the default class. If empty, these defaults apply to the global scope. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Default") + /** @brief Name of the default class. If empty, these defaults apply to the global scope. + * Hidden from the Details panel — synced from the SCS hierarchy. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Default", + meta=(EditCondition="false", EditConditionHides)) FString ClassName; - /** @brief Name of the parent default class for inheritance. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Default") + /** @brief Name of the parent default class for inheritance. Hidden from the Details panel — + * synced from the SCS hierarchy. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Default", + meta=(EditCondition="false", EditConditionHides)) FString ParentClassName; /** diff --git a/Source/URLab/Public/MuJoCo/Components/Deformable/MjFlexcomp.h b/Source/URLab/Public/MuJoCo/Components/Deformable/MjFlexcomp.h index 7d60c16..157c55e 100644 --- a/Source/URLab/Public/MuJoCo/Components/Deformable/MjFlexcomp.h +++ b/Source/URLab/Public/MuJoCo/Components/Deformable/MjFlexcomp.h @@ -24,6 +24,7 @@ #include "CoreMinimal.h" #include "MuJoCo/Components/MjComponent.h" +#include "MuJoCo/Generated/MjArticulationEnums.h" #include #include #include "MuJoCo/Utils/MjOrientationUtils.h" @@ -46,15 +47,7 @@ enum class EMjFlexcompType : uint8 Direct UMETA(DisplayName = "Direct (manual point + element)"), }; -UENUM(BlueprintType) -enum class EMjFlexcompDof : uint8 -{ - Full UMETA(DisplayName = "Full"), - Radial UMETA(DisplayName = "Radial"), - Trilinear UMETA(DisplayName = "Trilinear"), - Quadratic UMETA(DisplayName = "Quadratic"), - TwoD UMETA(DisplayName = "2D"), -}; +// EMjFlexcompDof moved to MuJoCo/Generated/MjArticulationEnums.h. /** * @class UMjFlexcomp @@ -71,124 +64,124 @@ class URLAB_API UMjFlexcomp : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_group = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_group")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_group")) int32 group = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_dim = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_dim")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_dim")) int32 dim = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_count = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_count")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_count")) TArray count = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_cellcount = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_cellcount")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_cellcount")) TArray cellcount = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_spacing = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_spacing")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_spacing", MjUnit="m")) TArray spacing = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_radius = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_radius")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_radius", Units="m")) float radius = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_rigid = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_rigid")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_rigid")) bool rigid = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_mass = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_mass")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_mass")) float mass = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_inertiabox = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_inertiabox")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_inertiabox")) float inertiabox = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_scale = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_scale")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_scale")) TArray scale = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_file = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_file")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_file")) FString file = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_point = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_point")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_point")) TArray point = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_element = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_element")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_element")) TArray element = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_texcoord = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_texcoord")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_texcoord")) TArray texcoord = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_material = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_material")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_material")) FString material = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_rgba = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_rgba")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_rgba")) FLinearColor rgba = FLinearColor::White; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_flatskin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_flatskin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_flatskin")) bool flatskin = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjFlexcomp", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Flexcomp", meta=(InlineEditConditionToggle)) bool bOverride_origin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjFlexcomp", meta=(EditCondition="bOverride_origin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Flexcomp", meta=(EditCondition="bOverride_origin")) TArray origin = {}; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/MjGeom.h b/Source/URLab/Public/MuJoCo/Components/Geometry/MjGeom.h index 58c24f0..8ebb79d 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/MjGeom.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/MjGeom.h @@ -27,12 +27,10 @@ #include "mujoco/mujoco.h" #include "MuJoCo/Utils/MjBind.h" #include "MuJoCo/Components/MjComponent.h" +#include "MuJoCo/Generated/MjArticulationEnums.h" #include "MuJoCo/Utils/MjOrientationUtils.h" #include "MjGeom.generated.h" - - - /** * @enum EMjGeomType * @brief Defines the geometric primitive type for the MuJoCo geom. @@ -51,35 +49,7 @@ enum class EMjGeomType : uint8 SDF UMETA(DisplayName = "SDF") }; -/** - * @enum EMjGeomInertia - * @brief MJCF ````. Mirrors MuJoCo's mjtGeomInertia. - * - * - Volume: inertia computed from solid volume (MuJoCo default). - * - Shell: inertia computed from a thin shell (mass distributed on surface). - */ -UENUM(BlueprintType) -enum class EMjGeomInertia : uint8 -{ - Volume UMETA(DisplayName = "Volume"), - Shell UMETA(DisplayName = "Shell"), -}; - -/** - * @enum EMjFluidShape - * @brief MJCF ````. Selects the ellipsoid-fluid - * interaction model in MuJoCo. Stored as 0.0/1.0 in - * mjsGeom.fluid_ellipsoid. - * - * - None: no ellipsoid fluid model (MuJoCo default). - * - Ellipsoid: enable the ellipsoid-fluid interaction model. - */ -UENUM(BlueprintType) -enum class EMjFluidShape : uint8 -{ - None UMETA(DisplayName = "None"), - Ellipsoid UMETA(DisplayName = "Ellipsoid"), -}; +// EMjGeomInertia, EMjFluidShape moved to MuJoCo/Generated/MjArticulationEnums.h. /** * @class UMjGeom @@ -97,136 +67,136 @@ class URLAB_API UMjGeom : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_contype = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_contype")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_contype")) int32 contype = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_conaffinity = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_conaffinity")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_conaffinity")) int32 conaffinity = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_condim = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_condim")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_condim")) int32 condim = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_group = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_group")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_group")) int32 group = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_priority = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_priority")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_priority")) int32 priority = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_size = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_size")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="false", EditConditionHides)) TArray size = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_material = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_material")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_material")) FString material = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_friction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_friction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_friction")) TArray friction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_mass = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_mass")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_mass")) float mass = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_density = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_density")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_density")) float density = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_solmix = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_solmix")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_solmix")) float solmix = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_solref = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_solref")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_solref")) TArray solref = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_solimp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_solimp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_solimp")) TArray solimp = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_margin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_margin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_margin", Units="m")) float margin = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_gap = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_gap")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_gap", Units="m")) float gap = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_hfield = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_hfield")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_hfield")) FString hfield = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_mesh = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_mesh")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_mesh")) FString mesh = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_fitscale = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_fitscale")) - bool fitscale = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_fitscale")) + double fitscale = 0.0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_rgba = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_rgba")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_rgba")) FLinearColor rgba = FLinearColor::White; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjGeom", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Geom", meta=(InlineEditConditionToggle)) bool bOverride_fluidcoef = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjGeom", meta=(EditCondition="bOverride_fluidcoef")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", meta=(EditCondition="bOverride_fluidcoef")) TArray fluidcoef = {}; // --- CODEGEN_PROPERTIES_END --- @@ -418,9 +388,11 @@ class URLAB_API UMjGeom : public UMjComponent meta=(EditCondition="Type != EMjGeomType::Mesh", EditConditionHides)) TObjectPtr OverrideMaterial; - /** @brief Reference to a UMjDefault component for default class inheritance. Set via detail customization dropdown. */ - UPROPERTY(BlueprintReadWrite, Category = "MuJoCo|Geom") - UMjDefault* DefaultClass; + /** @brief Reference to a UMjDefault component for default class inheritance. Hidden from the + * Details panel — synced from MjClassName via the editor dropdown. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Geom", + meta=(EditCondition="false", EditConditionHides)) + UMjDefault* DefaultClass = nullptr; /** * @brief Registers this geom to the MuJoCo spec. diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/MjSite.h b/Source/URLab/Public/MuJoCo/Components/Geometry/MjSite.h index 1a1b1e5..3f4a9f4 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/MjSite.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/MjSite.h @@ -32,7 +32,10 @@ /** * @enum EMjSiteType - * @brief Defines the geometric shape of a MuJoCo site. + * @brief Defines the geometric shape of a MuJoCo site. Mirrors the + * geom-subset MuJoCo permits on . Plane and SDF stay omitted + * (infinite extent / heavy data, not what a site spawn surface + * wants). */ UENUM(BlueprintType) enum class EMjSiteType : uint8 @@ -42,6 +45,8 @@ enum class EMjSiteType : uint8 Ellipsoid UMETA(DisplayName = "Ellipsoid"), Cylinder UMETA(DisplayName = "Cylinder"), Box UMETA(DisplayName = "Box"), + Mesh UMETA(DisplayName = "Mesh"), + Hfield UMETA(DisplayName = "Hfield"), }; /** @@ -61,40 +66,40 @@ class URLAB_API UMjSite : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSite|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Site|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSite|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSite|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Site|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSite|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSite", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Site", meta=(InlineEditConditionToggle)) bool bOverride_group = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSite", meta=(EditCondition="bOverride_group")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site", meta=(EditCondition="bOverride_group")) int32 group = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSite", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Site", meta=(InlineEditConditionToggle)) bool bOverride_material = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSite", meta=(EditCondition="bOverride_material")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site", meta=(EditCondition="bOverride_material")) FString material = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSite", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Site", meta=(InlineEditConditionToggle)) bool bOverride_size = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSite", meta=(EditCondition="bOverride_size")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site", meta=(EditCondition="false", EditConditionHides)) TArray size = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSite", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Site", meta=(InlineEditConditionToggle)) bool bOverride_rgba = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSite", meta=(EditCondition="bOverride_rgba")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site", meta=(EditCondition="bOverride_rgba")) FLinearColor rgba = FLinearColor::White; // --- CODEGEN_PROPERTIES_END --- @@ -145,8 +150,10 @@ class URLAB_API UMjSite : public UMjComponent TArray GetDefaultClassOptions() const; #endif - /** @brief Reference to a UMjDefault component for default class inheritance. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site") + /** @brief Reference to a UMjDefault component for default class inheritance. Hidden from the + * Details panel — synced from MjClassName via the editor dropdown. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Site", + meta=(EditCondition="false", EditConditionHides)) UMjDefault* DefaultClass = nullptr; virtual FString GetMjClassName() const override diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjBox.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjBox.h index 0c5f041..06e9790 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjBox.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjBox.h @@ -37,13 +37,15 @@ class URLAB_API UMjBox : public UMjGeom public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjBox(); virtual void OnRegister() override; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive") + /** @brief Half-extents along local X/Y/Z in MJ metres. Authored via + * the UE Transform's Scale handle; hidden from the Details panel. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive", + meta=(EditCondition="false", EditConditionHides)) FVector Extents = FVector(0.0f); /** @brief Internal-only visual mesh for the editor. */ diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCapsule.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCapsule.h index fb50bc7..677121c 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCapsule.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCapsule.h @@ -44,20 +44,22 @@ class URLAB_API UMjCapsule : public UMjGeom public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjCapsule(); virtual void OnRegister() override; - /** @brief Capsule radius. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive") + /** @brief Capsule radius in MJ metres. Authored via the UE Transform's + * Scale handle; hidden from the Details panel. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive", + meta=(EditCondition="false", EditConditionHides)) float Radius = 0.0f; - /** @brief Capsule half-length measured along the component's local Z - * axis. Total axial length from tip-to-tip is `2 * (Radius + HalfLength)`; - * the shaft length (between the cap centres) is `2 * HalfLength`. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive") + /** @brief Capsule half-length along the component's local Z axis. + * Shaft length = ``2 * HalfLength``; tip-to-tip = ``2 * (Radius + HalfLength)``. + * Authored via the Scale handle; hidden from the Details panel. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive", + meta=(EditCondition="false", EditConditionHides)) float HalfLength = 0.0f; // UPROPERTY-decorated so Unreal's GC tracks these sub-component pointers. diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCylinder.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCylinder.h index 3158aff..3b96fc6 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCylinder.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjCylinder.h @@ -37,17 +37,19 @@ class URLAB_API UMjCylinder : public UMjGeom public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjCylinder(); virtual void OnRegister() override; - /** @brief Radius of the cylinder. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive") + /** @brief Cylinder radius in MJ metres. Hidden — authored via Scale handle. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive", + meta=(EditCondition="false", EditConditionHides)) float Radius = 0.0f; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive") + /** @brief Cylinder half-length in MJ metres. Hidden — authored via Scale handle. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive", + meta=(EditCondition="false", EditConditionHides)) float HalfLength = 0.0f; /** @brief Internal-only visual mesh for the editor. */ diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.h index 4bd629c..1b3be16 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjEllipsoid.h @@ -44,7 +44,7 @@ class URLAB_API UMjEllipsoid : public UMjGeom UMjEllipsoid(); // --- CODEGEN_PROPERTIES_START --- - + // (no type-specific schema attrs) // --- CODEGEN_PROPERTIES_END --- virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjPlane.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjPlane.h index 3a43e87..0d1a3ce 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjPlane.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjPlane.h @@ -44,7 +44,7 @@ class URLAB_API UMjPlane : public UMjGeom UMjPlane(); // --- CODEGEN_PROPERTIES_START --- - + // (no type-specific schema attrs) // --- CODEGEN_PROPERTIES_END --- virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSdf.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSdf.h index be1a853..9d37141 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSdf.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSdf.h @@ -44,7 +44,7 @@ class URLAB_API UMjSdf : public UMjGeom UMjSdf(); // --- CODEGEN_PROPERTIES_START --- - + // (no type-specific schema attrs) // --- CODEGEN_PROPERTIES_END --- virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; diff --git a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSphere.h b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSphere.h index 521896d..b979072 100644 --- a/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSphere.h +++ b/Source/URLab/Public/MuJoCo/Components/Geometry/Primitives/MjSphere.h @@ -37,13 +37,15 @@ class URLAB_API UMjSphere : public UMjGeom public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjSphere(); virtual void OnRegister() override; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive") + /** @brief Sphere radius in MJ metres. Authored via the UE Transform's + * Scale handle; hidden from the Details panel widget. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Primitive", + meta=(EditCondition="false", EditConditionHides)) float Radius = 0.0f; /** @brief Internal-only visual mesh for the editor. */ diff --git a/Source/URLab/Public/MuJoCo/Components/Joints/MjBallJoint.h b/Source/URLab/Public/MuJoCo/Components/Joints/MjBallJoint.h index 58550ed..a22c5f1 100644 --- a/Source/URLab/Public/MuJoCo/Components/Joints/MjBallJoint.h +++ b/Source/URLab/Public/MuJoCo/Components/Joints/MjBallJoint.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjBallJoint - * @brief Specific Ball Joint component. + * @brief Autogenerated component representing the MuJoCo 'ball' element. + * + * Subclass of UMjJoint. Sets Type = Ball in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjBallJoint : public UMjJoint { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjBallJoint(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsJoint* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Joints/MjFreeJoint.h b/Source/URLab/Public/MuJoCo/Components/Joints/MjFreeJoint.h index 7affd36..7627611 100644 --- a/Source/URLab/Public/MuJoCo/Components/Joints/MjFreeJoint.h +++ b/Source/URLab/Public/MuJoCo/Components/Joints/MjFreeJoint.h @@ -36,7 +36,6 @@ class URLAB_API UMjFreeJoint : public UMjJoint GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjFreeJoint(); diff --git a/Source/URLab/Public/MuJoCo/Components/Joints/MjHingeJoint.h b/Source/URLab/Public/MuJoCo/Components/Joints/MjHingeJoint.h index 05a8c55..7639668 100644 --- a/Source/URLab/Public/MuJoCo/Components/Joints/MjHingeJoint.h +++ b/Source/URLab/Public/MuJoCo/Components/Joints/MjHingeJoint.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjHingeJoint - * @brief Specific Hinge Joint component. + * @brief Autogenerated component representing the MuJoCo 'hinge' element. + * + * Subclass of UMjJoint. Sets Type = Hinge in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjHingeJoint : public UMjJoint { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjHingeJoint(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsJoint* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Joints/MjJoint.h b/Source/URLab/Public/MuJoCo/Components/Joints/MjJoint.h index f479928..2c7da8b 100644 --- a/Source/URLab/Public/MuJoCo/Components/Joints/MjJoint.h +++ b/Source/URLab/Public/MuJoCo/Components/Joints/MjJoint.h @@ -59,112 +59,124 @@ class URLAB_API UMjJoint : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint|Spatial Pose", meta=(InlineEditConditionToggle)) + bool bOverride_Pos = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) + FVector Pos = FVector::ZeroVector; + + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_group = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_group")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_group", ToolTip="Visualisation group 0–5. MuJoCo viewer uses this to toggle visibility.")) int32 group = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) + bool bOverride_Axis = false; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_Axis", ToolTip="Joint axis in the parent body's local frame. Hinge: rotation axis. Slide: translation direction. Ignored for Ball and Free.")) + FVector Axis = FVector(0.0f, 0.0f, 1.0f); + + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_springdamper = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_springdamper")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_springdamper", ToolTip="Compact spring spec [stiffness, damping]; populated when MJCF used . Overrides stiffness + damping when set.")) TArray springdamper = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_limited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_limited")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_limited")) bool limited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) - bool bOverride_actuatorfrclimited = false; + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) + bool bOverride_ActFrcLimited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_actuatorfrclimited")) - bool actuatorfrclimited = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_ActFrcLimited")) + bool ActFrcLimited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_solreflimit = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_solreflimit")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_solreflimit")) TArray solreflimit = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_solimplimit = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_solimplimit")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_solimplimit")) TArray solimplimit = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_solreffriction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_solreffriction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_solreffriction")) TArray solreffriction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_solimpfriction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_solimpfriction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_solimpfriction")) TArray solimpfriction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_stiffness = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_stiffness")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_stiffness", ToolTip="Per-axis spring stiffness. Hinge/Ball: N·m/rad. Slide: N/m.")) TArray stiffness = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_range = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_range")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_range", ToolTip="Joint position bounds [min, max]. Hinge/Ball: degrees. Slide: centimetres. Ignored when 'limited' is false.")) TArray range = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) - bool bOverride_actuatorfrcrange = false; + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) + bool bOverride_ActFrcRange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_actuatorfrcrange")) - TArray actuatorfrcrange = {}; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_ActFrcRange", ToolTip="Actuator force bounds [min, max] when 'ActFrcLimited' is true. Hinge/Ball: N·m. Slide: N.")) + TArray ActFrcRange = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_actuatorgravcomp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_actuatorgravcomp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_actuatorgravcomp", ToolTip="Gravity compensation factor passed to actuators on this joint. 0 = no compensation, 1 = full gravity cancelled.")) float actuatorgravcomp = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_margin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_margin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_margin", ToolTip="Contact-detection margin (m). Joints inherit this when computing limit constraints.")) float margin = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_ref = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_ref")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_ref", ToolTip="Reference (zero) position. Hinge/Ball: degrees. Slide: centimetres.")) float ref = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_springref = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_springref")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_springref", ToolTip="Equilibrium position for the joint spring. Hinge/Ball: degrees. Slide: centimetres.")) float springref = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_armature = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_armature")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_armature", ToolTip="Added rotor inertia for hinges (kg·m²) or added mass for slides (kg). Models reflected inertia of the actuator.")) float armature = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_damping = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_damping")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_damping", ToolTip="Per-axis damping. Hinge/Ball: N·m·s/rad. Slide: N·s/m.")) TArray damping = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjJoint", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) bool bOverride_frictionloss = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjJoint", meta=(EditCondition="bOverride_frictionloss")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_frictionloss", ToolTip="Dry-friction loss. Hinge/Ball: N·m. Slide: N.")) float frictionloss = 0.0f; // --- CODEGEN_PROPERTIES_END --- @@ -255,8 +267,10 @@ class URLAB_API UMjJoint : public UMjComponent TArray GetDefaultClassOptions() const; #endif - /** @brief Reference to a UMjDefault component for default class inheritance. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint") + /** @brief Reference to a UMjDefault component for default class inheritance. Hidden from the + * Details panel — synced from MjClassName via the editor dropdown. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", + meta=(EditCondition="false", EditConditionHides)) class UMjDefault* DefaultClass = nullptr; virtual FString GetMjClassName() const override @@ -289,15 +303,10 @@ class URLAB_API UMjJoint : public UMjComponent UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_Type")) EMjJointType Type = EMjJointType::Hinge; - /** @brief Override toggle for Axis. */ - UPROPERTY(EditAnywhere, Category = "MuJoCo|Joint", meta=(InlineEditConditionToggle)) - bool bOverride_Axis = false; - - /** @brief Local joint axis vector (relative to parent body). Ignored for Free/Ball joints. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Joint", meta=(EditCondition="bOverride_Axis")) - FVector Axis = FVector(0.0f, 0.0f, 1.0f); - - + // Axis UPROPERTY is codegen-emitted (rules.joint.vec3_convert.axis = + // y_negate, property_renames.axis = "Axis", property_defaults.axis = + // FVector(0,0,1)). The Pos UPROPERTY is codegen-emitted via the + // spatial_pose canon. // --- Physics Properties (with override toggles) --- diff --git a/Source/URLab/Public/MuJoCo/Components/Joints/MjSlideJoint.h b/Source/URLab/Public/MuJoCo/Components/Joints/MjSlideJoint.h index 68c7a6f..775e35c 100644 --- a/Source/URLab/Public/MuJoCo/Components/Joints/MjSlideJoint.h +++ b/Source/URLab/Public/MuJoCo/Components/Joints/MjSlideJoint.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjSlideJoint - * @brief Specific Slide Joint component. + * @brief Autogenerated component representing the MuJoCo 'slide' element. + * + * Subclass of UMjJoint. Sets Type = Slide in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjSlideJoint : public UMjJoint { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjSlideJoint(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsJoint* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Keyframes/MjKeyframe.h b/Source/URLab/Public/MuJoCo/Components/Keyframes/MjKeyframe.h index 4016eeb..cfec868 100644 --- a/Source/URLab/Public/MuJoCo/Components/Keyframes/MjKeyframe.h +++ b/Source/URLab/Public/MuJoCo/Components/Keyframes/MjKeyframe.h @@ -41,46 +41,46 @@ class URLAB_API UMjKeyframe : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Time = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Time")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Time")) float Time = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Qpos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Qpos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Qpos")) TArray Qpos = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Qvel = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Qvel")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Qvel")) TArray Qvel = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Act = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Act")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Act")) TArray Act = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Mpos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Mpos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Mpos")) TArray Mpos = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Mquat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Mquat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Mquat")) TArray Mquat = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjKeyframe", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Keyframe", meta=(InlineEditConditionToggle)) bool bOverride_Ctrl = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjKeyframe", meta=(EditCondition="bOverride_Ctrl")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Keyframe", meta=(EditCondition="bOverride_Ctrl")) TArray Ctrl = {}; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/MjComponent.h b/Source/URLab/Public/MuJoCo/Components/MjComponent.h index 9c2ef78..091ff90 100644 --- a/Source/URLab/Public/MuJoCo/Components/MjComponent.h +++ b/Source/URLab/Public/MuJoCo/Components/MjComponent.h @@ -105,10 +105,14 @@ class URLAB_API UMjComponent : public USceneComponent, public IMjSpecElement return ViewType(); } - // 1. Try ID based binding via spec element - // NOTE: mjs_getId can return stale/garbage IDs after mjs_attach merges - // a child spec into the root. We validate the ID against model bounds - // before using it. + // 1. Try ID based binding via spec element (the primary path) + // EMPIRICAL (probe test 2026-05-27, MjBindingPathProbeTest): + // mjs_getId returns the correct compiled-model id after mjs_attach + // in current MuJoCo (mj=6882095). Path 1 == Path 2 == Bind in every + // tested scenario. We keep the bounds check + Path 2 fallback as + // safety nets for edge cases not yet observed (recompile mid-PIE, + // multi-attach order, runtime component churn). The old v0.1-alpha + // comment claiming "stale/garbage IDs after mjs_attach" is obsolete. if (m_SpecElement) { int id = mjs_getId(m_SpecElement); @@ -150,6 +154,39 @@ class URLAB_API UMjComponent : public USceneComponent, public IMjSpecElement return ViewType(); } + /** + * @brief Bind a typed view AND cache the resulting mjId on the component. + * + * Collapses the 4-line pattern that 16 base components currently hand-roll: + * Super::Bind(model, data, prefix); + * m_View = BindToView(prefix); + * if (m_View.id != -1) m_ID = m_View.id; + * else UE_LOG warning; + * + * After v8 the per-category Bind() override becomes: + * Super::Bind(model, data, prefix); + * BindAndCacheView(m_View, prefix); + * + * 3 components keep their own Bind() override for real work + * (MjTactileSensor runtime Dim sync, MjPDController, MjFlexcomp); they + * are free to call this helper too if they want. + */ + template + void BindAndCacheView(ViewType& OutView, const FString& Prefix) + { + OutView = BindToView(Prefix); + if (OutView.id != -1) + { + m_ID = OutView.id; + } + else + { + UE_LOG(LogURLabBind, Warning, + TEXT("[BindAndCacheView] '%s' — failed to bind (Prefix='%s', type=%d). m_ID stays -1."), + *GetName(), *Prefix, ViewType::obj_type); + } + } + /** @brief Checks if the component is successfully bound to MuJoCo runtime. */ UFUNCTION(BlueprintCallable, Category = "MuJoCo|Base") bool IsBound() const; @@ -158,6 +195,9 @@ class URLAB_API UMjComponent : public USceneComponent, public IMjSpecElement UFUNCTION(BlueprintCallable, Category = "MuJoCo|Base") int GetMjID() const { return m_ID; } + /** @brief Diagnostic-only accessor for the spec element pointer. Used by binding-path probes. */ + mjsElement* GetSpecElementForDiagnostics() const { return m_SpecElement; } + /** @brief If true, this component is a template in a block. Auto-resolved in Setup(). */ UPROPERTY() bool bIsDefault = false; diff --git a/Source/URLab/Public/MuJoCo/Components/Physics/MjContactExclude.h b/Source/URLab/Public/MuJoCo/Components/Physics/MjContactExclude.h index 6bc92f5..2617a59 100644 --- a/Source/URLab/Public/MuJoCo/Components/Physics/MjContactExclude.h +++ b/Source/URLab/Public/MuJoCo/Components/Physics/MjContactExclude.h @@ -44,24 +44,25 @@ class URLAB_API UMjContactExclude : public USceneComponent, public IMjSpecElemen public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactExclude", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactExclude", meta=(InlineEditConditionToggle)) bool bOverride_body1 = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactExclude", meta=(EditCondition="bOverride_body1")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactExclude", meta=(EditCondition="bOverride_body1")) FString body1 = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactExclude", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactExclude", meta=(InlineEditConditionToggle)) bool bOverride_body2 = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactExclude", meta=(EditCondition="bOverride_body2")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactExclude", meta=(EditCondition="bOverride_body2")) FString body2 = TEXT(""); // --- CODEGEN_PROPERTIES_END --- /** @brief Default constructor. */ UMjContactExclude(); - /** @brief Name of the contact exclusion (optional). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Contact Exclude") + /** @brief Name of the contact exclusion (optional). Hidden from the Details panel — synced from MjName. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Contact Exclude", + meta=(EditCondition="false", EditConditionHides)) FString Name; @@ -85,7 +86,8 @@ class URLAB_API UMjContactExclude : public USceneComponent, public IMjSpecElemen */ virtual void RegisterToSpec(class FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody = nullptr) override; - virtual void Bind(mjModel* model, mjData* data, const FString& Prefix = TEXT("")) override; + /** No-op: contact excludes are global static data, no per-instance runtime binding. Required by IMjSpecElement. */ + virtual void Bind(mjModel* model, mjData* data, const FString& Prefix = TEXT("")) override {} #if WITH_EDITOR UFUNCTION() diff --git a/Source/URLab/Public/MuJoCo/Components/Physics/MjContactPair.h b/Source/URLab/Public/MuJoCo/Components/Physics/MjContactPair.h index 580fd4e..6729a15 100644 --- a/Source/URLab/Public/MuJoCo/Components/Physics/MjContactPair.h +++ b/Source/URLab/Public/MuJoCo/Components/Physics/MjContactPair.h @@ -44,66 +44,67 @@ class URLAB_API UMjContactPair : public USceneComponent, public IMjSpecElement public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_geom1 = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_geom1")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_geom1")) FString geom1 = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_geom2 = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_geom2")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_geom2")) FString geom2 = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_condim = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_condim")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_condim")) int32 condim = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_friction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_friction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_friction")) TArray friction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_solref = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_solref")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_solref")) TArray solref = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_solreffriction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_solreffriction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_solreffriction")) TArray solreffriction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_solimp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_solimp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_solimp")) TArray solimp = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_gap = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_gap")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_gap", Units="m")) float gap = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjContactPair", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|ContactPair", meta=(InlineEditConditionToggle)) bool bOverride_margin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjContactPair", meta=(EditCondition="bOverride_margin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|ContactPair", meta=(EditCondition="bOverride_margin", Units="m")) float margin = 0.0f; // --- CODEGEN_PROPERTIES_END --- /** @brief Default constructor. */ UMjContactPair(); - /** @brief Name of the contact pair (optional). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Contact Pair") + /** @brief Name of the contact pair (optional). Hidden from the Details panel — synced from MjName. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Contact Pair", + meta=(EditCondition="false", EditConditionHides)) FString Name; @@ -133,7 +134,8 @@ class URLAB_API UMjContactPair : public USceneComponent, public IMjSpecElement */ virtual void RegisterToSpec(class FMujocoSpecWrapper& Wrapper, mjsBody* ParentBody = nullptr) override; - virtual void Bind(mjModel* model, mjData* data, const FString& Prefix = TEXT("")) override; + /** No-op: contact pairs are global static data, no per-instance runtime binding. Required by IMjSpecElement. */ + virtual void Bind(mjModel* model, mjData* data, const FString& Prefix = TEXT("")) override {} #if WITH_EDITOR UFUNCTION() diff --git a/Source/URLab/Public/MuJoCo/Components/Physics/MjInertial.h b/Source/URLab/Public/MuJoCo/Components/Physics/MjInertial.h index 095dd27..b641446 100644 --- a/Source/URLab/Public/MuJoCo/Components/Physics/MjInertial.h +++ b/Source/URLab/Public/MuJoCo/Components/Physics/MjInertial.h @@ -38,34 +38,34 @@ class URLAB_API UMjInertial : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjInertial|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Inertial|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjInertial|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Inertial|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjInertial|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Inertial|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjInertial|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Inertial|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjInertial", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Inertial", meta=(InlineEditConditionToggle)) bool bOverride_mass = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjInertial", meta=(EditCondition="bOverride_mass")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Inertial", meta=(EditCondition="bOverride_mass")) float mass = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjInertial", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Inertial", meta=(InlineEditConditionToggle)) bool bOverride_diaginertia = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjInertial", meta=(EditCondition="bOverride_diaginertia")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Inertial", meta=(EditCondition="bOverride_diaginertia")) TArray diaginertia = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjInertial", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Inertial", meta=(InlineEditConditionToggle)) bool bOverride_fullinertia = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjInertial", meta=(EditCondition="bOverride_fullinertia")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Inertial", meta=(EditCondition="bOverride_fullinertia")) TArray fullinertia = {}; // --- CODEGEN_PROPERTIES_END --- @@ -87,12 +87,6 @@ class URLAB_API UMjInertial : public UMjComponent // Note: Inertial usually doesn't have a direct 'mjsInertial' struct in mjspec.h same as others, // it's often part of body or explicit inertial element. // mjsBody has 'mass', 'inertia', 'fullinertia'. - - /** - * @brief Binds this component to the live MuJoCo simulation. - */ - virtual void Bind(mjModel* model, mjData* data, const FString& Prefix = TEXT("")) override; - /** * @brief Registers/Applies this inertial to the parent body in the spec. * @param Wrapper The spec wrapper instance. diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjAccelerometer.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjAccelerometer.h index 8844dd5..a37f099 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjAccelerometer.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjAccelerometer.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjAccelerometer - * @brief Specific Accelerometer Sensor component. + * @brief Autogenerated component representing the MuJoCo 'accelerometer' element. + * + * Subclass of UMjSensor. Sets Type = Accelerometer in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjAccelerometer : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjAccelerometer(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorFrcSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorFrcSensor.h index 37bdc00..b9bd325 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorFrcSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorFrcSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjActuatorFrcSensor - * @brief Specific ActuatorFrc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'actuatorfrc' element. + * + * Subclass of UMjSensor. Sets Type = ActuatorFrc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjActuatorFrcSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjActuatorFrcSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorPosSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorPosSensor.h index e40c6b8..53985a5 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorPosSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorPosSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjActuatorPosSensor - * @brief Specific ActuatorPos Sensor component. + * @brief Autogenerated component representing the MuJoCo 'actuatorpos' element. + * + * Subclass of UMjSensor. Sets Type = ActuatorPos in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjActuatorPosSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjActuatorPosSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorVelSensor.h index af8e89b..e199943 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjActuatorVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjActuatorVelSensor - * @brief Specific ActuatorVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'actuatorvel' element. + * + * Subclass of UMjSensor. Sets Type = ActuatorVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjActuatorVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjActuatorVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallAngVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallAngVelSensor.h index 9951314..9085250 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallAngVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallAngVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjBallAngVelSensor - * @brief Specific BallAngVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'ballangvel' element. + * + * Subclass of UMjSensor. Sets Type = BallAngVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjBallAngVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjBallAngVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallQuatSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallQuatSensor.h index e116d94..e11918d 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallQuatSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjBallQuatSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjBallQuatSensor - * @brief Specific BallQuat Sensor component. + * @brief Autogenerated component representing the MuJoCo 'ballquat' element. + * + * Subclass of UMjSensor. Sets Type = BallQuat in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjBallQuatSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjBallQuatSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamProjectionSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamProjectionSensor.h index 29c3003..7c41bd5 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamProjectionSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamProjectionSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjCamProjectionSensor - * @brief Specific CamProjection Sensor component. + * @brief Autogenerated component representing the MuJoCo 'camprojection' element. + * + * Subclass of UMjSensor. Sets Type = CamProjection in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjCamProjectionSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjCamProjectionSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamera.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamera.h index 6d6830f..ca26b00 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamera.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjCamera.h @@ -86,76 +86,76 @@ class URLAB_API UMjCamera : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera|Spatial Pose", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera|Spatial Pose", meta=(InlineEditConditionToggle)) bool bOverride_Pos = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera|Spatial Pose", meta=(EditCondition="bOverride_Pos")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera|Spatial Pose", meta=(EditCondition="false", EditConditionHides)) FVector Pos = FVector::ZeroVector; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera|Orientation", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera|Orientation", meta=(InlineEditConditionToggle)) bool bOverride_Quat = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera|Orientation", meta=(EditCondition="bOverride_Quat")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera|Orientation", meta=(EditCondition="false", EditConditionHides)) FQuat Quat = FQuat::Identity; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_fovy = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_fovy")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_fovy", Units="deg")) float fovy = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_ipd = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_ipd")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_ipd", Units="m")) float ipd = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_resolution = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_resolution")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_resolution")) TArray resolution = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_output = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_output")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_output")) float output = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_target = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_target")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_target")) FString target = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_focal = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_focal")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_focal", MjUnit="m")) TArray focal = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_focalpixel = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_focalpixel")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_focalpixel")) TArray focalpixel = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_principal = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_principal")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_principal", MjUnit="m")) TArray principal = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_principalpixel = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_principalpixel")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_principalpixel")) TArray principalpixel = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjCamera", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Camera", meta=(InlineEditConditionToggle)) bool bOverride_sensorsize = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjCamera", meta=(EditCondition="bOverride_sensorsize")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Camera", meta=(EditCondition="bOverride_sensorsize", MjUnit="m")) TArray sensorsize = {}; // --- CODEGEN_PROPERTIES_END --- diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjCameraTypes.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjCameraTypes.h index f4f5cd4..7b54b45 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjCameraTypes.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjCameraTypes.h @@ -20,6 +20,7 @@ #pragma once #include "CoreMinimal.h" +#include "MuJoCo/Generated/MjArticulationEnums.h" #include "MjCameraTypes.generated.h" /** @@ -39,39 +40,5 @@ enum class EMjCameraMode : uint8 InstanceSegmentation UMETA(DisplayName = "Instance Segmentation"), }; -/** - * @enum EMjCameraTrackingMode - * @brief MJCF ```` tracking mode. Mirrors MuJoCo's - * mjtCamLight subset that applies to cameras. Distinct from - * ``EMjCameraMode`` above (which is URLab's render-mode selector, - * not a MuJoCo concept). - * - * - Fixed: camera attached to its body with a fixed transform. - * - Track: camera follows the body's world position, keeps own rotation. - * - TrackCom: like Track but follows the subtree centre of mass. - * - TargetBody: camera stays at its own position; rotates to look at target body. - * - TargetBodyCom: like TargetBody but aims at the target's subtree CoM. - */ -UENUM(BlueprintType) -enum class EMjCameraTrackingMode : uint8 -{ - Fixed UMETA(DisplayName = "Fixed"), - Track UMETA(DisplayName = "Track"), - TrackCom UMETA(DisplayName = "Track (Centre of Mass)"), - TargetBody UMETA(DisplayName = "Target Body"), - TargetBodyCom UMETA(DisplayName = "Target Body (Centre of Mass)"), -}; - -/** - * @enum EMjCameraProjection - * @brief MJCF ````. Mirrors MuJoCo's mjtProjection. - * - * - Perspective: standard pinhole camera (default). - * - Orthographic: parallel projection, no perspective foreshortening. - */ -UENUM(BlueprintType) -enum class EMjCameraProjection : uint8 -{ - Perspective UMETA(DisplayName = "Perspective"), - Orthographic UMETA(DisplayName = "Orthographic"), -}; +// EMjCameraTrackingMode, EMjCameraProjection moved to +// MuJoCo/Generated/MjArticulationEnums.h. diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjClockSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjClockSensor.h index b399abc..2c610c6 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjClockSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjClockSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjClockSensor - * @brief Specific Clock Sensor component. + * @brief Autogenerated component representing the MuJoCo 'clock' element. + * + * Subclass of UMjSensor. Sets Type = Clock in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjClockSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjClockSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjContactSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjContactSensor.h index fed4c67..68aa046 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjContactSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjContactSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjContactSensor - * @brief Specific Contact Sensor component. + * @brief Autogenerated component representing the MuJoCo 'contact' element. + * + * Subclass of UMjSensor. Sets Type = Contact in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjContactSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjContactSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjEKineticSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjEKineticSensor.h index 00b4fdd..9854712 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjEKineticSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjEKineticSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjEKineticSensor - * @brief Specific EKinetic Sensor component. + * @brief Autogenerated component representing the MuJoCo 'e_kinetic' element. + * + * Subclass of UMjSensor. Sets Type = EKinetic in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjEKineticSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjEKineticSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjEPotentialSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjEPotentialSensor.h index 7376469..7f244d1 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjEPotentialSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjEPotentialSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjEPotentialSensor - * @brief Specific EPotential Sensor component. + * @brief Autogenerated component representing the MuJoCo 'e_potential' element. + * + * Subclass of UMjSensor. Sets Type = EPotential in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjEPotentialSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjEPotentialSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjForceSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjForceSensor.h index 00d3807..1b106b6 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjForceSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjForceSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjForceSensor - * @brief Specific Force Sensor component. + * @brief Autogenerated component representing the MuJoCo 'force' element. + * + * Subclass of UMjSensor. Sets Type = Force in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjForceSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjForceSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngAccSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngAccSensor.h index 4ddbe0f..4f4f01f 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngAccSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngAccSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameAngAccSensor - * @brief Specific FrameAngAcc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'frameangacc' element. + * + * Subclass of UMjSensor. Sets Type = FrameAngAcc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameAngAccSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameAngAccSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngVelSensor.h index 2047e11..d58259a 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameAngVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameAngVelSensor - * @brief Specific FrameAngVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'frameangvel' element. + * + * Subclass of UMjSensor. Sets Type = FrameAngVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameAngVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameAngVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinAccSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinAccSensor.h index 1d969dc..cbf6e4a 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinAccSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinAccSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameLinAccSensor - * @brief Specific FrameLinAcc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'framelinacc' element. + * + * Subclass of UMjSensor. Sets Type = FrameLinAcc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameLinAccSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameLinAccSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinVelSensor.h index c8d71ad..1bd0994 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameLinVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameLinVelSensor - * @brief Specific FrameLinVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'framelinvel' element. + * + * Subclass of UMjSensor. Sets Type = FrameLinVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameLinVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameLinVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFramePosSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFramePosSensor.h index 78a21cf..27d8640 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFramePosSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFramePosSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFramePosSensor - * @brief Specific FramePos Sensor component. + * @brief Autogenerated component representing the MuJoCo 'framepos' element. + * + * Subclass of UMjSensor. Sets Type = FramePos in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFramePosSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFramePosSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameQuatSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameQuatSensor.h index f80797f..f6d43f6 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameQuatSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameQuatSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameQuatSensor - * @brief Specific FrameQuat Sensor component. + * @brief Autogenerated component representing the MuJoCo 'framequat' element. + * + * Subclass of UMjSensor. Sets Type = FrameQuat in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameQuatSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameQuatSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameXAxisSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameXAxisSensor.h index 0891c29..27caf41 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameXAxisSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameXAxisSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameXAxisSensor - * @brief Specific FrameXAxis Sensor component. + * @brief Autogenerated component representing the MuJoCo 'framexaxis' element. + * + * Subclass of UMjSensor. Sets Type = FrameXAxis in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameXAxisSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameXAxisSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameYAxisSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameYAxisSensor.h index a58d758..1fa5ee4 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameYAxisSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameYAxisSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameYAxisSensor - * @brief Specific FrameYAxis Sensor component. + * @brief Autogenerated component representing the MuJoCo 'frameyaxis' element. + * + * Subclass of UMjSensor. Sets Type = FrameYAxis in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameYAxisSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameYAxisSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameZAxisSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameZAxisSensor.h index 8508c3c..14f797b 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameZAxisSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjFrameZAxisSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjFrameZAxisSensor - * @brief Specific FrameZAxis Sensor component. + * @brief Autogenerated component representing the MuJoCo 'framezaxis' element. + * + * Subclass of UMjSensor. Sets Type = FrameZAxis in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjFrameZAxisSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjFrameZAxisSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomDistSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomDistSensor.h index 58c4457..fb8064d 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomDistSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomDistSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjGeomDistSensor - * @brief Specific GeomDist Sensor component. + * @brief Autogenerated component representing the MuJoCo 'distance' element. + * + * Subclass of UMjSensor. Sets Type = GeomDist in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjGeomDistSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjGeomDistSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomFromToSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomFromToSensor.h index 04046f0..951bfa6 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomFromToSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomFromToSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjGeomFromToSensor - * @brief Specific GeomFromTo Sensor component. + * @brief Autogenerated component representing the MuJoCo 'fromto' element. + * + * Subclass of UMjSensor. Sets Type = GeomFromTo in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjGeomFromToSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjGeomFromToSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomNormalSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomNormalSensor.h index 3c9f132..f55857f 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomNormalSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGeomNormalSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjGeomNormalSensor - * @brief Specific GeomNormal Sensor component. + * @brief Autogenerated component representing the MuJoCo 'normal' element. + * + * Subclass of UMjSensor. Sets Type = GeomNormal in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjGeomNormalSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjGeomNormalSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGyro.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGyro.h index 5481a95..43ccb21 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjGyro.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjGyro.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjGyro - * @brief Specific Gyro Sensor component. + * @brief Autogenerated component representing the MuJoCo 'gyro' element. + * + * Subclass of UMjSensor. Sets Type = Gyro in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjGyro : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjGyro(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjInsideSiteSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjInsideSiteSensor.h index a4a7c0e..ad8b774 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjInsideSiteSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjInsideSiteSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjInsideSiteSensor - * @brief Specific InsideSite Sensor component. + * @brief Autogenerated component representing the MuJoCo 'insidesite' element. + * + * Subclass of UMjSensor. Sets Type = InsideSite in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjInsideSiteSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjInsideSiteSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointActFrcSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointActFrcSensor.h index bc6cfcd..9e3cab8 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointActFrcSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointActFrcSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjJointActFrcSensor - * @brief Specific JointActFrc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'jointactuatorfrc' element. + * + * Subclass of UMjSensor. Sets Type = JointActFrc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjJointActFrcSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjJointActFrcSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.h index 885e010..d885cb4 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitFrcSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjJointLimitFrcSensor - * @brief Specific JointLimitFrc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'jointlimitfrc' element. + * + * Subclass of UMjSensor. Sets Type = JointLimitFrc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjJointLimitFrcSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjJointLimitFrcSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitPosSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitPosSensor.h index 873bf63..5bfe8f5 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitPosSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitPosSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjJointLimitPosSensor - * @brief Specific JointLimitPos Sensor component. + * @brief Autogenerated component representing the MuJoCo 'jointlimitpos' element. + * + * Subclass of UMjSensor. Sets Type = JointLimitPos in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjJointLimitPosSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjJointLimitPosSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitVelSensor.h index 3dafbbc..5091c92 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointLimitVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjJointLimitVelSensor - * @brief Specific JointLimitVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'jointlimitvel' element. + * + * Subclass of UMjSensor. Sets Type = JointLimitVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjJointLimitVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjJointLimitVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointPosSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointPosSensor.h index 613b657..0ce1cc7 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointPosSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointPosSensor.h @@ -36,7 +36,6 @@ class URLAB_API UMjJointPosSensor : public UMjSensor GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjJointPosSensor(); diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointVelSensor.h index 28eedb4..b1f5df1 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjJointVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjJointVelSensor - * @brief Specific JointVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'jointvel' element. + * + * Subclass of UMjSensor. Sets Type = JointVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjJointVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjJointVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjMagnetometer.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjMagnetometer.h index a571e9b..0af7e9a 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjMagnetometer.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjMagnetometer.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjMagnetometer - * @brief Specific Magnetometer Sensor component. + * @brief Autogenerated component representing the MuJoCo 'magnetometer' element. + * + * Subclass of UMjSensor. Sets Type = Magnetometer in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjMagnetometer : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjMagnetometer(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjPluginSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjPluginSensor.h index 7f06590..7509f0e 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjPluginSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjPluginSensor.h @@ -44,7 +44,7 @@ class URLAB_API UMjPluginSensor : public UMjSensor UMjPluginSensor(); // --- CODEGEN_PROPERTIES_START --- - + // (no type-specific schema attrs) // --- CODEGEN_PROPERTIES_END --- virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjRangeFinderSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjRangeFinderSensor.h index 736fe41..14b333b 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjRangeFinderSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjRangeFinderSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjRangeFinderSensor - * @brief Specific RangeFinder Sensor component. + * @brief Autogenerated component representing the MuJoCo 'rangefinder' element. + * + * Subclass of UMjSensor. Sets Type = RangeFinder in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjRangeFinderSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjRangeFinderSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSensor.h index f6e1798..387e07c 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSensor.h @@ -29,6 +29,7 @@ #include "MuJoCo/Core/Spec/MjSpecElement.h" #include "MuJoCo/Components/MjComponent.h" #include "MuJoCo/Components/Defaults/MjDefault.h" +#include "MuJoCo/Generated/MjArticulationEnums.h" #include "MuJoCo/Utils/MjBind.h" #include "MuJoCo/Utils/MjOrientationUtils.h" #include "MjSensor.generated.h" @@ -112,38 +113,7 @@ enum class EMjSensorType : uint8 User }; -/** - * @enum EMjObjType - * @brief Mirror of mjtObj for specifying sensor attachment/reference types. - */ -UENUM(BlueprintType) -enum class EMjObjType : uint8 -{ - Unknown, - Body, - XBody, - Joint, - DoF, - Geom, - Site, - Camera, - Light, - Mesh, - HField, - Texture, - Material, - Pair, - Exclude, - Equality, - Tendon, - Actuator, - Sensor, - Numeric, - Text, - Tuple, - Key, - Plugin, -}; +// EMjObjType moved to MuJoCo/Generated/MjArticulationEnums.h. /** * @class UMjSensor @@ -159,40 +129,40 @@ class URLAB_API UMjSensor : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSensor", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Sensor", meta=(InlineEditConditionToggle)) bool bOverride_nsample = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSensor", meta=(EditCondition="bOverride_nsample")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(EditCondition="bOverride_nsample")) int32 nsample = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSensor", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Sensor", meta=(InlineEditConditionToggle)) bool bOverride_interp = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSensor", meta=(EditCondition="bOverride_interp")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(EditCondition="bOverride_interp")) int32 interp = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSensor", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Sensor", meta=(InlineEditConditionToggle)) bool bOverride_delay = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSensor", meta=(EditCondition="bOverride_delay")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(EditCondition="bOverride_delay")) float delay = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSensor", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Sensor", meta=(InlineEditConditionToggle)) bool bOverride_interval = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSensor", meta=(EditCondition="bOverride_interval")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(EditCondition="bOverride_interval")) TArray interval = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSensor", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Sensor", meta=(InlineEditConditionToggle)) bool bOverride_cutoff = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSensor", meta=(EditCondition="bOverride_cutoff")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(EditCondition="bOverride_cutoff")) float cutoff = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjSensor", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Sensor", meta=(InlineEditConditionToggle)) bool bOverride_noise = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjSensor", meta=(EditCondition="bOverride_noise")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(EditCondition="bOverride_noise")) float noise = 0.0f; // --- CODEGEN_PROPERTIES_END --- @@ -226,8 +196,10 @@ class URLAB_API UMjSensor : public UMjComponent UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", meta=(GetOptions="GetDefaultClassOptions")) FString MjClassName; - /** @brief Reference to a UMjDefault component for default class inheritance. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor") + /** @brief Reference to a UMjDefault component for default class inheritance. Hidden from the + * Details panel — synced from MjClassName via the editor dropdown. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Sensor", + meta=(EditCondition="false", EditConditionHides)) UMjDefault* DefaultClass = nullptr; virtual FString GetMjClassName() const override diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.h index 10ad220..c76de53 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeAngMomSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjSubtreeAngMomSensor - * @brief Specific SubtreeAngMom Sensor component. + * @brief Autogenerated component representing the MuJoCo 'subtreeangmom' element. + * + * Subclass of UMjSensor. Sets Type = SubtreeAngMom in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjSubtreeAngMomSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjSubtreeAngMomSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeComSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeComSensor.h index 0416196..cdc8ff1 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeComSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeComSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjSubtreeComSensor - * @brief Specific SubtreeCom Sensor component. + * @brief Autogenerated component representing the MuJoCo 'subtreecom' element. + * + * Subclass of UMjSensor. Sets Type = SubtreeCom in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjSubtreeComSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjSubtreeComSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.h index 8fff017..d777b61 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjSubtreeLinVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjSubtreeLinVelSensor - * @brief Specific SubtreeLinVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'subtreelinvel' element. + * + * Subclass of UMjSensor. Sets Type = SubtreeLinVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjSubtreeLinVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjSubtreeLinVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTactileSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTactileSensor.h index 9189c4c..e1b69cf 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTactileSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTactileSensor.h @@ -36,7 +36,6 @@ class URLAB_API UMjTactileSensor : public UMjSensor GENERATED_BODY() public: // --- CODEGEN_PROPERTIES_START --- - // --- CODEGEN_PROPERTIES_END --- UMjTactileSensor(); diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonActFrcSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonActFrcSensor.h index 64672ab..be2ea3d 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonActFrcSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonActFrcSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTendonActFrcSensor - * @brief Specific TendonActFrc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'tendonactuatorfrc' element. + * + * Subclass of UMjSensor. Sets Type = TendonActFrc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTendonActFrcSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTendonActFrcSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.h index 1e39b2d..7b701ca 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitFrcSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTendonLimitFrcSensor - * @brief Specific TendonLimitFrc Sensor component. + * @brief Autogenerated component representing the MuJoCo 'tendonlimitfrc' element. + * + * Subclass of UMjSensor. Sets Type = TendonLimitFrc in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTendonLimitFrcSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTendonLimitFrcSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.h index e9d8ed1..31bebc3 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitPosSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTendonLimitPosSensor - * @brief Specific TendonLimitPos Sensor component. + * @brief Autogenerated component representing the MuJoCo 'tendonlimitpos' element. + * + * Subclass of UMjSensor. Sets Type = TendonLimitPos in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTendonLimitPosSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTendonLimitPosSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.h index 735495d..6858e73 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonLimitVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTendonLimitVelSensor - * @brief Specific TendonLimitVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'tendonlimitvel' element. + * + * Subclass of UMjSensor. Sets Type = TendonLimitVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTendonLimitVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTendonLimitVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonPosSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonPosSensor.h index b26c9c0..9b1bf45 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonPosSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonPosSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTendonPosSensor - * @brief Specific TendonPos Sensor component. + * @brief Autogenerated component representing the MuJoCo 'tendonpos' element. + * + * Subclass of UMjSensor. Sets Type = TendonPos in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTendonPosSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTendonPosSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonVelSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonVelSensor.h index f115862..9587c1c 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonVelSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTendonVelSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTendonVelSensor - * @brief Specific TendonVel Sensor component. + * @brief Autogenerated component representing the MuJoCo 'tendonvel' element. + * + * Subclass of UMjSensor. Sets Type = TendonVel in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTendonVelSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTendonVelSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTorqueSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTorqueSensor.h index 5aa7034..24d3a50 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTorqueSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTorqueSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTorqueSensor - * @brief Specific Torque Sensor component. + * @brief Autogenerated component representing the MuJoCo 'torque' element. + * + * Subclass of UMjSensor. Sets Type = Torque in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTorqueSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTorqueSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTouchSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTouchSensor.h index dd9a3e8..0ec70cc 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjTouchSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjTouchSensor.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjTouchSensor - * @brief Specific Touch Sensor component. + * @brief Autogenerated component representing the MuJoCo 'touch' element. + * + * Subclass of UMjSensor. Sets Type = Touch in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjTouchSensor : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjTouchSensor(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjUserSensor.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjUserSensor.h index 9984711..0c1a06c 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjUserSensor.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjUserSensor.h @@ -44,7 +44,7 @@ class URLAB_API UMjUserSensor : public UMjSensor UMjUserSensor(); // --- CODEGEN_PROPERTIES_START --- - + // (no type-specific schema attrs) // --- CODEGEN_PROPERTIES_END --- virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; diff --git a/Source/URLab/Public/MuJoCo/Components/Sensors/MjVelocimeter.h b/Source/URLab/Public/MuJoCo/Components/Sensors/MjVelocimeter.h index 0db16dc..2c15c44 100644 --- a/Source/URLab/Public/MuJoCo/Components/Sensors/MjVelocimeter.h +++ b/Source/URLab/Public/MuJoCo/Components/Sensors/MjVelocimeter.h @@ -13,12 +13,15 @@ // limitations under the License. // // --- LEGAL DISCLAIMER --- -// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, -// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are +// UnrealRoboticsLab is an independent software plugin. It is NOT affiliated with, +// endorsed by, or sponsored by Epic Games, Inc. "Unreal" and "Unreal Engine" are // trademarks or registered trademarks of Epic Games, Inc. in the US and elsewhere. // -// This plugin incorporates third-party software: MuJoCo (Apache 2.0), +// This plugin incorporates third-party software: MuJoCo (Apache 2.0), // CoACD (MIT), and libzmq (MPL 2.0). See ThirdPartyNotices.txt for details. +// +// AUTOGENERATED by Scripts/codegen/generate_ue_components.py +// Do not edit by hand. Re-run the generator to regenerate. #pragma once @@ -28,20 +31,22 @@ /** * @class UMjVelocimeter - * @brief Specific Velocimeter Sensor component. + * @brief Autogenerated component representing the MuJoCo 'velocimeter' element. + * + * Subclass of UMjSensor. Sets Type = Velocimeter in the constructor. */ -UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent)) +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class URLAB_API UMjVelocimeter : public UMjSensor { GENERATED_BODY() -public: - // --- CODEGEN_PROPERTIES_START --- - - // --- CODEGEN_PROPERTIES_END --- +public: UMjVelocimeter(); - virtual void ImportFromXml(const class FXmlNode* Node, const struct FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; + // --- CODEGEN_PROPERTIES_START --- + // (no type-specific schema attrs) + // --- CODEGEN_PROPERTIES_END --- + virtual void ImportFromXml(const class FXmlNode* Node, const FMjCompilerSettings& CompilerSettings = FMjCompilerSettings{}) override; virtual void ExportTo(mjsSensor* Element, mjsDefault* Default = nullptr) override; }; diff --git a/Source/URLab/Public/MuJoCo/Components/Tendons/MjTendon.h b/Source/URLab/Public/MuJoCo/Components/Tendons/MjTendon.h index 1b7a4be..66c0013 100644 --- a/Source/URLab/Public/MuJoCo/Components/Tendons/MjTendon.h +++ b/Source/URLab/Public/MuJoCo/Components/Tendons/MjTendon.h @@ -112,112 +112,112 @@ class URLAB_API UMjTendon : public UMjComponent public: // --- CODEGEN_PROPERTIES_START --- - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_group = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_group")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_group")) int32 group = 0; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_limited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_limited")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_limited")) bool limited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) - bool bOverride_actuatorfrclimited = false; + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) + bool bOverride_ActFrcLimited = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_actuatorfrclimited")) - bool actuatorfrclimited = false; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_ActFrcLimited")) + bool ActFrcLimited = false; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_range = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_range")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_range")) TArray range = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) - bool bOverride_actuatorfrcrange = false; + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) + bool bOverride_ActFrcRange = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_actuatorfrcrange")) - TArray actuatorfrcrange = {}; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_ActFrcRange")) + TArray ActFrcRange = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_solreflimit = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_solreflimit")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_solreflimit")) TArray solreflimit = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_solimplimit = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_solimplimit")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_solimplimit")) TArray solimplimit = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_solreffriction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_solreffriction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_solreffriction")) TArray solreffriction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_solimpfriction = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_solimpfriction")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_solimpfriction")) TArray solimpfriction = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_frictionloss = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_frictionloss")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_frictionloss")) float frictionloss = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_springlength = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_springlength")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_springlength", MjUnit="m")) TArray springlength = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_width = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_width")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_width")) float width = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_material = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_material")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_material")) FString material = TEXT(""); - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_margin = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_margin")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_margin")) float margin = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_stiffness = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_stiffness")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_stiffness")) TArray stiffness = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_damping = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_damping")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_damping")) TArray damping = {}; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_armature = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_armature")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_armature")) float armature = 0.0f; - UPROPERTY(EditAnywhere, Category = "MuJoCo|MjTendon", meta=(InlineEditConditionToggle)) + UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon", meta=(InlineEditConditionToggle)) bool bOverride_rgba = false; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|MjTendon", meta=(EditCondition="bOverride_rgba")) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(EditCondition="bOverride_rgba")) FLinearColor rgba = FLinearColor::White; // --- CODEGEN_PROPERTIES_END --- @@ -290,8 +290,10 @@ class URLAB_API UMjTendon : public UMjComponent UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", meta=(GetOptions="GetDefaultClassOptions")) FString MjClassName; - /** @brief Reference to a UMjDefault component for default class inheritance. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon") + /** @brief Reference to a UMjDefault component for default class inheritance. Hidden from the + * Details panel — synced from MjClassName via the editor dropdown. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon", + meta=(EditCondition="false", EditConditionHides)) UMjDefault* DefaultClass = nullptr; virtual FString GetMjClassName() const override @@ -328,23 +330,10 @@ class URLAB_API UMjTendon : public UMjComponent - // --- Actuator Limits --- - - /** @brief Override toggle for bActFrcLimited. */ - UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon|Limits", meta=(InlineEditConditionToggle)) - bool bOverride_ActFrcLimited = false; - - /** @brief Whether the tendon has actuator force limits. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon|Limits", meta=(EditCondition="bOverride_ActFrcLimited")) - bool bActFrcLimited = false; - - /** @brief Override toggle for ActFrcRange. */ - UPROPERTY(EditAnywhere, Category = "MuJoCo|Tendon|Limits", meta=(InlineEditConditionToggle)) - bool bOverride_ActFrcRange = false; - - /** @brief Tendon actuator force limits [min, max]. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MuJoCo|Tendon|Limits", meta=(EditCondition="bOverride_ActFrcRange")) - TArray ActFrcRange = {0.0f, 0.0f}; + // ActFrcLimited / ActFrcRange UPROPERTYs are codegen-emitted in the + // CODEGEN_PROPERTIES block above (driven by codegen_rules.json's + // property_renames: actuatorfrclimited -> ActFrcLimited / actuatorfrcrange + // -> ActFrcRange). // --- Solver Parameters --- diff --git a/Source/URLab/Public/MuJoCo/Core/MjArticulation.h b/Source/URLab/Public/MuJoCo/Core/MjArticulation.h index 42a5e3d..cddf57b 100644 --- a/Source/URLab/Public/MuJoCo/Core/MjArticulation.h +++ b/Source/URLab/Public/MuJoCo/Core/MjArticulation.h @@ -25,7 +25,7 @@ #include "CoreMinimal.h" #include #include "MuJoCo/Core/Spec/MjSpecWrapper.h" -#include "MuJoCo/Core/MjSimOptions.h" +#include "MuJoCo/Generated/MjOptionGenerated.h" #include "GameFramework/Pawn.h" #include "MuJoCo/Components/Bodies/MjBody.h" #include "MuJoCo/Components/Joints/MjJoint.h" @@ -207,8 +207,8 @@ class URLAB_API AMjArticulation : public APawn UFUNCTION(BlueprintCallable, Category = "MuJoCo|Discovery") TArray GetRuntimeComponentsOfClass(TSubclassOf ComponentClass) const; - /** - * @brief Templated helper to find all components of type T belonging to this articulation + /** + * @brief Templated helper to find all components of type T belonging to this articulation * that are NOT marked as 'bIsDefault'. This is the standard way to find simulation-active components. */ template @@ -231,6 +231,51 @@ class URLAB_API AMjArticulation : public APawn } } + // ============================================================================ + // Templated map-lookup helpers — collapse the 9 hand-rolled `GetNames` / + // `Gets` / `GetByMjId` methods into 1-line BP wrappers per category. + // Equality and Keyframe getters do NOT use these (name-keyed maps + dedup + + // different name-source) — they stay hand-rolled. See deviation D-future. + // ============================================================================ + + /** Return all values from an id-keyed component map. */ + template + TArray GetComponentsFromMap(const TMap& IdMap) const + { + TArray Out; + IdMap.GenerateValueArray(Out); + return Out; + } + + /** Return MuJoCo names of all components in an id-keyed map (skipping null values). */ + template + TArray GetComponentNamesFromMap(const TMap& IdMap) const + { + TArray Names; + Names.Reserve(IdMap.Num()); + for (const auto& Pair : IdMap) + { + if (Pair.Value) Names.Add(Pair.Value->GetMjName()); + } + return Names; + } + + /** Lookup a component by its compiled mjId in an id-keyed map. Returns nullptr if absent. */ + template + T* GetComponentByIdInMap(int Id, const TMap& IdMap) const + { + if (T* const* Found = IdMap.Find(Id)) return *Found; + return nullptr; + } + + /** Lookup a component by name in a name-keyed map. Returns nullptr if absent. */ + template + T* GetComponentByNameInMap(const FString& Name, const TMap& NameMap) const + { + if (T* const* Found = NameMap.Find(Name)) return *Found; + return nullptr; + } + // ========================================================================= // Blueprint Runtime API — Component Accessors (delegate to the component) // ========================================================================= @@ -370,6 +415,9 @@ class URLAB_API AMjArticulation : public APawn UPROPERTY(BlueprintReadOnly, Category = "MuJoCo|Status") bool bAttachFailed = false; + /** @brief Diagnostic-only accessor for the articulation prefix used by mjs_attach. */ + FString GetPrefixForDiagnostics() const { return m_prefix; } + protected: mjVFS* m_vfs = nullptr; mjSpec* m_spec = nullptr; @@ -417,7 +465,7 @@ class URLAB_API AMjArticulation : public APawn * Parsed from the MJCF