Files
orx/orx-compositor/src/main/kotlin/Compositor.kt
2018-11-07 22:25:09 +01:00

95 lines
2.6 KiB
Kotlin

package org.openrndr.extra.compositor
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.*
/**
* Layer representation
*/
class Layer internal constructor() {
var drawFunc: () -> Unit = {}
val children: MutableList<Layer> = mutableListOf()
var blendFilter: Pair<Filter, Filter.() -> Unit>? = null
val postFilters: MutableList<Pair<Filter, Filter.() -> Unit>> = mutableListOf()
fun draw(drawer: Drawer) {
val rt = RenderTarget.active
val layerTarget = renderTarget(rt.width, rt.height) {
colorBuffer()
depthBuffer()
}
drawer.isolatedWithTarget(layerTarget) {
drawer.background(ColorRGBa.TRANSPARENT)
children.reversed().forEach {
it.draw(drawer)
}
drawFunc()
}
val (tmpTargets, layerPost) = postFilters.let { filters ->
val targets = List(Math.min(filters.size, 2)) {
colorBuffer(rt.width, rt.height)
}
val result = filters.foldIndexed(layerTarget.colorBuffer(0)) { i, source, filter ->
val target = targets[i % targets.size]
filter.first.apply(filter.second)
filter.first.apply(source, target)
target
}
Pair(targets, result)
}
val lblend = blendFilter
if (lblend == null) {
drawer.isolatedWithTarget(rt) {
drawer.image(layerPost, layerPost.bounds, drawer.bounds)
}
} else {
lblend.first.apply(lblend.second)
lblend.first.apply(arrayOf(rt.colorBuffer(0), layerPost), rt.colorBuffer(0))
}
tmpTargets.forEach {
it.destroy()
}
layerTarget.colorBuffer(0).destroy()
layerTarget.depthBuffer?.destroy()
layerTarget.detachColorBuffers()
layerTarget.detachDepthBuffer()
layerTarget.destroy()
}
}
/**
* create a layer within the composition
*/
fun Layer.layer(function: Layer.() -> Unit) {
children.add(Layer().apply { function() })
}
fun Layer.draw(function: () -> Unit) {
drawFunc = function
}
fun <F : Filter> Layer.post(filter: F, configure: F.() -> Unit = {}) {
postFilters.add(Pair(filter as Filter, configure as Filter.() -> Unit))
}
fun <F : Filter> Layer.blend(filter: F, configure: F.() -> Unit = {}) {
blendFilter = Pair(filter as Filter, configure as Filter.() -> Unit)
}
/**
* create a layered composition
*/
fun compose(function: Layer.() -> Unit): Layer {
val root = Layer()
root.function()
return root
}