New properties #34
@ -3,6 +3,7 @@ package ru.mipt.npm.sat
|
||||
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vision.solid.Solid
|
||||
import hep.dataforge.vision.solid.clear
|
||||
import hep.dataforge.vision.solid.color
|
||||
import hep.dataforge.vision.solid.invoke
|
||||
import hep.dataforge.vision.three.server.*
|
||||
@ -42,7 +43,7 @@ fun main() {
|
||||
val targetVision = sat[target] as Solid
|
||||
targetVision.color("red")
|
||||
delay(300)
|
||||
targetVision.color("darkgreen")
|
||||
targetVision.color.clear()
|
||||
delay(10)
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,9 @@ public interface Vision : Described {
|
||||
*/
|
||||
public fun setProperty(name: Name, item: MetaItem<*>?, notify: Boolean = true)
|
||||
|
||||
/**
|
||||
* Subscribe on property updates. The subscription is bound to the given [scope] and canceled when the scope is canceled
|
||||
*/
|
||||
public fun onPropertyChange(scope: CoroutineScope, callback: suspend (Name) -> Unit)
|
||||
|
||||
/**
|
||||
@ -81,7 +84,7 @@ public interface Vision : Described {
|
||||
public suspend fun notifyPropertyChanged(propertyName: Name): Unit
|
||||
|
||||
/**
|
||||
* Update this vision using external meta. Children are not updated.
|
||||
* Update this vision using a dif represented by [VisionChange].
|
||||
*/
|
||||
public fun update(change: VisionChange)
|
||||
|
||||
|
@ -3,12 +3,14 @@ package hep.dataforge.vision
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.MutableMeta
|
||||
import hep.dataforge.meta.asMetaItem
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.descriptors.defaultItem
|
||||
import hep.dataforge.meta.descriptors.get
|
||||
import hep.dataforge.meta.update
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.values.Null
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.vision.Vision.Companion.STYLE_KEY
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -27,6 +29,7 @@ internal data class PropertyListener(
|
||||
val action: (name: Name) -> Unit,
|
||||
)
|
||||
|
||||
|
||||
@Serializable
|
||||
@SerialName("vision")
|
||||
public open class VisionBase : Vision {
|
||||
@ -100,6 +103,8 @@ public open class VisionBase : Vision {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TODO check memory consumption for the flow
|
||||
@Transient
|
||||
private val propertyInvalidationFlow: MutableSharedFlow<Name> = MutableSharedFlow()
|
||||
|
||||
@ -116,13 +121,30 @@ public open class VisionBase : Vision {
|
||||
propertyInvalidationFlow.emit(propertyName)
|
||||
}
|
||||
|
||||
public fun configure(block: MutableMeta<*>.() -> Unit) {
|
||||
public fun configure(block: suspend MutableMeta<*>.() -> Unit) {
|
||||
scope.launch {
|
||||
getOrCreateConfig().block()
|
||||
}
|
||||
}
|
||||
|
||||
override fun update(change: VisionChange) {
|
||||
|
||||
fun updateProperties(at: Name, item: MetaItem<*>) {
|
||||
when (item) {
|
||||
is MetaItem.ValueItem -> {
|
||||
if (item.value == Null) {
|
||||
setProperty(at, null)
|
||||
} else
|
||||
setProperty(at, item)
|
||||
}
|
||||
is MetaItem.NodeItem -> item.node.items.forEach { (token, childItem) ->
|
||||
updateProperties(at + token, childItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
change.properties?.let {
|
||||
getOrCreateConfig().update(it)
|
||||
updateProperties(Name.EMPTY, it.asMetaItem())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package hep.dataforge.vision
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.values.Null
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
@ -30,7 +31,8 @@ public class VisionChangeBuilder : VisionContainerBuilder<Vision> {
|
||||
|
||||
public fun propertyChanged(visionName: Name, propertyName: Name, item: MetaItem<*>?) {
|
||||
if (visionName == Name.EMPTY) {
|
||||
propertyChange[propertyName] = item
|
||||
//Write property removal as [Null]
|
||||
propertyChange[propertyName] = (item ?: Null.asMetaItem())
|
||||
} else {
|
||||
getOrPutChild(visionName).propertyChanged(Name.EMPTY, propertyName, item)
|
||||
}
|
||||
@ -112,6 +114,10 @@ public fun Vision.flowChanges(
|
||||
coroutineScope {
|
||||
collectChange(Name.EMPTY, this@flowChanges) { collector }
|
||||
|
||||
//Send initial vision state
|
||||
val initialChange = VisionChange(vision = isolate(manager))
|
||||
emit(initialChange)
|
||||
|
||||
while (currentCoroutineContext().isActive) {
|
||||
//Wait for changes to accumulate
|
||||
delay(collectionDuration)
|
||||
|
@ -134,14 +134,6 @@ public class VisionServer internal constructor(
|
||||
|
||||
try {
|
||||
withContext(visionManager.context.coroutineContext) {
|
||||
|
||||
val initialVision = VisionChange(vision = vision)
|
||||
val initialJson = visionManager.jsonFormat.encodeToString(
|
||||
VisionChange.serializer(),
|
||||
initialVision
|
||||
)
|
||||
outgoing.send(Frame.Text(initialJson))
|
||||
|
||||
vision.flowChanges(visionManager, updateInterval.milliseconds).collect { update ->
|
||||
val json = visionManager.jsonFormat.encodeToString(
|
||||
VisionChange.serializer(),
|
||||
|
@ -0,0 +1,51 @@
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.MutableItemProvider
|
||||
import hep.dataforge.meta.set
|
||||
import hep.dataforge.meta.value
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.asValue
|
||||
import hep.dataforge.values.string
|
||||
import hep.dataforge.vision.Colors
|
||||
import hep.dataforge.vision.VisionBuilder
|
||||
|
||||
@VisionBuilder
|
||||
public class ColorAccessor(private val parent: MutableItemProvider, private val colorKey: Name) {
|
||||
public var value: Value?
|
||||
get() = parent.getItem(colorKey).value
|
||||
set(value) {
|
||||
parent[colorKey] = value
|
||||
}
|
||||
}
|
||||
|
||||
public var ColorAccessor?.string: String?
|
||||
get() = this?.value?.string
|
||||
set(value) {
|
||||
this?.value = value?.asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(webColor: String) {
|
||||
this?.value = webColor.asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color as RGB integer
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(rgb: Int) {
|
||||
this?.value = Colors.rgbToString(rgb).asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color as RGB
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(r: UByte, g: UByte, b: UByte) {
|
||||
this?.value = Colors.rgbToString(r, g, b).asValue()
|
||||
}
|
||||
|
||||
public fun ColorAccessor?.clear(){
|
||||
this?.value = null
|
||||
}
|
@ -6,51 +6,13 @@ import hep.dataforge.meta.descriptors.attributes
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.values.asValue
|
||||
import hep.dataforge.values.string
|
||||
import hep.dataforge.vision.*
|
||||
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
|
||||
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_KEY
|
||||
import hep.dataforge.vision.solid.SolidMaterial.Companion.MATERIAL_OPACITY_KEY
|
||||
|
||||
@VisionBuilder
|
||||
public class ColorAccessor(private val parent: MutableItemProvider, private val colorKey: Name) {
|
||||
public var value: Value?
|
||||
get() = parent.getItem(colorKey).value
|
||||
set(value) {
|
||||
parent[colorKey] = value
|
||||
}
|
||||
}
|
||||
|
||||
public var ColorAccessor?.string: String?
|
||||
get() = this?.value?.string
|
||||
set(value) {
|
||||
this?.value = value?.asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [webcolor](https://en.wikipedia.org/wiki/Web_colors) as string
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(webColor: String) {
|
||||
this?.value = webColor.asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color as RGB integer
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(rgb: Int) {
|
||||
this?.value = Colors.rgbToString(rgb).asValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color as RGB
|
||||
*/
|
||||
public operator fun ColorAccessor?.invoke(r: UByte, g: UByte, b: UByte) {
|
||||
this?.value = Colors.rgbToString(r, g, b).asValue()
|
||||
}
|
||||
|
||||
@VisionBuilder
|
||||
public class SolidMaterial : Scheme() {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user