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).Internal paths are rebased; external paths remain shared. Relationship targets, path values, and attribute connections that point inside the source subtree are retargeted to each clone. Paths outside the subtree are unchanged.
Change tracking. Cloned attribute values, including relationship targets, are ordinal-change-tracked. Attribute connections and scene hierarchy changes, such as parent child lists, are not.
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.