compose/remote/remote-creation/doc/guides/LOOP_GUIDE.md
The loop mechanism in RemoteCompose allows you to repeat a sequence of operations on the player side. This is highly efficient for drawing repetitive elements (like clock ticks, grid lines, or multiple particles) without sending each individual command over the wire.
from, step, and until parameters can be dynamic expressions (Remote IDs).The RemoteComposeContextAndroid provides a convenient loop extension.
loop(from = 0f, step = 1f, until = 12f) { index ->
// 'index' is an RFloat representing the current iteration value
save {
rotate(index * 30f, centerX, centerY)
drawLine(centerX, centerY - 100f, centerX, centerY - 120f)
}
}
from: The starting value of the index.step: The increment added to the index after each iteration.until: The loop continues as long as index < until.index: The closure provides the index as an RFloat, which you can use in math expressions.In Java, you use the RemoteComposeWriter directly.
float indexVar = rc.startLoopVar(0f, 1f, 12f);
// Drawing operations using indexVar
rc.save();
rc.rotate(rc.floatExpression(indexVar, 30f, MUL), cx, cy);
rc.drawLine(cx, cy - 100, cx, cy - 120);
rc.restore();
rc.endLoop();
Alternatively, using a functional interface:
rc.loop(indexId, 0f, 1f, 12f, () -> {
// operations
});
RemoteComposeWriter.java)When you call startLoop, the writer emits a LOOP_START opcode into the WireBuffer along with:
indexId: The ID of the variable that will store the current index.from, step, until: The loop range parameters.Operations following LOOP_START are buffered as children of the loop until an endLoop (which closes the container) is encountered.
LoopOperation.java)On the player side, the LoopOperation acts as a container for its child operations.
During the paint pass:
from, step, and until.for loop.RemoteContext using loadFloat(mIndexVariableId, i).apply() on them.// Draw 60 minute ticks
loop(0f, 1f, 60f) { i ->
val angle = i * 6f // 360 / 60
save {
rotate(angle, cx, cy)
val length = ifElse(i % 5f, 10f, 20f) // Longer ticks every 5 mins
drawLine(cx, cy - radius, cx, cy - radius + length)
}
}
val spacing = 50f
loop(0f, spacing, width) { x ->
drawLine(x, 0f, x, height)
}
loop(0f, spacing, height) { y ->
drawLine(0f, y, width, y)
}