Add 'scriptless' mode to orx-olive
This commit is contained in:
@@ -10,12 +10,14 @@ sourceSets {
|
||||
|
||||
dependencies {
|
||||
implementation project(":orx-file-watcher")
|
||||
|
||||
implementation project(":orx-kotlin-parser")
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-scripting-jvm:$kotlinVersion"
|
||||
implementation "org.jetbrains.kotlin:kotlin-scripting-jvm-host:$kotlinVersion"
|
||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||
implementation "org.jetbrains.kotlin:kotlin-scripting-jsr223:$kotlinVersion"
|
||||
|
||||
|
||||
demoImplementation(project(":orx-camera"))
|
||||
demoImplementation("org.openrndr:openrndr-core:$openrndrVersion")
|
||||
demoImplementation("org.openrndr:openrndr-extensions:$openrndrVersion")
|
||||
|
||||
29
orx-olive/src/demo/kotlin/DemoOliveScriptless01.kt
Normal file
29
orx-olive/src/demo/kotlin/DemoOliveScriptless01.kt
Normal file
@@ -0,0 +1,29 @@
|
||||
import org.openrndr.Program
|
||||
import org.openrndr.application
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.extra.olive.Olive
|
||||
import org.openrndr.math.IntVector2
|
||||
|
||||
fun main() {
|
||||
application {
|
||||
configure {
|
||||
position = IntVector2(3440 / 2 + 200, 360)
|
||||
width = 1280
|
||||
height = 720
|
||||
}
|
||||
program {
|
||||
extend(Olive<Program>()) {
|
||||
script = "orx-olive/src/demo/kotlin/DemoOliveScriptless01.kt"
|
||||
program {
|
||||
extend {
|
||||
drawer.background(ColorRGBa.PINK)
|
||||
drawer.circle(width /2.0, height / 2.0, 300.0 + Math.cos(seconds)*100.0)
|
||||
|
||||
drawer.fill = ColorRGBa.RED
|
||||
drawer.circle(mouse.position, 100.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import org.openrndr.Program
|
||||
import org.openrndr.draw.Session
|
||||
import org.openrndr.events.Event
|
||||
import org.openrndr.exceptions.stackRootClassName
|
||||
import org.openrndr.extra.kotlinparser.extractProgram
|
||||
import org.openrndr.launch
|
||||
import org.operndr.extras.filewatcher.stop
|
||||
import org.operndr.extras.filewatcher.triggerChange
|
||||
@@ -34,7 +35,7 @@ enum class OliveScriptHost {
|
||||
|
||||
data class ScriptLoadedEvent(val scriptFile: String)
|
||||
|
||||
class Olive<P : Program>(val resources: Resources? = null) : Extension {
|
||||
class Olive<P : Program>(val resources: Resources? = null, private var scriptless: Boolean = false) : Extension {
|
||||
override var enabled: Boolean = true
|
||||
var session: Session? = null
|
||||
var scriptHost = OliveScriptHost.JSR223_REUSE
|
||||
@@ -43,10 +44,12 @@ class Olive<P : Program>(val resources: Resources? = null) : Extension {
|
||||
|
||||
internal var scriptChange: (String) -> Unit = {}
|
||||
|
||||
var script = "src/main/kotlin/${stackRootClassName().split(".").last()}.kts"
|
||||
var script = if (!scriptless) "src/main/kotlin/${stackRootClassName().split(".").last()}.kts"
|
||||
else "src/main/kotlin/${stackRootClassName().split(".").last()}.kt"
|
||||
set(value) {
|
||||
field = value
|
||||
scriptChange(value)
|
||||
scriptless = value.endsWith(".kt")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,13 +114,21 @@ class Olive<P : Program>(val resources: Resources? = null) : Extension {
|
||||
watcher = program.watchFile(File(script)) {
|
||||
try {
|
||||
logger.info("change detected, reloading script")
|
||||
|
||||
val scriptContents = if (!scriptless) {
|
||||
it.readText()
|
||||
} else {
|
||||
val source = it.readText()
|
||||
val programSource = extractProgram(source)
|
||||
generateScript(programSource)
|
||||
}
|
||||
|
||||
val futureFunc = GlobalScope.async {
|
||||
val start = System.currentTimeMillis()
|
||||
|
||||
val loadedFunction = when (scriptHost) {
|
||||
OliveScriptHost.JSR223_REUSE -> loadFromScript(it, jsr233ObjectLoader!!)
|
||||
OliveScriptHost.JSR223 -> loadFromScript(it)
|
||||
OliveScriptHost.KOTLIN_SCRIPT -> loadFromScriptKSH<P.() -> Unit>(it)
|
||||
OliveScriptHost.JSR223_REUSE -> loadFromScriptContents(scriptContents, jsr233ObjectLoader!!)
|
||||
OliveScriptHost.JSR223 -> loadFromScriptContents(scriptContents)
|
||||
OliveScriptHost.KOTLIN_SCRIPT -> loadFromScriptContentsKSH<P.() -> Unit>(scriptContents)
|
||||
}
|
||||
|
||||
val end = System.currentTimeMillis()
|
||||
@@ -140,7 +151,6 @@ class Olive<P : Program>(val resources: Resources? = null) : Extension {
|
||||
Unit
|
||||
}
|
||||
Unit
|
||||
|
||||
} catch (e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
@@ -170,4 +180,11 @@ class Olive<P : Program>(val resources: Resources? = null) : Extension {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun program(f: Program.() -> Unit) {
|
||||
require(script.endsWith(".kt")) {
|
||||
"""program bodies are only allowed in 'scriptless' mode"""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
17
orx-olive/src/main/kotlin/ScriptGenerator.kt
Normal file
17
orx-olive/src/main/kotlin/ScriptGenerator.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package org.openrndr.extra.olive
|
||||
|
||||
import org.openrndr.extra.kotlinparser.ProgramSource
|
||||
|
||||
fun generateScript(programSource: ProgramSource): String {
|
||||
return """
|
||||
@file:Suppress("UNUSED_LAMBDA_EXPRESSION")
|
||||
|
||||
${programSource.imports}
|
||||
|
||||
{ program: Program ->
|
||||
program.apply {
|
||||
${programSource.programLambda}
|
||||
}
|
||||
}
|
||||
"""
|
||||
}
|
||||
@@ -67,3 +67,10 @@ inline fun <reified T : Any> loadFromScript(fileOrUrl: String, loader: ScriptObj
|
||||
*/
|
||||
inline fun <reified T : Any> loadFromScript(file: File, loader: ScriptObjectLoader = ScriptObjectLoader()): T =
|
||||
loader.load(file.readText())
|
||||
|
||||
|
||||
/**
|
||||
* Load an object from script file
|
||||
*/
|
||||
inline fun <reified T : Any> loadFromScriptContents(contents:String, loader: ScriptObjectLoader = ScriptObjectLoader()): T =
|
||||
loader.load(contents)
|
||||
|
||||
@@ -30,10 +30,10 @@ fun <T> loadFromScriptKSH(
|
||||
}
|
||||
|
||||
}
|
||||
): T = loadFromScriptKSH(script.readText(), host, body)
|
||||
): T = loadFromScriptContentsKSH(script.readText(), host, body)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> loadFromScriptKSH(
|
||||
fun <T> loadFromScriptContentsKSH(
|
||||
script: String,
|
||||
host: BasicScriptingHost = BasicJvmScriptingHost(),
|
||||
body: ScriptCompilationConfiguration.Builder.() -> Unit = {
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import org.amshove.kluent.`should be equal to`
|
||||
import org.openrndr.extra.olive.ScriptObjectLoader
|
||||
import org.openrndr.extra.olive.loadFromScript
|
||||
import org.openrndr.extra.olive.loadFromScriptKSH
|
||||
import org.openrndr.extra.olive.loadFromScriptContentsKSH
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
object TestLoadScriptKSH : Spek({
|
||||
|
||||
describe("some script") {
|
||||
val number = loadFromScriptKSH<Int>("5")
|
||||
val number = loadFromScriptContentsKSH<Int>("5")
|
||||
|
||||
it("should evaluate properly") {
|
||||
number `should be equal to` 5
|
||||
|
||||
Reference in New Issue
Block a user