MCPcopy Create free account
hub / github.com/URLab-Sim/UnrealRoboticsLab / _emit_export_line

Function _emit_export_line

Scripts/codegen/generate_ue_components.py:377–448  ·  view source on GitHub ↗
(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,
                      vec3_convert: Optional[str] = None,
                      array_cap: Optional[int] = None)

Source from the content-addressed store, hash-verified

375
376
377def _emit_export_line(attr: str, prop_name: str, ue_type: str,
378 mjs_fields: set | None = None,
379 slot_sentinel: str | None = None,
380 attr_to_mjs_field: Dict[str, str] | None = None,
381 consumed_by_setto: set | None = None,
382 vec3_convert: Optional[str] = None,
383 array_cap: Optional[int] = None) -> str:
384 toggle = override_toggle_name(prop_name)
385 # If we have an mjs field set and the attr can't be resolved to one of
386 # them, this attr isn't directly assignable on the mjs struct (e.g.
387 # actuator subtype params like `kp` live in gainprm[], not Element->kp).
388 # Emit either:
389 # - nothing (silent) when the attr is consumed by an mjs_setTo* call
390 # above us in the same CODEGEN_EXPORT block (no need for noise)
391 # - a one-line "(skipped)" marker otherwise (genuinely unhandled,
392 # reviewers should know)
393 if mjs_fields:
394 field = _resolve_mjs_field(attr, mjs_fields, attr_to_mjs_field)
395 if field == attr and attr not in mjs_fields and not (
396 attr_to_mjs_field and attr in attr_to_mjs_field
397 ):
398 if consumed_by_setto and attr in consumed_by_setto:
399 return ""
400 return f' // (skipped: mjs has no field for "{attr}"; hand-roll via mjs_setTo<Type>)\n'
401 else:
402 field = attr_to_mjs_field.get(attr, attr) if attr_to_mjs_field else attr
403 if ue_type.startswith("TArray<float") or ue_type.startswith("TArray<int") or ue_type.startswith("TArray<double"):
404 # When the destination C field is a fixed-size array, cap the
405 # loop count against the C array dim so a future MuJoCo shrink
406 # (gainprm[10] -> gainprm[6]) doesn't memory-overrun. Dynamic
407 # vec destinations (mjFloatVec*, mjDoubleVec*) pass array_cap=None
408 # and use the raw prop.Num() — the dynamic vec resizes itself.
409 upper = f"FMath::Min({prop_name}.Num(), {array_cap})" if array_cap else f"{prop_name}.Num()"
410 if slot_sentinel is not None:
411 # Per-slot sentinel guard: skip slots whose value equals the
412 # sentinel (used for `size` so fromto-only imports don't
413 # clobber the inherited default radius / earlier slots).
414 return _guarded_export(toggle,
415 f'{{ for (int32 i = 0; i < {upper}; ++i)'
416 f' {{ if ({prop_name}[i] != {slot_sentinel}) Element->{field}[i] = {prop_name}[i]; }} }}',
417 )
418 return _guarded_export(toggle,
419 f'{{ for (int32 i = 0; i < {upper}; ++i)'
420 f' Element->{field}[i] = {prop_name}[i]; }}',
421 )
422 if ue_type == "FVector":
423 if vec3_convert == "y_negate":
424 return _guarded_export(toggle,
425 f'{{ Element->{field}[0] = {prop_name}.X;'
426 f' Element->{field}[1] = -{prop_name}.Y;'
427 f' Element->{field}[2] = {prop_name}.Z; }}',
428 )
429 return _guarded_export(toggle,
430 f'{{ Element->{field}[0] = {prop_name}.X;'
431 f' Element->{field}[1] = {prop_name}.Y;'
432 f' Element->{field}[2] = {prop_name}.Z; }}',
433 )
434 if ue_type == "FLinearColor":

Callers 1

_emit_exports_blockFunction · 0.85

Calls 3

override_toggle_nameFunction · 0.90
_resolve_mjs_fieldFunction · 0.90
_guarded_exportFunction · 0.85

Tested by

no test coverage detected