diff --git a/orx-parameters/src/main/kotlin/Annotations.kt b/orx-parameters/src/main/kotlin/Annotations.kt index 00b8d94c..8763040f 100644 --- a/orx-parameters/src/main/kotlin/Annotations.kt +++ b/orx-parameters/src/main/kotlin/Annotations.kt @@ -17,6 +17,7 @@ import kotlin.reflect.full.memberProperties 5. Add a test in TestAnnotations.kt */ +// @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) annotation class Description(val title: String, val description: String = "") @@ -33,6 +34,29 @@ annotation class Description(val title: String, val description: String = "") @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) + +/** + * DoubleListParameter annotation for a double precision 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 minimumListLength the minimum amount of entries the annotated list should contain + * @property maximumListLength the maximum amount of entries the annotated list should contain + * @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 DoubleListParameter( + val label: String, + val low: Double = -1.0, + val high: Double = 1.0, + val minimumListLength: Int = 1, + val maximumListLength: Int = 16, + val precision: Int = 3, + val order: Int = Integer.MAX_VALUE +) + /** * IntParameter annotation for an integer parameter * @property label a short description of the parameter @@ -100,6 +124,8 @@ annotation class XYParameter( @Retention(AnnotationRetention.RUNTIME) annotation class ActionParameter(val label: String, val order: Int = Integer.MAX_VALUE) +// +// enum class ParameterType(val annotationClass: KClass) { Double(DoubleParameter::class), Int(IntParameter::class), @@ -107,7 +133,8 @@ enum class ParameterType(val annotationClass: KClass) { Action(ActionParameter::class), Text(TextParameter::class), Color(ColorParameter::class), - XY(XYParameter::class) + XY(XYParameter::class), + DoubleList(DoubleListParameter::class) ; companion object { @@ -117,7 +144,8 @@ enum class ParameterType(val annotationClass: KClass) { val parameterAnnotationClasses get() = values().map { it.annotationClass } } } - +// +// /** * Parameter summary class. This is used by [listParameters] as a way to report parameters in * a unified form. @@ -138,25 +166,28 @@ class Parameter( val label: String, val doubleRange: ClosedRange?, val vectorRange: Pair?, + val sizeRange: ClosedRange?, val intRange: IntRange?, val precision: Int?, val invertY: Boolean?, val showVector: Boolean?, val order: Int) - +// +// /** * List all parameters, (public var properties with a parameter annotation) */ fun Any.listParameters(): List { - return (this::class.memberProperties.filter { - !it.isConst && - it is KMutableProperty1<*, *> && - it.visibility == KVisibility.PUBLIC && - it.annotations.map { it.annotationClass }.intersect(ParameterType.parameterAnnotationClasses).isNotEmpty() - }.map { - val annotations = it.annotations.filter { it.annotationClass in ParameterType.parameterAnnotationClasses } + return (this::class.memberProperties.filter { property -> + !property.isConst && + property is KMutableProperty1<*, *> && + property.visibility == KVisibility.PUBLIC && + property.annotations.map { it.annotationClass }.intersect(ParameterType.parameterAnnotationClasses).isNotEmpty() + }.map { property -> + val annotations = property.annotations.filter { it.annotationClass in ParameterType.parameterAnnotationClasses } var intRange: IntRange? = null var doubleRange: ClosedRange? = null + var sizeRange: ClosedRange? = null var order: Int = Integer.MAX_VALUE var label = "" var precision: Int? = null @@ -199,15 +230,24 @@ fun Any.listParameters(): List { 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 + + } } } Parameter( parameterType = type ?: error("no type"), - property = it as KMutableProperty1, + property = property as KMutableProperty1, function = null, label = label, doubleRange = doubleRange, vectorRange = vectorRange, + sizeRange = sizeRange, intRange = intRange, precision = precision, showVector = showVector, @@ -228,6 +268,7 @@ fun Any.listParameters(): List { label = label, doubleRange = null, intRange = null, + sizeRange = null, vectorRange = null, precision = null, showVector = null, @@ -236,6 +277,7 @@ fun Any.listParameters(): List { ) }).sortedBy { it.order } } +// fun Any.title() = this::class.findAnnotation()?.title diff --git a/orx-parameters/src/test/kotlin/TestAnnotations.kt b/orx-parameters/src/test/kotlin/TestAnnotations.kt index 21f7bd67..6e2cff93 100644 --- a/orx-parameters/src/test/kotlin/TestAnnotations.kt +++ b/orx-parameters/src/test/kotlin/TestAnnotations.kt @@ -28,20 +28,23 @@ val a = object { @XYParameter("an XY parameter", order = 6) var xy = Vector2.ZERO + + @DoubleListParameter("a double list parameter", order = 7) + var dl = mutableListOf() } object TestAnnotations : Spek({ describe("an annotated object") { it("has listable parameters") { val list = a.listParameters() - list.size `should be equal to` 7 + list.size `should be equal to` 8 list[0].property?.name `should be equal to` "d" list[0].parameterType `should be equal to` ParameterType.Double 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 + it.start shouldBeInRange 0.0..0.0001 + it.endInclusive shouldBeInRange 0.999..1.001 } list[0].precision `should be equal to` 3 @@ -68,7 +71,7 @@ object TestAnnotations : Spek({ invoking { try { list[3].function?.call(a) - } catch(e: java.lang.reflect.InvocationTargetException) { + } catch (e: java.lang.reflect.InvocationTargetException) { /* this unpacks the exception that is wrapped in the ITExc */ throw(e.targetException) } @@ -85,6 +88,10 @@ object TestAnnotations : Spek({ list[6].parameterType `should be equal to` ParameterType.XY list[6].property?.name `should be equal to` "xy" list[6].label `should be equal to` "an XY parameter" + + list[7].parameterType `should be equal to` ParameterType.DoubleList + list[7].property?.name `should be equal to` "dl" + list[7].label `should be equal to` "a double list parameter" } } })