Add OliveProgram scriptless replacement
This commit is contained in:
@@ -35,7 +35,12 @@ enum class OliveScriptHost {
|
||||
|
||||
data class ScriptLoadedEvent(val scriptFile: String)
|
||||
|
||||
class Olive<P : Program>(val resources: Resources? = null, private var scriptless: Boolean = false) : Extension {
|
||||
enum class ScriptMode {
|
||||
KOTLIN_SCRIPT,
|
||||
OLIVE_PROGRAM
|
||||
}
|
||||
|
||||
class Olive<P : Program>(val resources: Resources? = null, private var scriptMode: ScriptMode = ScriptMode.KOTLIN_SCRIPT) : Extension {
|
||||
override var enabled: Boolean = true
|
||||
var session: Session? = null
|
||||
var scriptHost = OliveScriptHost.JSR223_REUSE
|
||||
@@ -44,12 +49,16 @@ class Olive<P : Program>(val resources: Resources? = null, private var scriptles
|
||||
|
||||
internal var scriptChange: (String) -> Unit = {}
|
||||
|
||||
var script = if (!scriptless) "src/main/kotlin/${stackRootClassName().split(".").last()}.kts"
|
||||
else "src/main/kotlin/${stackRootClassName().split(".").last()}.kt"
|
||||
var script = when (scriptMode) {
|
||||
ScriptMode.KOTLIN_SCRIPT -> "src/main/kotlin/${stackRootClassName().split(".").last()}.kts"
|
||||
else -> "src/main/kotlin/${stackRootClassName().split(".").last()}.kt"
|
||||
}
|
||||
set(value) {
|
||||
// require(scriptMode == ScriptMode.KOTLIN_SCRIPT) {
|
||||
// "can only change the script in KOTLIN_SCRIPT mode"
|
||||
// }
|
||||
field = value
|
||||
scriptChange(value)
|
||||
scriptless = value.endsWith(".kt")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,12 +124,13 @@ class Olive<P : Program>(val resources: Resources? = null, private var scriptles
|
||||
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 scriptContents = when(scriptMode) {
|
||||
ScriptMode.KOTLIN_SCRIPT -> it.readText()
|
||||
ScriptMode.OLIVE_PROGRAM -> {
|
||||
val source = it.readText()
|
||||
val programSource = extractProgram(source, programIdentifier = "oliveProgram")
|
||||
generateScript<OliveProgram>(programSource)
|
||||
}
|
||||
}
|
||||
|
||||
val futureFunc = GlobalScope.async {
|
||||
@@ -181,10 +191,5 @@ class Olive<P : Program>(val resources: Resources? = null, private var scriptles
|
||||
}
|
||||
}
|
||||
|
||||
fun program(f: Program.() -> Unit) {
|
||||
require(script.endsWith(".kt")) {
|
||||
"""program bodies are only allowed in 'scriptless' mode"""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
43
orx-olive/src/main/kotlin/OliveProgram.kt
Normal file
43
orx-olive/src/main/kotlin/OliveProgram.kt
Normal file
@@ -0,0 +1,43 @@
|
||||
package org.openrndr.extra.olive
|
||||
|
||||
import org.openrndr.ApplicationBuilder
|
||||
import org.openrndr.Program
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import kotlin.streams.toList
|
||||
|
||||
open class OliveProgram(private val sourceLocation: String) : Program() {
|
||||
val olive = extend(Olive<OliveProgram>(scriptMode = ScriptMode.OLIVE_PROGRAM)) {
|
||||
script = sourceLocation
|
||||
}
|
||||
}
|
||||
|
||||
fun stackRootClassName(thread: Thread = Thread.currentThread(), sanitize: Boolean = true): String {
|
||||
val root = Thread.currentThread().stackTrace.last()
|
||||
val rootClass = root.className
|
||||
return if (sanitize) rootClass.replace(Regex("Kt$"), "") else rootClass
|
||||
}
|
||||
|
||||
fun ApplicationBuilder.oliveProgram(init: OliveProgram.() -> Unit): OliveProgram {
|
||||
val rootClassName = stackRootClassName(sanitize = true)
|
||||
|
||||
var sourceLocation = "src/main/kotlin/$rootClassName.kt"
|
||||
val candidateFile = File(sourceLocation)
|
||||
if (!candidateFile.exists()) {
|
||||
val otherCandidates = Files.walk(Paths.get("."))
|
||||
.filter { Files.isRegularFile(it) && it.toString().endsWith("$rootClassName.kt") }.toList()
|
||||
if (otherCandidates.size == 1) {
|
||||
sourceLocation = otherCandidates.first().toString()
|
||||
} else {
|
||||
error("multiple source candidates found: $otherCandidates")
|
||||
}
|
||||
}
|
||||
program = object : OliveProgram(sourceLocation) {
|
||||
override fun setup() {
|
||||
super.setup()
|
||||
init()
|
||||
}
|
||||
}
|
||||
return program as OliveProgram
|
||||
}
|
||||
@@ -2,16 +2,19 @@ package org.openrndr.extra.olive
|
||||
|
||||
import org.openrndr.extra.kotlinparser.ProgramSource
|
||||
|
||||
fun generateScript(programSource: ProgramSource): String {
|
||||
return """
|
||||
inline fun <reified T> generateScript(programSource: ProgramSource): String {
|
||||
val script = """
|
||||
@file:Suppress("UNUSED_LAMBDA_EXPRESSION")
|
||||
|
||||
import org.openrndr.extra.olive.OliveProgram
|
||||
${programSource.imports}
|
||||
|
||||
{ program: Program ->
|
||||
{ program: ${T::class.simpleName} ->
|
||||
program.apply {
|
||||
${programSource.programLambda}
|
||||
}
|
||||
}
|
||||
"""
|
||||
println(script)
|
||||
return script
|
||||
}
|
||||
@@ -28,6 +28,7 @@ class ScriptObjectLoader(classLoader: ClassLoader? = Thread.currentThread().cont
|
||||
fun <R> safeEval(evaluation: () -> R?) = try {
|
||||
evaluation()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
throw LoadException("Cannot load script", e)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user