Cloning Subtrees#

ovstage_clone copies the subtree under a source prim to one or more new target paths in a single ordinal-keyed call. Passing several targets in one call is the multi-environment pattern: stamp out N copies of a prototype subtree — for example, one scene or robot per reinforcement-learning environment — in a single enqueue.

Note

The clone API is pre-release and provisional (“Draft — API in flux”). Treat the exact symbols and argument ordering as subject to change. Clone operates on populated content (see Population (USD → ovstage)).

Cloning to Multiple Targets#

Like a write, clone carries an ordinal and is sealed by the write floor. Choose an ordinal above the current floor, then advance the floor afterward to make the clones readable:

# The multi-environment pattern: stamp out N copies of a prototype
# (e.g. one scene/robot per RL environment) in a single call. Clone is
# an ordinal-keyed write (pick an ordinal above the current write
# floor) that copies the source subtree's attributes verbatim; the
# source must exist and each target must not. clone() blocks and
# raises OvstageError on failure.
stage.clone("/World/A", ["/World/A_env0", "/World/A_env1"], ordinal=3)
stage.advance_write_floor(ordinal=3).wait()  # seal the clones so they're readable
print("cloned /World/A -> A_env0, A_env1")
// One call clones the subtree under a source prim to several new targets --
// the multi-environment pattern (N copies of a prototype, e.g. one scene
// per RL environment). Clone is an ordinal-keyed write: pick an ordinal
// above the write floor (ordinal 1 was sealed above, so clone at 2). The
// source must exist; each target must not already exist.
const ovx_string_t cloneTargets[] = { literal_to_ovx_string("/World/A_env0"),
                                      literal_to_ovx_string("/World/A_env1") };
enq = ovstage_clone(stage, literal_to_ovx_string("/World/A"), cloneTargets, 2, /*ordinal*/ 2);
waitOp(stage, enq, "clone");
writeFloor.ordinal = 2; // seal the clones so they're readable
enq = ovstage_advance_write_floor(stage, &writeFloor);
waitOp(stage, enq, "advance_write_floor");
std::printf("cloned /World/A -> A_env0, A_env1\n");

Semantics#

  • Create-only, all-or-nothing. The source must already exist and every target must be new. A batch containing any pre-existing target clones nothing.

  • Ordinal-keyed. Pick an ordinal strictly above the write floor (and above the seal of every attribute the clone reproduces); advance the floor afterward to read the clones.

  • Asynchronous. Clone is an enqueue returning an op_index; nothing exists until you observe it — C ovstage_wait_op + ovstage_release_op, Python .wait() (Stage.clone blocks and raises OvstageError; Stage.clone_async returns an Operation).

  • Relationships are copied verbatim, not retargeted. Bindings to a shared scope outside the subtree still resolve; targets inside the subtree point at the source’s copies.

  • Change tracking. Only value attributes are change-tracked; relationship changes and parent child-list changes are not ordinal-change-tracked.

Where to Go Next#