Files
orx/orx-glslify/src/main/kotlin/Glslify.kt
Ricardo Matias 75d6802ea8 Add orx-glslify
2020-02-28 20:58:08 +01:00

114 lines
3.4 KiB
Kotlin

package org.openrndr.extra.glslify
import khttp.responses.Response
import mu.KotlinLogging
import java.io.ByteArrayInputStream
import java.io.File
import java.io.InputStream
const val BASE_URL = "https://registry.npmjs.org"
const val GLSLIFY_PATH = "src/main/resources/glslify"
const val IMPORT_PATT = """#pragma\sglslify:\s*(.*)\s=\s*require\('([\w\-]+)'\)"""
const val EXPORT_PATT = """#pragma\sglslify:\s*export\(([\w\-]+)\)"""
internal val shaderExtensions = arrayOf("glsl", "frag")
data class GlslifyImport(
val functionName: String,
val pkgName: String,
var exists: Boolean
)
private val logger = KotlinLogging.logger {}
fun glslify(module: String, renameFunctionTo: String? = null): String {
val (moduleName: String, shaderPath: String) = parseModule(module)
val moduleDir = File("$GLSLIFY_PATH/$moduleName")
val packageUrl = getPackageUrl(moduleName)
if (packageUrl.isNullOrEmpty()) {
throw error("[glslify] $moduleName not found")
}
if (!moduleDir.exists()) {
try {
moduleDir.mkdirs()
val response: Response = khttp.get(packageUrl, stream = true)
val tarStream: InputStream = ByteArrayInputStream(response.content)
extractGzipStream(tarStream, moduleDir)
moveFilesUp(moduleDir)
File("$moduleDir/package").deleteRecursively()
logger.trace("[glslify] $moduleName downloaded")
} catch (ex: Exception) {
logger.error(ex) { "[glslify]: There was an error getting $moduleName" }
return ""
}
} else {
logger.trace("[glslify] $moduleName already exists.. Skipping download")
}
val shaderFile: File
try {
shaderFile = shaderExtensions.map {
File("$GLSLIFY_PATH/$moduleName/$shaderPath.$it")
}.first { it.exists() }
} catch (ex: NoSuchElementException) {
logger.trace("[glslify] $moduleName: $shaderPath doesn't lead to any shader file")
return ""
}
val shader = mutableListOf<String>()
val imports = mutableListOf<GlslifyImport>()
var exportName: String? = null
shaderFile.useLines { sequence ->
for (line in sequence.iterator()) {
if (line.contains("#pragma")) {
Regex(IMPORT_PATT).find(line)?.let {
if (it.groupValues.size > 1) {
val importExists = File("$GLSLIFY_PATH/${it.groupValues[2]}").exists()
imports.add(GlslifyImport(it.groupValues[1], it.groupValues[2], importExists))
}
}
Regex(EXPORT_PATT).find(line)?.let {
if (it.groupValues.size > 1) {
exportName = it.groupValues[1]
}
}
} else {
shader.add(line)
}
}
}
val missingImports = imports.filter { !it.exists }
if (missingImports.isNotEmpty()) {
missingImports.forEach {
logger.info("Missing package: ${it.pkgName} - Import name: ${it.functionName}")
}
throw error("[glslify] Please declare the missing imports")
}
var shaderString = shader.joinToString("\n")
if (renameFunctionTo != null && exportName != null) {
shaderString = shaderString.replace( exportName!!, renameFunctionTo)
}
return shaderString
}