Gui: add .toObject() .fromObject() (#126)
Split .loadParameters() .saveParameters() in two This allows the user to read / write the gui state and serialize it externally.
This commit is contained in:
72
orx-gui/src/demo/kotlin/DemoPresets01.kt
Normal file
72
orx-gui/src/demo/kotlin/DemoPresets01.kt
Normal file
@@ -0,0 +1,72 @@
|
||||
import org.openrndr.application
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.color.mix
|
||||
import org.openrndr.extensions.SingleScreenshot
|
||||
import org.openrndr.extra.gui.GUI
|
||||
import org.openrndr.extra.parameters.*
|
||||
|
||||
/**
|
||||
* Shows how to store and retrieve in-memory gui presets.
|
||||
* Keyboard controls:
|
||||
* [Left Shift] + [0]..[9] => store current gui values to a preset
|
||||
* [0]..[9] => recall a preset
|
||||
*/
|
||||
fun main() = application {
|
||||
program {
|
||||
// -- this block is for automation purposes only
|
||||
if (System.getProperty("takeScreenshot") == "true") {
|
||||
extend(SingleScreenshot()) {
|
||||
this.outputFile = System.getProperty("screenshotPath")
|
||||
}
|
||||
}
|
||||
|
||||
val gui = GUI()
|
||||
gui.compartmentsCollapsedByDefault = false
|
||||
|
||||
val presets = MutableList(10) {
|
||||
gui.toObject()
|
||||
}
|
||||
|
||||
val settings = @Description("Settings") object {
|
||||
@IntParameter("a", 1, 10)
|
||||
var a = 7
|
||||
|
||||
@IntParameter("b", 1, 10)
|
||||
var b = 3
|
||||
|
||||
@ColorParameter("foreground")
|
||||
var foreground = ColorRGBa.fromHex("654062")
|
||||
|
||||
@ColorParameter("background")
|
||||
var background = ColorRGBa.fromHex("ff9c71")
|
||||
}
|
||||
gui.add(settings)
|
||||
extend(gui)
|
||||
extend {
|
||||
drawer.clear(settings.background)
|
||||
drawer.stroke = settings.background
|
||||
drawer.fill = settings.foreground
|
||||
// Draw a pattern based on modulo
|
||||
for(i in 0 until 100) {
|
||||
if(i % settings.a == 0 || i % settings.b == 0) {
|
||||
val x = (i % 10) * 64.0
|
||||
val y = (i / 10) * 48.0
|
||||
drawer.rectangle(x, y, 64.0, 48.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
keyboard.keyDown.listen {
|
||||
when (it.name) {
|
||||
in "0" .. "9" -> {
|
||||
if(keyboard.pressedKeys.contains("left-shift")) {
|
||||
// 1. Get the current gui state, store it in a list
|
||||
presets[it.name.toInt()] = gui.toObject()
|
||||
} else {
|
||||
// 2. Set the gui state
|
||||
gui.fromObject(presets[it.name.toInt()])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,7 @@ package org.openrndr.extra.gui
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import org.openrndr.Extension
|
||||
import org.openrndr.KEY_F11
|
||||
import org.openrndr.KEY_LEFT_SHIFT
|
||||
import org.openrndr.KeyModifier
|
||||
import org.openrndr.Program
|
||||
import org.openrndr.*
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.dialogs.getDefaultPathForContext
|
||||
import org.openrndr.dialogs.openFileDialog
|
||||
@@ -22,8 +18,6 @@ import org.openrndr.panel.ControlManager
|
||||
import org.openrndr.panel.controlManager
|
||||
import org.openrndr.panel.elements.*
|
||||
import org.openrndr.panel.style.*
|
||||
import org.openrndr.panel.styleSheet
|
||||
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
@@ -631,7 +625,7 @@ class GUI : Extension {
|
||||
}
|
||||
}
|
||||
|
||||
private class ParameterValue(var doubleValue: Double? = null,
|
||||
class ParameterValue(var doubleValue: Double? = null,
|
||||
var intValue: Int? = null,
|
||||
var booleanValue: Boolean? = null,
|
||||
var colorValue: ColorRGBa? = null,
|
||||
@@ -644,16 +638,20 @@ class GUI : Extension {
|
||||
|
||||
)
|
||||
|
||||
|
||||
fun saveParameters(file: File) {
|
||||
/**
|
||||
* Can be called by the user to obtain an object to be serialized
|
||||
* externally. This allows the user to combine custom data with gui
|
||||
* state and save it all to one file. Complements `.fromObject()`.
|
||||
*/
|
||||
fun toObject(): Map<String, Map<String, ParameterValue>> {
|
||||
fun <T> KMutableProperty1<out Any, Any?>?.qget(obj: Any): T {
|
||||
return (this as KMutableProperty1<Any, T>).get(obj)
|
||||
}
|
||||
|
||||
val toSave =
|
||||
trackedObjects.entries.associate { (lo, b) ->
|
||||
return trackedObjects.entries.associate { (lo, b) ->
|
||||
Pair(lo.label, b.parameterControls.keys.associate { k ->
|
||||
Pair(k.property?.name ?: k.function?.name ?: error("no name"), when (k.parameterType) {
|
||||
Pair(k.property?.name ?: k.function?.name
|
||||
?: error("no name"), when (k.parameterType) {
|
||||
/* 3) setup serializers */
|
||||
ParameterType.Double -> ParameterValue(doubleValue = k.property.qget(lo.obj) as Double)
|
||||
ParameterType.Int -> ParameterValue(intValue = k.property.qget(lo.obj) as Int)
|
||||
@@ -670,10 +668,19 @@ class GUI : Extension {
|
||||
})
|
||||
})
|
||||
}
|
||||
file.writeText(Gson().toJson(toSave))
|
||||
}
|
||||
|
||||
fun loadParameters(file: File) {
|
||||
fun saveParameters(file: File) {
|
||||
file.writeText(Gson().toJson(toObject()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be called by the user to update the gui using an object
|
||||
* deserialized externally. Allows the user to load a larger json object,
|
||||
* deserialize it, and use part of it to update the GUI.
|
||||
* Complements `.toObject()`.
|
||||
*/
|
||||
fun fromObject(labeledValues: Map<String, Map<String, ParameterValue>>) {
|
||||
fun <T> KMutableProperty1<out Any, Any?>?.qset(obj: Any, value: T) =
|
||||
(this as KMutableProperty1<Any, T>).set(obj, value)
|
||||
|
||||
@@ -686,10 +693,6 @@ class GUI : Extension {
|
||||
(this as KMutableProperty1<Any, Enum<*>>).set(obj, enumValue)
|
||||
}
|
||||
|
||||
val json = file.readText()
|
||||
val typeToken = object : TypeToken<Map<String, Map<String, ParameterValue>>>() {}
|
||||
val labeledValues: Map<String, Map<String, ParameterValue>> = Gson().fromJson(json, typeToken.type)
|
||||
|
||||
labeledValues.forEach { (label, ps) ->
|
||||
trackedObjects.keys.find { it.label == label }?.let { lo ->
|
||||
val binding = trackedObjects[lo]!!
|
||||
@@ -741,6 +744,14 @@ class GUI : Extension {
|
||||
updateControls()
|
||||
}
|
||||
|
||||
fun loadParameters(file: File) {
|
||||
val json = file.readText()
|
||||
val typeToken = object : TypeToken<Map<String, Map<String, ParameterValue>>>() {}
|
||||
val labeledValues: Map<String, Map<String, ParameterValue>> = Gson().fromJson(json, typeToken.type)
|
||||
|
||||
fromObject(labeledValues)
|
||||
}
|
||||
|
||||
private fun updateControl(labeledObject: LabeledObject, parameter: Parameter, control: Element) {
|
||||
when (parameter.parameterType) {
|
||||
/* 5) Update control from property value */
|
||||
|
||||
Reference in New Issue
Block a user