Writing Program extensions

The extension interface

OPENRNDR provides a simple Extension interface with which default Program behaviour can be changed.

interface Extension {
    var enabled: Boolean
    fun setup(program: Program) {}
    fun beforeDraw(drawer: Drawer, program: Program) {}
    fun afterDraw(drawer: Drawer, program: Program) {}
}

In the setup() function the extension can setup itself and hook into program events.

The beforeDraw() function is called right before the program’s draw() is executed.

The afterDraw() is called after the program’s draw() is executed.

You can enabled and disable an extension by setting the enabled boolean on the extension.

A simple extension

Presented here is the outline of a simple extension that overlays the frames per second on top of the program output.

class FPSDisplay : Extension {
    override var enabled: Boolean = true
    
    var frames = 0
    var startTime: Double = 0.0
    
    override fun setup(program: Program) {
        startTime = program.seconds
    }
    
    override fun afterDraw(drawer: Drawer, program: Program) {
        frames++
        
        drawer.isolated {
            // -- set view and projections
            drawer.view = Matrix44.IDENTITY
            drawer.ortho()
            
            drawer.text("fps: ${frames / (program.seconds - startTime)}")
        }
    }
}

Using the FPSDisplay extension from your main program would then look like this:

fun main() = application {
    program {
        extend(FPSDisplay())
    }
}

Extension application order

In the scenario in which a program has 3 extensions installed like in the snippet below.

fun setup() {
    extend(ExtensionA())
    extend(ExtensionB())
    extend(ExtensionC())
}

This resulting application order of beforeDraw and afterDraw is then as follows:

extensionA.beforeDraw()
extensionB.beforeDraw()
extensionC.beforeDraw()

program.draw()

extensionC.afterDraw()
extensionB.afterDraw()
extensionA.afterDraw()

As you can see, the afterDraw() calls are applied in reverse order, this order was decided on to help with push/pop order of transforms and styles.

edit on GitHub