Live coding with orx-olive

By using Kotlin’s ability to run script files we can build a live coding environment. The orx-olive library simplifies the work to be done to set up a live coding environment. Code and additional documentation for the library can be found in the Github repository.

Prerequisites

Assuming you are working on an openrndr-template based project, all you have to do is enable orx-olive in the orxFeatures set in build.gradle.kts and reimport the gradle project.

Basic example

fun main() = application {
    configure {
        width = 768
        height = 576
    }
    program {
        extend(Olive<Program>())
    }
}

When running this script you will see a file called live.kts appear in src/main/kotlin. When you edit this file you will see that changes are automatically detected (after save) and that the program reloads.

Interaction with extensions

The Olive extension works well together with other extensions, but only those which are installed before the Olive extension. In the following example we see the use of Orbital in combination with Olive.

fun main() = application {
    program {
        extend(Orbital())
        extend(Olive<Program>())
    }
}

Adding script drag/drop support

A simple trick to turn your live coding host program into a versatile live coding environment is to add file drop support. With this enabled one can drag a .kts file onto the window and drop it to load the script file.

fun main() = application {
    program {
        extend(Olive<Program>()) {
            this@program.window.drop.listen {
                this.script = it.files.first()
            }
        }
    }
}

Adding persistent state

Sometimes you want to keep parts of your application persistent, that means its state will survive a script reload. In the following example we show how you can prepare the host program to contain a persistent camera device.

fun main() = application {
    oliveProgram {
        val camera by Once {
            persistent {
                VideoPlayerFFMPEG.fromDevice()
            }
        }
        camera.play()
        extend {
            camera.colorBuffer?.let {
                drawer.image(it, 0.0, 0.0, 128.0, 96.0)
            }
        }
    }
}

Note that when you create a custom host program you also have to adjust script files to include the program type. For example live.kts would become like this.

@file:Suppress("UNUSED_LAMBDA_EXPRESSION")
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.*

{ program: PersistentProgram ->
    program.apply {
        extend {
            camera.next()
            drawer.drawStyle.colorMatrix = tint(ColorRGBa.GREEN) * grayscale(0.0, 0.0, 1.0)
            camera.draw(drawer)
        }
    }
}         

edit on GitHub