Add Vector2/Vector3/Vector4 parameters and controls
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user