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.extra.parameters.*
|
||||||
import org.openrndr.internal.Driver
|
import org.openrndr.internal.Driver
|
||||||
import org.openrndr.math.Vector2
|
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.controlManager
|
import org.openrndr.panel.controlManager
|
||||||
import org.openrndr.panel.elements.*
|
import org.openrndr.panel.elements.*
|
||||||
@@ -185,6 +187,19 @@ class GUI : Extension {
|
|||||||
this.width = 175.px
|
this.width = 175.px
|
||||||
this.height = 100.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>
|
//</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>
|
//</editor-fold>
|
||||||
@@ -486,7 +577,9 @@ class GUI : Extension {
|
|||||||
var intValue: Int? = null,
|
var intValue: Int? = null,
|
||||||
var booleanValue: Boolean? = null,
|
var booleanValue: Boolean? = null,
|
||||||
var colorValue: ColorRGBa? = 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 doubleListValue: MutableList<Double>? = null,
|
||||||
var textValue: String? = null)
|
var textValue: String? = null)
|
||||||
|
|
||||||
@@ -507,8 +600,11 @@ class GUI : Extension {
|
|||||||
ParameterType.Color -> ParameterValue(colorValue = k.property.qget(lo.obj) as ColorRGBa)
|
ParameterType.Color -> ParameterValue(colorValue = k.property.qget(lo.obj) as ColorRGBa)
|
||||||
ParameterType.Text -> ParameterValue(textValue = k.property.qget(lo.obj) as String)
|
ParameterType.Text -> ParameterValue(textValue = k.property.qget(lo.obj) as String)
|
||||||
ParameterType.Boolean -> ParameterValue(booleanValue = k.property.qget(lo.obj) as Boolean)
|
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.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 {
|
ParameterType.Color -> parameterValue.colorValue?.let {
|
||||||
parameter.property.qset(lo.obj, it)
|
parameter.property.qset(lo.obj, it)
|
||||||
}
|
}
|
||||||
ParameterType.XY -> parameterValue.vectorValue?.let {
|
ParameterType.XY -> parameterValue.vector2Value?.let {
|
||||||
parameter.property.qset(lo.obj, it)
|
parameter.property.qset(lo.obj, it)
|
||||||
}
|
}
|
||||||
ParameterType.DoubleList -> parameterValue.doubleListValue?.let {
|
ParameterType.DoubleList -> parameterValue.doubleListValue?.let {
|
||||||
@@ -552,6 +648,15 @@ class GUI : Extension {
|
|||||||
ParameterType.Boolean -> parameterValue.booleanValue?.let {
|
ParameterType.Boolean -> parameterValue.booleanValue?.let {
|
||||||
parameter.property.qset(lo.obj, it)
|
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 -> {
|
ParameterType.Action -> {
|
||||||
// intentionally do nothing
|
// intentionally do nothing
|
||||||
}
|
}
|
||||||
@@ -587,13 +692,22 @@ class GUI : Extension {
|
|||||||
ParameterType.Boolean -> {
|
ParameterType.Boolean -> {
|
||||||
(control as Toggle).value = (parameter.property as KMutableProperty1<Any, Boolean>).get(labeledObject.obj)
|
(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 -> {
|
ParameterType.Action -> {
|
||||||
// intentionally do nothing
|
// intentionally do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun randomize(strength:Double = 0.05) {
|
fun randomize(strength: Double = 0.05) {
|
||||||
for ((labeledObject, binding) in trackedObjects) {
|
for ((labeledObject, binding) in trackedObjects) {
|
||||||
// -- only randomize visible parameters
|
// -- only randomize visible parameters
|
||||||
for (parameter in binding.parameterControls.keys) {
|
for (parameter in binding.parameterControls.keys) {
|
||||||
@@ -604,7 +718,7 @@ class GUI : Extension {
|
|||||||
val max = parameter.doubleRange!!.endInclusive
|
val max = parameter.doubleRange!!.endInclusive
|
||||||
val currentValue = (parameter.property as KMutableProperty1<Any, Double>).get(labeledObject.obj)
|
val currentValue = (parameter.property as KMutableProperty1<Any, Double>).get(labeledObject.obj)
|
||||||
val randomValue = Math.random() * (max - min) + min
|
val randomValue = Math.random() * (max - min) + min
|
||||||
val newValue = (1.0 - strength) * currentValue + randomValue * strength
|
val newValue = (1.0 - strength) * currentValue + randomValue * strength
|
||||||
(parameter.property as KMutableProperty1<Any, Double>).set(labeledObject.obj, newValue)
|
(parameter.property as KMutableProperty1<Any, Double>).set(labeledObject.obj, newValue)
|
||||||
}
|
}
|
||||||
ParameterType.Int -> {
|
ParameterType.Int -> {
|
||||||
@@ -612,7 +726,7 @@ class GUI : Extension {
|
|||||||
val max = parameter.intRange!!.last
|
val max = parameter.intRange!!.last
|
||||||
val currentValue = (parameter.property as KMutableProperty1<Any, Int>).get(labeledObject.obj)
|
val currentValue = (parameter.property as KMutableProperty1<Any, Int>).get(labeledObject.obj)
|
||||||
val randomValue = Math.random() * (max - min) + min
|
val randomValue = Math.random() * (max - min) + min
|
||||||
val newValue = ((1.0 - strength) * currentValue + randomValue * strength).roundToInt()
|
val newValue = ((1.0 - strength) * currentValue + randomValue * strength).roundToInt()
|
||||||
(parameter.property as KMutableProperty1<Any, Int>).set(labeledObject.obj, newValue)
|
(parameter.property as KMutableProperty1<Any, Int>).set(labeledObject.obj, newValue)
|
||||||
}
|
}
|
||||||
ParameterType.Boolean -> {
|
ParameterType.Boolean -> {
|
||||||
@@ -622,9 +736,9 @@ class GUI : Extension {
|
|||||||
ParameterType.Color -> {
|
ParameterType.Color -> {
|
||||||
val currentValue = (parameter.property as KMutableProperty1<Any, ColorRGBa>).get(labeledObject.obj)
|
val currentValue = (parameter.property as KMutableProperty1<Any, ColorRGBa>).get(labeledObject.obj)
|
||||||
val randomValue = ColorRGBa(Math.random(), Math.random(), Math.random(), currentValue.a)
|
val randomValue = ColorRGBa(Math.random(), Math.random(), Math.random(), currentValue.a)
|
||||||
val newValue = ColorRGBa((1.0 - strength) * currentValue.r + randomValue.r * strength,
|
val newValue = ColorRGBa((1.0 - strength) * currentValue.r + randomValue.r * strength,
|
||||||
(1.0 - strength) * currentValue.g + randomValue.g * strength,
|
(1.0 - strength) * currentValue.g + randomValue.g * strength,
|
||||||
(1.0 - strength) * currentValue.b + randomValue.b * strength)
|
(1.0 - strength) * currentValue.b + randomValue.b * strength)
|
||||||
|
|
||||||
(parameter.property as KMutableProperty1<Any, ColorRGBa>).set(labeledObject.obj, newValue)
|
(parameter.property as KMutableProperty1<Any, ColorRGBa>).set(labeledObject.obj, newValue)
|
||||||
}
|
}
|
||||||
@@ -637,7 +751,6 @@ class GUI : Extension {
|
|||||||
updateControls()
|
updateControls()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively find a unique label
|
* Recursively find a unique label
|
||||||
* @param label to find an alternate for in case it already exist
|
* @param label to find an alternate for in case it already exist
|
||||||
@@ -690,7 +803,7 @@ class GUI : Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("addToGui")
|
@JvmName("addToGui")
|
||||||
fun <T : Any> T.addTo(gui: GUI, label:String? = this.title()): T {
|
fun <T : Any> T.addTo(gui: GUI, label: String? = this.title()): T {
|
||||||
gui.add(this, label)
|
gui.add(this, label)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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)
|
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.events.Event
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
import org.openrndr.math.map
|
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.style.effectiveColor
|
||||||
import org.openrndr.panel.tools.Tooltip
|
import org.openrndr.panel.tools.Tooltip
|
||||||
import org.openrndr.shape.Rectangle
|
import org.openrndr.shape.Rectangle
|
||||||
@@ -20,21 +18,17 @@ import kotlin.math.abs
|
|||||||
import kotlin.math.round
|
import kotlin.math.round
|
||||||
import kotlin.math.roundToInt
|
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)
|
public override var maximumSequenceLength = 16
|
||||||
var label = "sequence"
|
public override var minimumSequenceLength = 1
|
||||||
var precision = 2
|
|
||||||
var maximumSequenceLength = 16
|
|
||||||
var minimumSequenceLength = 1
|
|
||||||
var range: ClosedRange<Double> = -1.0..1.0
|
|
||||||
|
|
||||||
private var selectedIndex: Int? = null
|
class ValueChangedEvent(val source: SequenceEditorBase,
|
||||||
private var tooltip: Tooltip? = null
|
|
||||||
|
|
||||||
private val footerHeight = 20.0
|
|
||||||
|
|
||||||
class ValueChangedEvent(val source: SequenceEditor,
|
|
||||||
val oldValue: List<Double>,
|
val oldValue: List<Double>,
|
||||||
val newValue: List<Double>)
|
val newValue: List<Double>)
|
||||||
|
|
||||||
@@ -44,6 +38,37 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
|
|
||||||
val events = Events()
|
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 {
|
init {
|
||||||
fun query(position: Vector2): Vector2 {
|
fun query(position: Vector2): Vector2 {
|
||||||
val x = (position.x - layout.screenX) / layout.screenWidth
|
val x = (position.x - layout.screenX) / layout.screenWidth
|
||||||
@@ -56,8 +81,8 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
requestRedraw()
|
requestRedraw()
|
||||||
}
|
}
|
||||||
mouse.pressed.listen {
|
mouse.pressed.listen {
|
||||||
if (value.isNotEmpty()) {
|
if (baseValue.isNotEmpty()) {
|
||||||
val dx = (layout.screenWidth / (value.size + 1))
|
val dx = (layout.screenWidth / (baseValue.size + 1))
|
||||||
val index = (it.position.x - layout.screenX) / dx
|
val index = (it.position.x - layout.screenX) / dx
|
||||||
|
|
||||||
val d = index - round(index)
|
val d = index - round(index)
|
||||||
@@ -68,20 +93,20 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
selectedIndex = if (KeyModifier.CTRL !in it.modifiers) {
|
selectedIndex = if (KeyModifier.CTRL !in it.modifiers) {
|
||||||
round(index).toInt()
|
round(index).toInt()
|
||||||
} else {
|
} else {
|
||||||
if (value.size > minimumSequenceLength) {
|
if (baseValue.size > minimumSequenceLength) {
|
||||||
val oldValue = value.map { it }
|
val oldValue = baseValue.map { it }
|
||||||
value.removeAt(round(index).toInt() - 1)
|
baseValue.removeAt(round(index).toInt() - 1)
|
||||||
events.valueChanged.trigger(ValueChangedEvent(this, oldValue, value))
|
baseEvents.valueChanged.trigger(ValueChangedEvent(this, oldValue, baseValue))
|
||||||
}
|
}
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (KeyModifier.CTRL !in it.modifiers) {
|
if (KeyModifier.CTRL !in it.modifiers) {
|
||||||
if (value.size < maximumSequenceLength) {
|
if (baseValue.size < maximumSequenceLength) {
|
||||||
val q = query(it.position)
|
val q = query(it.position)
|
||||||
val oldValue = value.map { it }
|
val oldValue = baseValue.map { it }
|
||||||
value.add(index.toInt(), q.y.map(-1.0, 1.0, range.start, range.endInclusive))
|
baseValue.add(index.toInt(), q.y.map(-1.0, 1.0, range.start, range.endInclusive))
|
||||||
events.valueChanged.trigger(ValueChangedEvent(this, oldValue, value))
|
baseEvents.valueChanged.trigger(ValueChangedEvent(this, oldValue, baseValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,8 +133,8 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
requestRedraw()
|
requestRedraw()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.isNotEmpty()) {
|
if (baseValue.isNotEmpty()) {
|
||||||
val dx = (layout.screenWidth / (value.size + 1))
|
val dx = (layout.screenWidth / (baseValue.size + 1))
|
||||||
val index = (it.position.x - layout.screenX) / dx
|
val index = (it.position.x - layout.screenX) / dx
|
||||||
val d = index - round(index)
|
val d = index - round(index)
|
||||||
val dp = d * dx
|
val dp = d * dx
|
||||||
@@ -118,9 +143,9 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
if (dpa < 10.0) {
|
if (dpa < 10.0) {
|
||||||
hoverJob = GlobalScope.launch {
|
hoverJob = GlobalScope.launch {
|
||||||
val readIndex = index.roundToInt() - 1
|
val readIndex = index.roundToInt() - 1
|
||||||
if (readIndex >= 0 && readIndex < value.size) {
|
if (readIndex >= 0 && readIndex < baseValue.size) {
|
||||||
val value = String.format("%.0${precision}f", value[readIndex])
|
val value = String.format("%.0${precision}f", baseValue[readIndex])
|
||||||
tooltip = Tooltip(this@SequenceEditor, it.position - Vector2(layout.screenX, layout.screenY), "$value")
|
tooltip = Tooltip(this@SequenceEditorBase, it.position - Vector2(layout.screenX, layout.screenY), "$value")
|
||||||
requestRedraw()
|
requestRedraw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,10 +156,10 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
val q = query(it.position)
|
val q = query(it.position)
|
||||||
selectedIndex?.let { index ->
|
selectedIndex?.let { index ->
|
||||||
val writeIndex = index - 1
|
val writeIndex = index - 1
|
||||||
if (writeIndex >= 0 && writeIndex < value.size) {
|
if (writeIndex >= 0 && writeIndex < baseValue.size) {
|
||||||
val oldValue = value.map { it }
|
val oldValue = baseValue.map { it }
|
||||||
value[writeIndex] = q.y.coerceIn(-1.0, 1.0).map(-1.0, 1.0, range.start, range.endInclusive)
|
baseValue[writeIndex] = q.y.coerceIn(-1.0, 1.0).map(-1.0, 1.0, range.start, range.endInclusive)
|
||||||
events.valueChanged.trigger(ValueChangedEvent(this, oldValue, value))
|
baseEvents.valueChanged.trigger(ValueChangedEvent(this, oldValue, baseValue))
|
||||||
}
|
}
|
||||||
requestRedraw()
|
requestRedraw()
|
||||||
}
|
}
|
||||||
@@ -154,9 +179,9 @@ class SequenceEditor : Element(ElementType("sequence-editor")) {
|
|||||||
drawer.strokeWeight = 7.0
|
drawer.strokeWeight = 7.0
|
||||||
drawer.fill = computedStyle.effectiveColor
|
drawer.fill = computedStyle.effectiveColor
|
||||||
|
|
||||||
for (i in value.indices) {
|
for (i in baseValue.indices) {
|
||||||
val dx = layout.screenWidth / (value.size + 1)
|
val dx = layout.screenWidth / (baseValue.size + 1)
|
||||||
val height = -value[i].map(range.start, range.endInclusive, -1.0, 1.0).coerceIn(-1.0, 1.0) * controlArea.height / 2.0
|
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)
|
val x = dx * (i + 1)
|
||||||
drawer.lineCap = LineCap.ROUND
|
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
|
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") {
|
styleSheet(has type "colorpicker") {
|
||||||
height = 80.px
|
height = 80.px
|
||||||
|
|||||||
@@ -115,6 +115,36 @@ annotation class XYParameter(
|
|||||||
val order: Int = Integer.MAX_VALUE
|
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
|
* ActionParameter annotation for functions without arguments
|
||||||
* @property label a short description of the parameter
|
* @property label a short description of the parameter
|
||||||
@@ -134,7 +164,10 @@ enum class ParameterType(val annotationClass: KClass<out Annotation>) {
|
|||||||
Text(TextParameter::class),
|
Text(TextParameter::class),
|
||||||
Color(ColorParameter::class),
|
Color(ColorParameter::class),
|
||||||
XY(XYParameter::class),
|
XY(XYParameter::class),
|
||||||
DoubleList(DoubleListParameter::class)
|
DoubleList(DoubleListParameter::class),
|
||||||
|
Vector2(Vector2Parameter::class),
|
||||||
|
Vector3(Vector3Parameter::class),
|
||||||
|
Vector4(Vector4Parameter::class)
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -236,7 +269,24 @@ fun Any.listParameters(): List<Parameter> {
|
|||||||
doubleRange = it.low..it.high
|
doubleRange = it.low..it.high
|
||||||
precision = it.precision
|
precision = it.precision
|
||||||
sizeRange = it.minimumListLength..it.maximumListLength
|
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.color.ColorRGBa
|
||||||
import org.openrndr.extra.parameters.*
|
import org.openrndr.extra.parameters.*
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
|
import org.openrndr.math.Vector3
|
||||||
|
import org.openrndr.math.Vector4
|
||||||
import org.spekframework.spek2.Spek
|
import org.spekframework.spek2.Spek
|
||||||
import org.spekframework.spek2.style.specification.describe
|
import org.spekframework.spek2.style.specification.describe
|
||||||
|
|
||||||
@@ -31,13 +33,24 @@ val a = object {
|
|||||||
|
|
||||||
@DoubleListParameter("a double list parameter", order = 7)
|
@DoubleListParameter("a double list parameter", order = 7)
|
||||||
var dl = mutableListOf<Double>()
|
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({
|
object TestAnnotations : Spek({
|
||||||
describe("an annotated object") {
|
describe("an annotated object") {
|
||||||
it("has listable parameters") {
|
it("has listable parameters") {
|
||||||
val list = a.listParameters()
|
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].property?.name `should be equal to` "d"
|
||||||
list[0].parameterType `should be equal to` ParameterType.Double
|
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].parameterType `should be equal to` ParameterType.DoubleList
|
||||||
list[7].property?.name `should be equal to` "dl"
|
list[7].property?.name `should be equal to` "dl"
|
||||||
list[7].label `should be equal to` "a double list parameter"
|
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