Add orx-parameters
This commit is contained in:
@@ -81,7 +81,7 @@ allprojects {
|
|||||||
compile "org.openrndr:openrndr-shape:$openrndrVersion"
|
compile "org.openrndr:openrndr-shape:$openrndrVersion"
|
||||||
compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.2'
|
compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: '1.3.2'
|
||||||
testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
|
testImplementation "org.spekframework.spek2:spek-dsl-jvm:$spekVersion"
|
||||||
testImplementation "org.amshove.kluent:kluent:1.53"
|
testImplementation "org.amshove.kluent:kluent:1.59"
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
|
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
|
||||||
testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
|
testRuntimeOnly "org.spekframework.spek2:spek-runner-junit5:$spekVersion"
|
||||||
testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
testRuntimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||||
|
|||||||
3
orx-fx/build.gradle
Normal file
3
orx-fx/build.gradle
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dependencies {
|
||||||
|
compile project(":orx-parameters")
|
||||||
|
}
|
||||||
41
orx-parameters/README.md
Normal file
41
orx-parameters/README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# orx-parameters
|
||||||
|
|
||||||
|
A collection of annotations and tools that are used to turn Kotlin properties into introspectable parameters. Parameters
|
||||||
|
are highly suitable for automatically generating user interfaces, but note that this is _not_ what `orx-parameters` does.
|
||||||
|
|
||||||
|
Currently orx-parameters supplies the following annotations:
|
||||||
|
|
||||||
|
- `DoubleParameter`
|
||||||
|
- `IntParameter`
|
||||||
|
- `DoubleParameter`
|
||||||
|
|
||||||
|
## Annotation application
|
||||||
|
|
||||||
|
Annotations can be applied to a properties inside a class or object class.
|
||||||
|
|
||||||
|
````kotlin
|
||||||
|
val foo = object {
|
||||||
|
@DoubleParameter("a double scalar", 0.0, 1.0, order = 0)
|
||||||
|
var d = 1.0
|
||||||
|
|
||||||
|
@IntParameter("an integer scalar", 1, 100, order = 1)
|
||||||
|
var i = 1
|
||||||
|
|
||||||
|
@BooleanParameter("a boolean parameter", order = 2)
|
||||||
|
var b = false
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
## Querying parameters
|
||||||
|
|
||||||
|
Given an instance of an annotated class we can list the parameters using the extension method
|
||||||
|
`Any.listParameters()` of our previously declared object `foo`
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import org.openrndr.extra.parameters.listParameters
|
||||||
|
|
||||||
|
// ..
|
||||||
|
|
||||||
|
val parameters = foo.listParameters()
|
||||||
|
```
|
||||||
|
|
||||||
3
orx-parameters/build.gradle
Normal file
3
orx-parameters/build.gradle
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||||
|
}
|
||||||
102
orx-parameters/src/main/kotlin/Annotations.kt
Normal file
102
orx-parameters/src/main/kotlin/Annotations.kt
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package org.openrndr.extra.parameters
|
||||||
|
|
||||||
|
import kotlin.reflect.KMutableProperty1
|
||||||
|
import kotlin.reflect.KVisibility
|
||||||
|
import kotlin.reflect.full.declaredMemberProperties
|
||||||
|
import kotlin.reflect.full.findAnnotation
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class Description(val description: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DoubleParameter annotation for a double precision Filter parameter
|
||||||
|
* @property label a short description of the parameter
|
||||||
|
* @property low the lowest value this parameter should be assigned
|
||||||
|
* @property high the highest value this parameter should be assigned
|
||||||
|
* @property precision a hint for precision in user interfaces
|
||||||
|
* @property order hint for where to place the parameter in user interfaces
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class DoubleParameter(val label: String, val low: Double, val high: Double, val precision: Int = 3, val order: Int = Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IntParameter annotation for an integer Filter parameter
|
||||||
|
* @property label a short description of the parameter
|
||||||
|
* @property low the lowest value this parameter should be assigned
|
||||||
|
* @property high the highest value this parameter should be assigned
|
||||||
|
* @property order hint for where to place the parameter in user interfaces
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class IntParameter(val label: String, val low: Int, val high: Int, val order: Int = Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BooleanParameter annotation for an integer Filter parameter
|
||||||
|
* @property label a short description of the parameter
|
||||||
|
* @property order hint for where to place the parameter in user interfaces
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
annotation class BooleanParameter(val label: String, val order: Int = Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameter summary class. This is used by [listParameters] as a way to report parameters in
|
||||||
|
* a unified form.
|
||||||
|
* @property property the property that received any of the parameter annotations
|
||||||
|
* [BooleanParameter], [IntParameter], or [DoubleParameter]
|
||||||
|
* @property label a label that describes the property
|
||||||
|
* @property doubleRange a floating point based range in case [DoubleParameter] is used
|
||||||
|
* @property intRange an integer range in case [IntParameter] is used
|
||||||
|
* @property precision a precision hint in case a [DoubleParameter] annotation is used
|
||||||
|
* @property order a hint for where in the ui this parameter is placed, lower value means higher priority
|
||||||
|
*/
|
||||||
|
class Parameter(
|
||||||
|
val property: KMutableProperty1<out Any, Any?>,
|
||||||
|
val label: String,
|
||||||
|
val doubleRange: ClosedRange<Double>?,
|
||||||
|
val intRange: IntRange?,
|
||||||
|
val precision: Int?,
|
||||||
|
val order: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all parameters, (public var properties with a parameter annotation)
|
||||||
|
*/
|
||||||
|
fun Any.listParameters(): List<Parameter> {
|
||||||
|
return this::class.declaredMemberProperties.filter {
|
||||||
|
!it.isConst &&
|
||||||
|
it.visibility == KVisibility.PUBLIC &&
|
||||||
|
(it.findAnnotation<BooleanParameter>() != null ||
|
||||||
|
it.findAnnotation<IntParameter>() != null ||
|
||||||
|
it.findAnnotation<DoubleParameter>() != null)
|
||||||
|
}.map {
|
||||||
|
val annotations = listOf(it.findAnnotation<BooleanParameter>(), it.findAnnotation<IntParameter>(), it.findAnnotation<DoubleParameter>()).filterNotNull()
|
||||||
|
var intRange: IntRange? = null
|
||||||
|
var doubleRange: ClosedRange<Double>? = null
|
||||||
|
var order: Int = Integer.MAX_VALUE
|
||||||
|
var label: String = ""
|
||||||
|
var precision: Int? = null
|
||||||
|
|
||||||
|
annotations.forEach {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Parameter(it as KMutableProperty1<out Any, Any?>, label, doubleRange, intRange, precision, order)
|
||||||
|
}.sortedBy { it.order }
|
||||||
|
}
|
||||||
46
orx-parameters/src/test/kotlin/TestAnnotations.kt
Normal file
46
orx-parameters/src/test/kotlin/TestAnnotations.kt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import org.amshove.kluent.`should be equal to`
|
||||||
|
import org.amshove.kluent.shouldBeInRange
|
||||||
|
import org.openrndr.extra.parameters.BooleanParameter
|
||||||
|
import org.openrndr.extra.parameters.DoubleParameter
|
||||||
|
import org.openrndr.extra.parameters.IntParameter
|
||||||
|
import org.openrndr.extra.parameters.listParameters
|
||||||
|
import org.spekframework.spek2.Spek
|
||||||
|
import org.spekframework.spek2.style.specification.describe
|
||||||
|
|
||||||
|
val a = object {
|
||||||
|
@DoubleParameter("a double scalar", 0.0, 1.0, order = 0)
|
||||||
|
var d = 1.0
|
||||||
|
|
||||||
|
@IntParameter("an integer scalar", 1, 100, order = 1)
|
||||||
|
var i = 1
|
||||||
|
|
||||||
|
@BooleanParameter("a boolean parameter", order = 2)
|
||||||
|
var b = false
|
||||||
|
}
|
||||||
|
|
||||||
|
object TestAnnotations : Spek({
|
||||||
|
describe("an annotated object") {
|
||||||
|
it("has listable parameters") {
|
||||||
|
val list = a.listParameters()
|
||||||
|
list.size `should be equal to` 3
|
||||||
|
list[0].property.name `should be equal to` "d"
|
||||||
|
list[0].label `should be equal to` "a double scalar"
|
||||||
|
list[0].doubleRange?.let {
|
||||||
|
it.start shouldBeInRange 0.0 .. 0.0001
|
||||||
|
it.endInclusive shouldBeInRange 0.999 .. 1.001
|
||||||
|
}
|
||||||
|
list[0].precision `should be equal to` 3
|
||||||
|
|
||||||
|
list[1].property.name `should be equal to` "i"
|
||||||
|
list[1].label `should be equal to` "an integer scalar"
|
||||||
|
list[1].intRange?.let {
|
||||||
|
it.start `should be equal to` 1
|
||||||
|
it.endInclusive `should be equal to` 100
|
||||||
|
}
|
||||||
|
|
||||||
|
list[2].property.name `should be equal to` "b"
|
||||||
|
list[2].label `should be equal to` "a boolean parameter"
|
||||||
|
list[2].precision `should be equal to` null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -4,6 +4,7 @@ include 'orx-camera',
|
|||||||
'orx-compositor',
|
'orx-compositor',
|
||||||
'orx-easing',
|
'orx-easing',
|
||||||
'orx-file-watcher',
|
'orx-file-watcher',
|
||||||
|
'orx-parameters',
|
||||||
'orx-filter-extension',
|
'orx-filter-extension',
|
||||||
'orx-fx',
|
'orx-fx',
|
||||||
'orx-gradient-descent',
|
'orx-gradient-descent',
|
||||||
|
|||||||
Reference in New Issue
Block a user