From 9212d75033870cc12df31d34c97b3c14e857cfc6 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Wed, 12 Feb 2020 18:12:53 +0100 Subject: [PATCH] Add Layer.enabled and make it @BooleanParameter annotated --- orx-compositor/build.gradle | 3 + orx-compositor/src/main/kotlin/Compositor.kt | 326 ++++++++++--------- 2 files changed, 180 insertions(+), 149 deletions(-) create mode 100644 orx-compositor/build.gradle diff --git a/orx-compositor/build.gradle b/orx-compositor/build.gradle new file mode 100644 index 00000000..fff268b1 --- /dev/null +++ b/orx-compositor/build.gradle @@ -0,0 +1,3 @@ +dependencies { + compile project(":orx-parameters") +} \ No newline at end of file diff --git a/orx-compositor/src/main/kotlin/Compositor.kt b/orx-compositor/src/main/kotlin/Compositor.kt index 51e36ccb..e490d8ec 100644 --- a/orx-compositor/src/main/kotlin/Compositor.kt +++ b/orx-compositor/src/main/kotlin/Compositor.kt @@ -1,150 +1,178 @@ -package org.openrndr.extra.compositor - -import org.openrndr.color.ColorRGBa -import org.openrndr.draw.* -import org.openrndr.math.Matrix44 - - -private val postBufferCache = mutableListOf() - -fun RenderTarget.deepDestroy() { - val cbcopy = colorBuffers.map { it} - val dbcopy = depthBuffer - detachDepthBuffer() - detachColorBuffers() - cbcopy.forEach { - it.destroy() - } - dbcopy?.destroy() - destroy() -} - -/** - * A single layer representation - */ -class Layer internal constructor() { - var drawFunc: () -> Unit = {} - val children: MutableList = mutableListOf() - var blendFilter: Pair Unit>? = null - val postFilters: MutableList Unit>> = mutableListOf() - - var clearColor: ColorRGBa? = ColorRGBa.TRANSPARENT - private var layerTarget:RenderTarget? = null - - /** - * draw the layer - */ - fun draw(drawer: Drawer) { - val rt = RenderTarget.active - - val llt = layerTarget - if (llt == null || (llt.width != rt.width || llt.height != rt.height)) { - layerTarget?.deepDestroy() - layerTarget = renderTarget(rt.width, rt.height) { - colorBuffer() - depthBuffer() - } - layerTarget?.let { - drawer.withTarget(it) { - drawer.background(ColorRGBa.TRANSPARENT) - } - } - } - - layerTarget?.let { target -> - drawer.isolatedWithTarget(target) { - clearColor?.let { - drawer.background(it) - } - drawFunc() - children.forEach { - it.draw(drawer) - } - } - - if (postFilters.size > 0) { - val sizeMismatch = if (postBufferCache.isNotEmpty()) { - postBufferCache[0].width != rt.width || postBufferCache[0].height != rt.height - } else { - false - } - - if (sizeMismatch) { - postBufferCache.forEach { it.destroy() } - postBufferCache.clear() - } - - if (postBufferCache.isEmpty()) { - postBufferCache += colorBuffer(rt.width, rt.height).apply { - Session.active.untrack(this) - } - postBufferCache += colorBuffer(rt.width, rt.height).apply { - Session.active.untrack(this) - } - } - } - - val layerPost = postFilters.let { filters -> - val targets = postBufferCache - val result = filters.foldIndexed(target.colorBuffer(0)) { i, source, filter -> - val target = targets[i % targets.size] - filter.first.apply(filter.second) - filter.first.apply(source, target) - target - } - result - } - - val lblend = blendFilter - if (lblend == null) { - drawer.isolatedWithTarget(rt) { - //drawer.ortho(rt) - drawer.ortho() - drawer.view = Matrix44.IDENTITY - drawer.model = Matrix44.IDENTITY - drawer.image(layerPost, layerPost.bounds, drawer.bounds) - } - } else { - lblend.first.apply(lblend.second) - lblend.first.apply(arrayOf(rt.colorBuffer(0), layerPost), rt.colorBuffer(0)) - } - } - } -} - -/** - * create a layer within the composition - */ -fun Layer.layer(function: Layer.() -> Unit) { - children.add(Layer().apply { function() }) -} - -/** - * set the draw contents of the layer - */ -fun Layer.draw(function: () -> Unit) { - drawFunc = function -} - -/** - * add a post-processing filter to the layer - */ -fun Layer.post(filter: F, configure: F.() -> Unit = {}) { - postFilters.add(Pair(filter as Filter, configure as Filter.() -> Unit)) -} - -/** - * add a blend filter to the layer - */ -fun 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 +package org.openrndr.extra.compositor + +import org.openrndr.Extension +import org.openrndr.Program +import org.openrndr.color.ColorRGBa +import org.openrndr.draw.* +import org.openrndr.extra.parameters.BooleanParameter +import org.openrndr.extra.parameters.Description +import org.openrndr.math.Matrix44 + + +private val postBufferCache = mutableListOf() + +fun RenderTarget.deepDestroy() { + val cbcopy = colorBuffers.map { it} + val dbcopy = depthBuffer + detachDepthBuffer() + detachColorBuffers() + cbcopy.forEach { + it.destroy() + } + dbcopy?.destroy() + destroy() +} + +/** + * A single layer representation + */ +@Description("Layer") +class Layer internal constructor() { + var drawFunc: () -> Unit = {} + val children: MutableList = mutableListOf() + var blendFilter: Pair Unit>? = null + val postFilters: MutableList Unit>> = mutableListOf() + + @BooleanParameter("enabled") + var enabled = true + var clearColor: ColorRGBa? = ColorRGBa.TRANSPARENT + private var layerTarget:RenderTarget? = null + + /** + * draw the layer + */ + fun draw(drawer: Drawer) { + + if (!enabled) { + return + } + + val rt = RenderTarget.active + + val llt = layerTarget + if (llt == null || (llt.width != rt.width || llt.height != rt.height)) { + layerTarget?.deepDestroy() + layerTarget = renderTarget(rt.width, rt.height) { + colorBuffer() + depthBuffer() + } + layerTarget?.let { + drawer.withTarget(it) { + drawer.background(ColorRGBa.TRANSPARENT) + } + } + } + + layerTarget?.let { target -> + drawer.isolatedWithTarget(target) { + clearColor?.let { + drawer.background(it) + } + drawFunc() + children.forEach { + it.draw(drawer) + } + } + + if (postFilters.size > 0) { + val sizeMismatch = if (postBufferCache.isNotEmpty()) { + postBufferCache[0].width != rt.width || postBufferCache[0].height != rt.height + } else { + false + } + + if (sizeMismatch) { + postBufferCache.forEach { it.destroy() } + postBufferCache.clear() + } + + if (postBufferCache.isEmpty()) { + postBufferCache += colorBuffer(rt.width, rt.height).apply { + Session.active.untrack(this) + } + postBufferCache += colorBuffer(rt.width, rt.height).apply { + Session.active.untrack(this) + } + } + } + + val layerPost = postFilters.let { filters -> + val targets = postBufferCache + val result = filters.foldIndexed(target.colorBuffer(0)) { i, source, filter -> + val target = targets[i % targets.size] + filter.first.apply(filter.second) + filter.first.apply(source, target) + target + } + result + } + + val lblend = blendFilter + if (lblend == null) { + drawer.isolatedWithTarget(rt) { + //drawer.ortho(rt) + drawer.ortho() + drawer.view = Matrix44.IDENTITY + drawer.model = Matrix44.IDENTITY + drawer.image(layerPost, layerPost.bounds, drawer.bounds) + } + } else { + lblend.first.apply(lblend.second) + lblend.first.apply(arrayOf(rt.colorBuffer(0), layerPost), rt.colorBuffer(0)) + } + } + } +} + +/** + * create a layer within the composition + */ +fun Layer.layer(function: Layer.() -> Unit) : Layer { + val layer = Layer().apply { function() } + children.add(layer) + return layer +} + +/** + * set the draw contents of the layer + */ +fun Layer.draw(function: () -> Unit) { + drawFunc = function +} + +/** + * add a post-processing filter to the layer + */ +fun Layer.post(filter: F, configure: F.() -> Unit = {}) : F { + postFilters.add(Pair(filter as Filter, configure as Filter.() -> Unit)) + return filter +} + +/** + * add a blend filter to the layer + */ +fun Layer.blend(filter: F, configure: F.() -> Unit = {}) : F { + blendFilter = Pair(filter as Filter, configure as Filter.() -> Unit) + return filter +} + +/** + * create a layered composition + */ +fun compose(function: Layer.() -> Unit): Layer { + val root = Layer() + root.function() + return root +} + +class Compositor: Extension { + override var enabled: Boolean = true + var composite = Layer() + + override fun afterDraw(drawer: Drawer, program: Program) { + drawer.isolated { + drawer.defaults() + composite.draw(drawer) + } + } } \ No newline at end of file