Add Vector2/Vector3/Vector4 parameters and controls
This commit is contained in:
@@ -14,6 +14,8 @@ import org.openrndr.draw.Drawer
|
||||
import org.openrndr.extra.parameters.*
|
||||
import org.openrndr.internal.Driver
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.Vector4
|
||||
import org.openrndr.panel.ControlManager
|
||||
import org.openrndr.panel.controlManager
|
||||
import org.openrndr.panel.elements.*
|
||||
@@ -185,6 +187,19 @@ class GUI : Extension {
|
||||
this.width = 175.px
|
||||
this.height = 100.px
|
||||
}
|
||||
descendant(has type "sliders-vector2") {
|
||||
this.width = 175.px
|
||||
this.height = 100.px
|
||||
}
|
||||
descendant(has type "sliders-vector3") {
|
||||
this.width = 175.px
|
||||
this.height = 100.px
|
||||
}
|
||||
descendant(has type "sliders-vector4") {
|
||||
this.width = 175.px
|
||||
this.height = 100.px
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
}
|
||||
|
||||
@@ -468,6 +483,82 @@ class GUI : Extension {
|
||||
}
|
||||
}
|
||||
|
||||
ParameterType.Vector2 -> {
|
||||
slidersVector2 {
|
||||
range = parameter.doubleRange!!
|
||||
label = parameter.label
|
||||
precision = parameter.precision!!
|
||||
|
||||
events.valueChanged.listen {
|
||||
setAndPersist(
|
||||
compartment.label,
|
||||
parameter.property as KMutableProperty1<Any, Vector2>,
|
||||
obj,
|
||||
it.newValue)
|
||||
|
||||
onChangeListener?.invoke(parameter.property!!.name, it.newValue)
|
||||
}
|
||||
getPersistedOrDefault(
|
||||
compartment.label,
|
||||
parameter.property as KMutableProperty1<Any, Vector2>,
|
||||
obj
|
||||
)?.let {
|
||||
value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterType.Vector3 -> {
|
||||
slidersVector3 {
|
||||
range = parameter.doubleRange!!
|
||||
label = parameter.label
|
||||
precision = parameter.precision!!
|
||||
|
||||
events.valueChanged.listen {
|
||||
setAndPersist(
|
||||
compartment.label,
|
||||
parameter.property as KMutableProperty1<Any, Vector3>,
|
||||
obj,
|
||||
it.newValue)
|
||||
|
||||
onChangeListener?.invoke(parameter.property!!.name, it.newValue)
|
||||
}
|
||||
getPersistedOrDefault(
|
||||
compartment.label,
|
||||
parameter.property as KMutableProperty1<Any, Vector3>,
|
||||
obj
|
||||
)?.let {
|
||||
value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterType.Vector4 -> {
|
||||
slidersVector4 {
|
||||
range = parameter.doubleRange!!
|
||||
label = parameter.label
|
||||
precision = parameter.precision!!
|
||||
|
||||
events.valueChanged.listen {
|
||||
setAndPersist(
|
||||
compartment.label,
|
||||
parameter.property as KMutableProperty1<Any, Vector4>,
|
||||
obj,
|
||||
it.newValue)
|
||||
|
||||
onChangeListener?.invoke(parameter.property!!.name, it.newValue)
|
||||
}
|
||||
getPersistedOrDefault(
|
||||
compartment.label,
|
||||
parameter.property as KMutableProperty1<Any, Vector4>,
|
||||
obj
|
||||
)?.let {
|
||||
value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
@@ -486,7 +577,9 @@ class GUI : Extension {
|
||||
var intValue: Int? = null,
|
||||
var booleanValue: Boolean? = null,
|
||||
var colorValue: ColorRGBa? = null,
|
||||
var vectorValue: Vector2? = null,
|
||||
var vector2Value: Vector2? = null,
|
||||
var vector3Value: Vector3? = null,
|
||||
var vector4Value: Vector4? = null,
|
||||
var doubleListValue: MutableList<Double>? = null,
|
||||
var textValue: String? = null)
|
||||
|
||||
@@ -507,8 +600,11 @@ class GUI : Extension {
|
||||
ParameterType.Color -> ParameterValue(colorValue = k.property.qget(lo.obj) as ColorRGBa)
|
||||
ParameterType.Text -> ParameterValue(textValue = k.property.qget(lo.obj) as String)
|
||||
ParameterType.Boolean -> ParameterValue(booleanValue = k.property.qget(lo.obj) as Boolean)
|
||||
ParameterType.XY -> ParameterValue(vectorValue = k.property.qget(lo.obj) as Vector2)
|
||||
ParameterType.XY -> ParameterValue(vector2Value = k.property.qget(lo.obj) as Vector2)
|
||||
ParameterType.DoubleList -> ParameterValue(doubleListValue = k.property.qget(lo.obj) as MutableList<Double>)
|
||||
ParameterType.Vector2 -> ParameterValue(vector2Value = k.property.qget(lo.obj) as Vector2)
|
||||
ParameterType.Vector3 -> ParameterValue(vector3Value = k.property.qget(lo.obj) as Vector3)
|
||||
ParameterType.Vector4 -> ParameterValue(vector4Value = k.property.qget(lo.obj) as Vector4)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -543,7 +639,7 @@ class GUI : Extension {
|
||||
ParameterType.Color -> parameterValue.colorValue?.let {
|
||||
parameter.property.qset(lo.obj, it)
|
||||
}
|
||||
ParameterType.XY -> parameterValue.vectorValue?.let {
|
||||
ParameterType.XY -> parameterValue.vector2Value?.let {
|
||||
parameter.property.qset(lo.obj, it)
|
||||
}
|
||||
ParameterType.DoubleList -> parameterValue.doubleListValue?.let {
|
||||
@@ -552,6 +648,15 @@ class GUI : Extension {
|
||||
ParameterType.Boolean -> parameterValue.booleanValue?.let {
|
||||
parameter.property.qset(lo.obj, it)
|
||||
}
|
||||
ParameterType.Vector2 -> parameterValue.vector2Value?.let {
|
||||
parameter.property.qset(lo.obj, it)
|
||||
}
|
||||
ParameterType.Vector3 -> parameterValue.vector3Value?.let {
|
||||
parameter.property.qset(lo.obj, it)
|
||||
}
|
||||
ParameterType.Vector4 -> parameterValue.vector4Value?.let {
|
||||
parameter.property.qset(lo.obj, it)
|
||||
}
|
||||
ParameterType.Action -> {
|
||||
// intentionally do nothing
|
||||
}
|
||||
@@ -587,6 +692,15 @@ class GUI : Extension {
|
||||
ParameterType.Boolean -> {
|
||||
(control as Toggle).value = (parameter.property as KMutableProperty1<Any, Boolean>).get(labeledObject.obj)
|
||||
}
|
||||
ParameterType.Vector2 -> {
|
||||
(control as SlidersVector2).value = (parameter.property as KMutableProperty1<Any, Vector2>).get(labeledObject.obj)
|
||||
}
|
||||
ParameterType.Vector3 -> {
|
||||
(control as SlidersVector3).value = (parameter.property as KMutableProperty1<Any, Vector3>).get(labeledObject.obj)
|
||||
}
|
||||
ParameterType.Vector4 -> {
|
||||
(control as SlidersVector4).value = (parameter.property as KMutableProperty1<Any, Vector4>).get(labeledObject.obj)
|
||||
}
|
||||
ParameterType.Action -> {
|
||||
// intentionally do nothing
|
||||
}
|
||||
@@ -637,7 +751,6 @@ class GUI : Extension {
|
||||
updateControls()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively find a unique label
|
||||
* @param label to find an alternate for in case it already exist
|
||||
|
||||
@@ -63,6 +63,12 @@ fun Element.envelopeEditor(vararg classes: String, init: EnvelopeEditor.() -> Un
|
||||
|
||||
fun Element.sequenceEditor(vararg classes: String, init: SequenceEditor.() -> Unit) = initElement(classes, SequenceEditor().apply {}, init)
|
||||
|
||||
fun Element.slidersVector2(vararg classes: String, init: SlidersVector2.() -> Unit) = initElement(classes, SlidersVector2().apply {}, init)
|
||||
fun Element.slidersVector3(vararg classes: String, init: SlidersVector3.() -> Unit) = initElement(classes, SlidersVector3().apply {}, init)
|
||||
fun Element.slidersVector4(vararg classes: String, init: SlidersVector4.() -> Unit) = initElement(classes, SlidersVector4().apply {}, init)
|
||||
|
||||
|
||||
|
||||
|
||||
fun Element.textfield(vararg classes: String, init: Textfield.() -> Unit) = initElement(classes, Textfield(), init)
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ import org.openrndr.draw.isolated
|
||||
import org.openrndr.events.Event
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.map
|
||||
import org.openrndr.panel.style.Color
|
||||
import org.openrndr.panel.style.color
|
||||
import org.openrndr.panel.style.effectiveColor
|
||||
import org.openrndr.panel.tools.Tooltip
|
||||
import org.openrndr.shape.Rectangle
|
||||
@@ -20,21 +18,17 @@ import kotlin.math.abs
|
||||
import kotlin.math.round
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
class SequenceEditor : SequenceEditorBase("sequence-editor") {
|
||||
var value
|
||||
get() = baseValue
|
||||
set(value) {
|
||||
baseValue = value
|
||||
}
|
||||
|
||||
var value = mutableListOf(0.0)
|
||||
var label = "sequence"
|
||||
var precision = 2
|
||||
var maximumSequenceLength = 16
|
||||
var minimumSequenceLength = 1
|
||||
var range: ClosedRange<Double> = -1.0..1.0
|
||||
public override var maximumSequenceLength = 16
|
||||
public override var minimumSequenceLength = 1
|
||||
|
||||
private var selectedIndex: Int? = null
|
||||
private var tooltip: Tooltip? = null
|
||||
|
||||
private val footerHeight = 20.0
|
||||
|
||||
class ValueChangedEvent(val source: SequenceEditor,
|
||||
class ValueChangedEvent(val source: SequenceEditorBase,
|
||||
val oldValue: List<Double>,
|
||||
val newValue: List<Double>)
|
||||
|
||||
@@ -44,6 +38,37 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
|
||||
val events = Events()
|
||||
|
||||
init {
|
||||
baseEvents.valueChanged.listen {
|
||||
events.valueChanged.trigger(ValueChangedEvent(this, it.oldValue, it.newValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class SequenceEditorBase(type: String = "sequence-editor-base") : Element(ElementType(type)) {
|
||||
|
||||
internal var baseValue = mutableListOf(0.0)
|
||||
var label = "sequence"
|
||||
var precision = 2
|
||||
internal open var maximumSequenceLength = 16
|
||||
internal open var minimumSequenceLength = 1
|
||||
var range: ClosedRange<Double> = -1.0..1.0
|
||||
|
||||
private var selectedIndex: Int? = null
|
||||
private var tooltip: Tooltip? = null
|
||||
|
||||
private val footerHeight = 20.0
|
||||
|
||||
internal class ValueChangedEvent(val source: SequenceEditorBase,
|
||||
val oldValue: List<Double>,
|
||||
val newValue: List<Double>)
|
||||
|
||||
internal class Events {
|
||||
val valueChanged = Event<ValueChangedEvent>("sequence-editor-base-value-changed")
|
||||
}
|
||||
|
||||
internal val baseEvents = Events()
|
||||
|
||||
init {
|
||||
fun query(position: Vector2): Vector2 {
|
||||
val x = (position.x - layout.screenX) / layout.screenWidth
|
||||
@@ -56,8 +81,8 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
requestRedraw()
|
||||
}
|
||||
mouse.pressed.listen {
|
||||
if (value.isNotEmpty()) {
|
||||
val dx = (layout.screenWidth / (value.size + 1))
|
||||
if (baseValue.isNotEmpty()) {
|
||||
val dx = (layout.screenWidth / (baseValue.size + 1))
|
||||
val index = (it.position.x - layout.screenX) / dx
|
||||
|
||||
val d = index - round(index)
|
||||
@@ -68,20 +93,20 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
selectedIndex = if (KeyModifier.CTRL !in it.modifiers) {
|
||||
round(index).toInt()
|
||||
} else {
|
||||
if (value.size > minimumSequenceLength) {
|
||||
val oldValue = value.map { it }
|
||||
value.removeAt(round(index).toInt() - 1)
|
||||
events.valueChanged.trigger(ValueChangedEvent(this, oldValue, value))
|
||||
if (baseValue.size > minimumSequenceLength) {
|
||||
val oldValue = baseValue.map { it }
|
||||
baseValue.removeAt(round(index).toInt() - 1)
|
||||
baseEvents.valueChanged.trigger(ValueChangedEvent(this, oldValue, baseValue))
|
||||
}
|
||||
null
|
||||
}
|
||||
} else {
|
||||
if (KeyModifier.CTRL !in it.modifiers) {
|
||||
if (value.size < maximumSequenceLength) {
|
||||
if (baseValue.size < maximumSequenceLength) {
|
||||
val q = query(it.position)
|
||||
val oldValue = value.map { it }
|
||||
value.add(index.toInt(), q.y.map(-1.0, 1.0, range.start, range.endInclusive))
|
||||
events.valueChanged.trigger(ValueChangedEvent(this, oldValue, value))
|
||||
val oldValue = baseValue.map { it }
|
||||
baseValue.add(index.toInt(), q.y.map(-1.0, 1.0, range.start, range.endInclusive))
|
||||
baseEvents.valueChanged.trigger(ValueChangedEvent(this, oldValue, baseValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,8 +133,8 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
requestRedraw()
|
||||
}
|
||||
|
||||
if (value.isNotEmpty()) {
|
||||
val dx = (layout.screenWidth / (value.size + 1))
|
||||
if (baseValue.isNotEmpty()) {
|
||||
val dx = (layout.screenWidth / (baseValue.size + 1))
|
||||
val index = (it.position.x - layout.screenX) / dx
|
||||
val d = index - round(index)
|
||||
val dp = d * dx
|
||||
@@ -118,9 +143,9 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
if (dpa < 10.0) {
|
||||
hoverJob = GlobalScope.launch {
|
||||
val readIndex = index.roundToInt() - 1
|
||||
if (readIndex >= 0 && readIndex < value.size) {
|
||||
val value = String.format("%.0${precision}f", value[readIndex])
|
||||
tooltip = Tooltip(this@SequenceEditor, it.position - Vector2(layout.screenX, layout.screenY), "$value")
|
||||
if (readIndex >= 0 && readIndex < baseValue.size) {
|
||||
val value = String.format("%.0${precision}f", baseValue[readIndex])
|
||||
tooltip = Tooltip(this@SequenceEditorBase, it.position - Vector2(layout.screenX, layout.screenY), "$value")
|
||||
requestRedraw()
|
||||
}
|
||||
}
|
||||
@@ -131,10 +156,10 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
val q = query(it.position)
|
||||
selectedIndex?.let { index ->
|
||||
val writeIndex = index - 1
|
||||
if (writeIndex >= 0 && writeIndex < value.size) {
|
||||
val oldValue = value.map { it }
|
||||
value[writeIndex] = q.y.coerceIn(-1.0, 1.0).map(-1.0, 1.0, range.start, range.endInclusive)
|
||||
events.valueChanged.trigger(ValueChangedEvent(this, oldValue, value))
|
||||
if (writeIndex >= 0 && writeIndex < baseValue.size) {
|
||||
val oldValue = baseValue.map { it }
|
||||
baseValue[writeIndex] = q.y.coerceIn(-1.0, 1.0).map(-1.0, 1.0, range.start, range.endInclusive)
|
||||
baseEvents.valueChanged.trigger(ValueChangedEvent(this, oldValue, baseValue))
|
||||
}
|
||||
requestRedraw()
|
||||
}
|
||||
@@ -154,9 +179,9 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
||||
drawer.strokeWeight = 7.0
|
||||
drawer.fill = computedStyle.effectiveColor
|
||||
|
||||
for (i in value.indices) {
|
||||
val dx = layout.screenWidth / (value.size + 1)
|
||||
val height = -value[i].map(range.start, range.endInclusive, -1.0, 1.0).coerceIn(-1.0, 1.0) * controlArea.height / 2.0
|
||||
for (i in baseValue.indices) {
|
||||
val dx = layout.screenWidth / (baseValue.size + 1)
|
||||
val height = -baseValue[i].map(range.start, range.endInclusive, -1.0, 1.0).coerceIn(-1.0, 1.0) * controlArea.height / 2.0
|
||||
|
||||
val x = dx * (i + 1)
|
||||
drawer.lineCap = LineCap.ROUND
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.openrndr.panel.elements
|
||||
|
||||
import org.openrndr.events.Event
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.Vector4
|
||||
|
||||
|
||||
class SlidersVector2 : SequenceEditorBase("sliders-vector2") {
|
||||
var value : Vector2
|
||||
get() {
|
||||
return Vector2(baseValue[0], baseValue[1])
|
||||
}
|
||||
set(value) {
|
||||
baseValue[0] = value.x
|
||||
baseValue[1] = value.y
|
||||
}
|
||||
|
||||
class ValueChangedEvent(val source: SequenceEditorBase,
|
||||
val oldValue: Vector2,
|
||||
val newValue: Vector2)
|
||||
|
||||
class Events {
|
||||
val valueChanged = Event<ValueChangedEvent>("sequence-editor-value-changed")
|
||||
}
|
||||
|
||||
val events = Events()
|
||||
|
||||
init {
|
||||
baseValue = mutableListOf(0.0, 0.0)
|
||||
minimumSequenceLength = 2
|
||||
maximumSequenceLength = 2
|
||||
baseEvents.valueChanged.listen {
|
||||
events.valueChanged.trigger(ValueChangedEvent(this,
|
||||
Vector2(it.oldValue[0], it.oldValue[1]),
|
||||
Vector2(it.newValue[0], it.newValue[1]))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SlidersVector3 : SequenceEditorBase("sliders-vector3") {
|
||||
var value : Vector3
|
||||
get() {
|
||||
return Vector3(baseValue[0], baseValue[1], baseValue[2])
|
||||
}
|
||||
set(value) {
|
||||
baseValue[0] = value.x
|
||||
baseValue[1] = value.y
|
||||
baseValue[2] = value.z
|
||||
}
|
||||
|
||||
class ValueChangedEvent(val source: SequenceEditorBase,
|
||||
val oldValue: Vector3,
|
||||
val newValue: Vector3)
|
||||
|
||||
class Events {
|
||||
val valueChanged = Event<ValueChangedEvent>("sliders-vector3-value-changed")
|
||||
}
|
||||
|
||||
val events = Events()
|
||||
|
||||
init {
|
||||
baseValue = mutableListOf(0.0, 0.0, 0.0)
|
||||
minimumSequenceLength = 3
|
||||
maximumSequenceLength = 3
|
||||
baseEvents.valueChanged.listen {
|
||||
events.valueChanged.trigger(ValueChangedEvent(this,
|
||||
Vector3(it.oldValue[0], it.oldValue[1], it.oldValue[2]),
|
||||
Vector3(it.newValue[0], it.newValue[1], it.newValue[2]))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SlidersVector4 : SequenceEditorBase("sliders-vector4") {
|
||||
var value : Vector4
|
||||
get() {
|
||||
return Vector4(baseValue[0], baseValue[1], baseValue[2], baseValue[3])
|
||||
}
|
||||
set(value) {
|
||||
baseValue[0] = value.x
|
||||
baseValue[1] = value.y
|
||||
baseValue[2] = value.z
|
||||
baseValue[3] = value.w
|
||||
}
|
||||
|
||||
class ValueChangedEvent(val source: SequenceEditorBase,
|
||||
val oldValue: Vector4,
|
||||
val newValue: Vector4)
|
||||
|
||||
class Events {
|
||||
val valueChanged = Event<ValueChangedEvent>("sliders-vector4-value-changed")
|
||||
}
|
||||
|
||||
val events = Events()
|
||||
|
||||
init {
|
||||
baseValue = mutableListOf(0.0, 0.0, 0.0, 0.0)
|
||||
minimumSequenceLength = 4
|
||||
maximumSequenceLength = 4
|
||||
baseEvents.valueChanged.listen {
|
||||
events.valueChanged.trigger(ValueChangedEvent(this,
|
||||
Vector4(it.oldValue[0], it.oldValue[1], it.oldValue[2], it.oldValue[3]),
|
||||
Vector4(it.newValue[0], it.newValue[1], it.newValue[2], it.newValue[3]))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,42 @@ fun defaultStyles(
|
||||
color = controlActiveColor
|
||||
}
|
||||
},
|
||||
styleSheet(has type "sliders-vector2") {
|
||||
height = 60.px
|
||||
width = 100.percent
|
||||
marginTop = 5.px
|
||||
marginBottom = 15.px
|
||||
marginLeft = 5.px
|
||||
marginRight = 5.px
|
||||
color = controlTextColor
|
||||
and(has state "active") {
|
||||
color = controlActiveColor
|
||||
}
|
||||
},
|
||||
styleSheet(has type "sliders-vector3") {
|
||||
height = 60.px
|
||||
width = 100.percent
|
||||
marginTop = 5.px
|
||||
marginBottom = 15.px
|
||||
marginLeft = 5.px
|
||||
marginRight = 5.px
|
||||
color = controlTextColor
|
||||
and(has state "active") {
|
||||
color = controlActiveColor
|
||||
}
|
||||
},
|
||||
styleSheet(has type "sliders-vector4") {
|
||||
height = 60.px
|
||||
width = 100.percent
|
||||
marginTop = 5.px
|
||||
marginBottom = 15.px
|
||||
marginLeft = 5.px
|
||||
marginRight = 5.px
|
||||
color = controlTextColor
|
||||
and(has state "active") {
|
||||
color = controlActiveColor
|
||||
}
|
||||
},
|
||||
|
||||
styleSheet(has type "colorpicker") {
|
||||
height = 80.px
|
||||
|
||||
@@ -115,6 +115,36 @@ annotation class XYParameter(
|
||||
val order: Int = Integer.MAX_VALUE
|
||||
)
|
||||
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class Vector2Parameter(
|
||||
val label: String,
|
||||
val min: Double = -1.0,
|
||||
val max: Double = 1.0,
|
||||
val precision: Int = 2,
|
||||
val order: Int = Integer.MAX_VALUE
|
||||
)
|
||||
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class Vector3Parameter(
|
||||
val label: String,
|
||||
val min: Double = -1.0,
|
||||
val max: Double = 1.0,
|
||||
val precision: Int = 2,
|
||||
val order: Int = Integer.MAX_VALUE
|
||||
)
|
||||
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class Vector4Parameter(
|
||||
val label: String,
|
||||
val min: Double = -1.0,
|
||||
val max: Double = 1.0,
|
||||
val precision: Int = 2,
|
||||
val order: Int = Integer.MAX_VALUE
|
||||
)
|
||||
|
||||
/**
|
||||
* ActionParameter annotation for functions without arguments
|
||||
* @property label a short description of the parameter
|
||||
@@ -134,7 +164,10 @@ enum class ParameterType(val annotationClass: KClass<out Annotation>) {
|
||||
Text(TextParameter::class),
|
||||
Color(ColorParameter::class),
|
||||
XY(XYParameter::class),
|
||||
DoubleList(DoubleListParameter::class)
|
||||
DoubleList(DoubleListParameter::class),
|
||||
Vector2(Vector2Parameter::class),
|
||||
Vector3(Vector3Parameter::class),
|
||||
Vector4(Vector4Parameter::class)
|
||||
;
|
||||
|
||||
companion object {
|
||||
@@ -236,7 +269,24 @@ fun Any.listParameters(): List<Parameter> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import org.amshove.kluent.*
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.extra.parameters.*
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.Vector4
|
||||
import org.spekframework.spek2.Spek
|
||||
import org.spekframework.spek2.style.specification.describe
|
||||
|
||||
@@ -31,13 +33,24 @@ val a = object {
|
||||
|
||||
@DoubleListParameter("a double list parameter", order = 7)
|
||||
var dl = mutableListOf<Double>()
|
||||
|
||||
@Vector2Parameter("a vector 2 parameter", order = 8)
|
||||
var v2 = Vector2.ZERO
|
||||
|
||||
@Vector3Parameter("a vector 3 parameter", order = 9)
|
||||
var v3 = Vector3.ZERO
|
||||
|
||||
@Vector4Parameter("a vector 4 parameter", order = 10)
|
||||
var v4 = Vector4.ZERO
|
||||
|
||||
|
||||
}
|
||||
|
||||
object TestAnnotations : Spek({
|
||||
describe("an annotated object") {
|
||||
it("has listable parameters") {
|
||||
val list = a.listParameters()
|
||||
list.size `should be equal to` 8
|
||||
list.size `should be equal to` 11
|
||||
|
||||
list[0].property?.name `should be equal to` "d"
|
||||
list[0].parameterType `should be equal to` ParameterType.Double
|
||||
@@ -92,6 +105,18 @@ object TestAnnotations : Spek({
|
||||
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"
|
||||
|
||||
list[8].parameterType `should be equal to` ParameterType.Vector2
|
||||
list[8].property?.name `should be equal to` "v2"
|
||||
list[8].label `should be equal to` "a vector 2 parameter"
|
||||
|
||||
list[9].parameterType `should be equal to` ParameterType.Vector3
|
||||
list[9].property?.name `should be equal to` "v3"
|
||||
list[9].label `should be equal to` "a vector 3 parameter"
|
||||
|
||||
list[10].parameterType `should be equal to` ParameterType.Vector4
|
||||
list[10].property?.name `should be equal to` "v4"
|
||||
list[10].label `should be equal to` "a vector 4 parameter"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user