[orx-compositor] Add explicit contract checks for lambdas with callsInPlace in layer-related functions

This commit is contained in:
Edwin Jakobs
2025-08-20 21:12:50 +02:00
parent ad31a9ab02
commit af64323229

View File

@@ -8,6 +8,9 @@ import org.openrndr.extra.fx.blend.SourceIn
import org.openrndr.extra.fx.blend.SourceOut
import org.openrndr.extra.parameters.BooleanParameter
import org.openrndr.extra.parameters.Description
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmRecord
@@ -200,24 +203,50 @@ open class Layer internal constructor(
}
/**
* create a layer within the composition
* Creates a new layer within the current layer, allowing for hierarchical composition of drawings.
* The newly created layer inherits properties such as color type and multisample from the parent layer
* unless explicitly overridden. A custom lambda function can be applied to configure the new layer.
*
* @param colorType The color type for the new layer. Defaults to the color type of the parent layer.
* @param multisample Specifies the multisampling mode for the new layer to control antialiasing.
* Defaults to [BufferMultisample.Disabled].
* @param function A configuration block where the properties and behavior of the new layer
* can be defined.
* @return The newly created layer, which is also added as a child of the parent layer.
*/
@OptIn(ExperimentalContracts::class)
fun Layer.layer(
colorType: ColorType = this.colorType,
multisample: BufferMultisample = BufferMultisample.Disabled,
function: Layer.() -> Unit
): Layer {
contract {
callsInPlace(function, InvocationKind.EXACTLY_ONCE)
}
val layer = Layer(LayerType.LAYER, multisample).apply { function() }
layer.colorType = colorType
children.add(layer)
return layer
}
/**
* Creates a new `Layer` of type `ASIDE` as a child of the current layer, applies the specified function
* to configure it, and returns the created layer.
*
* @param colorType The color type for the new layer. Defaults to the color type of the parent layer.
* @param multisample Multisampling configuration for the new layer. Defaults to `BufferMultisample.Disabled`.
* @param function Configuration function applied to the newly created layer.
* @return The newly created `Layer` of type `ASIDE`.
*/
@OptIn(ExperimentalContracts::class)
fun Layer.aside(
colorType: ColorType = this.colorType,
multisample: BufferMultisample = BufferMultisample.Disabled,
function: Layer.() -> Unit
): Layer {
contract {
callsInPlace(function, InvocationKind.EXACTLY_ONCE)
}
val layer = Layer(LayerType.ASIDE, multisample).apply { function() }
layer.colorType = colorType
children.add(layer)
@@ -348,9 +377,17 @@ class Composite(val session: Session?) : Layer(LayerType.LAYER), AutoCloseable {
}
/**
* create a layered composition
* Creates a `Composite` object and allows configuration of its layers and effects within the provided `function`.
*
* @param function the lambda function used to configure the `Composite`. It is invoked with the `Composite` instance as the receiver.
* @return the configured `Composite` object.
*/
@OptIn(ExperimentalContracts::class)
fun compose(function: Composite.() -> Unit): Composite {
contract {
callsInPlace(function, InvocationKind.EXACTLY_ONCE)
}
val session = Session.active.fork()
val root = Composite(session)
root.function()