Files
orx/orx-parameters/src/jvmMain/kotlin/Annotations.kt
2023-04-11 14:48:56 +02:00

165 lines
6.1 KiB
Kotlin

package org.openrndr.extra.parameters
import org.openrndr.math.Vector2
import kotlin.reflect.KCallable
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.KVisibility
import kotlin.reflect.full.declaredMemberFunctions
import kotlin.reflect.full.memberProperties
fun ParameterType.Companion.forParameterAnnotationClass(annotation: Annotation): ParameterType =
ParameterType.values().find { it.annotationClass == annotation.annotationClass } ?: error("no type for $annotation")
val ParameterType.Companion.parameterAnnotationClasses get() = ParameterType.values().map { it.annotationClass }
fun Any.listParameters(): List<Parameter> {
return (this::class.memberProperties.filter { property ->
!property.isConst &&
property is KMutableProperty1<*, *> &&
property.visibility == KVisibility.PUBLIC &&
property.annotations.map { it.annotationClass }.intersect(ParameterType.parameterAnnotationClasses.toSet()).isNotEmpty()
}.map { property ->
val annotations = property.annotations.filter { it.annotationClass in ParameterType.parameterAnnotationClasses }
var intRange: IntRange? = null
var doubleRange: ClosedRange<Double>? = null
var sizeRange: ClosedRange<Int>? = null
var order: Int = Int.MAX_VALUE
var label = ""
var precision: Int? = null
var type: ParameterType? = null
var vectorRange = Pair(Vector2(-1.0, -1.0), Vector2(1.0, 1.0))
var invertY: Boolean? = null
var showVector: Boolean? = null
var absolutePath: Boolean? = null
var pathContext: String? = null
var pathExtensions: Array<String>? = null
var pathIsDirectory: Boolean? = null
for (it in annotations) {
type = ParameterType.forParameterAnnotationClass(it)
when (it) {
is BooleanParameter -> {
label = it.label
order = it.order
}
is DoubleParameter -> {
label = it.label
doubleRange = it.low..it.high
precision = it.precision
order = it.order
}
is IntParameter -> {
label = it.label
intRange = it.low..it.high
order = it.order
}
is TextParameter -> {
label = it.label
order = it.order
}
is ColorParameter -> {
label = it.label
order = it.order
}
is XYParameter -> {
label = it.label
order = it.order
vectorRange = Pair(Vector2(it.minX, it.minY), Vector2(it.maxX, it.maxY))
precision = it.precision
invertY = it.invertY
showVector = it.showVector
}
is DoubleListParameter -> {
label = it.label
order = it.order
doubleRange = it.low..it.high
precision = it.precision
sizeRange = it.minimumListLength..it.maximumListLength
}
is Vector2Parameter -> {
label = it.label
order = it.order
doubleRange = it.min..it.max
precision = it.precision
}
is Vector3Parameter -> {
label = it.label
order = it.order
doubleRange = it.min..it.max
precision = it.precision
}
is Vector4Parameter -> {
label = it.label
order = it.order
doubleRange = it.min..it.max
precision = it.precision
}
is OptionParameter -> {
label = it.label
order = it.order
}
is PathParameter -> {
label = it.label
absolutePath = it.absolute
pathContext = it.context
pathExtensions = it.extensions
pathIsDirectory = it.directory
}
}
}
@Suppress("UNCHECKED_CAST")
Parameter(
parameterType = type ?: error("no type"),
property = property as KMutableProperty1<out Any, Any?>,
function = null,
label = label,
doubleRange = doubleRange,
vectorRange = vectorRange,
sizeRange = sizeRange,
intRange = intRange,
precision = precision,
showVector = showVector,
invertY = invertY,
absolutePath = absolutePath,
pathContext = pathContext,
pathExtensions = pathExtensions,
pathIsDirectory = pathIsDirectory,
order = order,
)
} + this::class.declaredMemberFunctions.filter {
it.findAnnotation<ActionParameter>() != null
}.map {
val annotation = it.findAnnotation<ActionParameter>()!!
val label = annotation.label
val order = annotation.order
val type = ParameterType.Action
@Suppress("UNCHECKED_CAST")
Parameter(
type,
property = null,
function = it as KCallable<Unit>,
label = label,
doubleRange = null,
intRange = null,
sizeRange = null,
vectorRange = null,
precision = null,
showVector = null,
invertY = null,
absolutePath = null,
pathContext = null,
pathExtensions = null,
pathIsDirectory = null,
order = order
)
}).sortedBy { it.order }
}
actual fun Any.title() = this::class.findAnnotation<Description>()?.title
actual fun Any.description(): String? = this::class.findAnnotation<Description>()?.description