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 — Covstage_wait_op+ovstage_release_op, Python.wait()(Stage.cloneblocks and raisesOvstageError;Stage.clone_asyncreturns anOperation).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#
Asynchronous Submit/Observe Model — driving the clone enqueue to completion.
Population (USD → ovstage) — ingesting USD content before cloning.
Runtime Loop — a full populate/read/update loop.