forked from kscience/visionforge
Server is alive!
This commit is contained in:
parent
faddb8a393
commit
6a742658af
@ -2,7 +2,7 @@ plugins {
|
||||
id("ru.mipt.npm.project")
|
||||
}
|
||||
|
||||
val dataforgeVersion by extra("0.2.0")
|
||||
val dataforgeVersion by extra("0.2.1-dev-4")
|
||||
val ktorVersion by extra("1.4.2")
|
||||
val htmlVersion by extra("0.7.2")
|
||||
val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20")
|
||||
|
@ -3,8 +3,8 @@ package ru.mipt.npm.sat
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vision.VisionManager
|
||||
import hep.dataforge.vision.get
|
||||
import hep.dataforge.vision.server.close
|
||||
import hep.dataforge.vision.server.serve
|
||||
import hep.dataforge.vision.server.show
|
||||
@ -40,11 +40,12 @@ fun main() {
|
||||
vision("main".asName(), sat)
|
||||
}
|
||||
launch {
|
||||
delay(1000)
|
||||
while (isActive) {
|
||||
val currentLayer = Random.nextInt(10)
|
||||
(sat["layer[$currentLayer]"] as? Solid)?.color(123)
|
||||
val target = "layer[${Random.nextInt(1,10)}].segment[${Random.nextInt(3)},${Random.nextInt(3)}]".toName()
|
||||
(sat[target] as? Solid)?.color("red")
|
||||
delay(300)
|
||||
(sat["layer[$currentLayer]"] as? Solid)?.color = null
|
||||
(sat[target] as? Solid)?.color = "green"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package hep.dataforge.vision
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.number
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.values.int
|
||||
import hep.dataforge.values.string
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
|
@ -3,10 +3,9 @@ package hep.dataforge.vision
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.plus
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.serialization.*
|
||||
@ -15,7 +14,7 @@ import kotlin.time.Duration
|
||||
/**
|
||||
* An update for a [Vision] or a [VisionGroup]
|
||||
*/
|
||||
public class VisionChangeBuilder: VisionContainerBuilder<Vision> {
|
||||
public class VisionChangeBuilder : VisionContainerBuilder<Vision> {
|
||||
private val propertyChange = HashMap<Name, Config>()
|
||||
private val childrenChange = HashMap<Name, Vision?>()
|
||||
|
||||
@ -47,7 +46,8 @@ private fun Vision.isolate(manager: VisionManager): Vision {
|
||||
@Serializable
|
||||
public data class VisionChange(
|
||||
val propertyChange: Map<Name, @Serializable(MetaSerializer::class) Meta>,
|
||||
val childrenChange: Map<Name, Vision?>) {
|
||||
val childrenChange: Map<Name, Vision?>,
|
||||
) {
|
||||
public fun isEmpty(): Boolean = propertyChange.isEmpty() && childrenChange.isEmpty()
|
||||
|
||||
/**
|
||||
@ -64,7 +64,7 @@ private fun CoroutineScope.collectChange(
|
||||
name: Name,
|
||||
source: Vision,
|
||||
mutex: Mutex,
|
||||
collector: ()->VisionChangeBuilder,
|
||||
collector: () -> VisionChangeBuilder,
|
||||
) {
|
||||
//Collect properties change
|
||||
source.config.onChange(mutex) { propertyName, oldItem, newItem ->
|
||||
@ -107,17 +107,19 @@ public fun Vision.flowChanges(
|
||||
val mutex = Mutex()
|
||||
|
||||
var collector = VisionChangeBuilder()
|
||||
scope.collectChange(Name.EMPTY, this@flowChanges, mutex){collector}
|
||||
scope.collectChange(Name.EMPTY, this@flowChanges, mutex) { collector }
|
||||
|
||||
while (true) {
|
||||
while (currentCoroutineContext().isActive) {
|
||||
//Wait for changes to accumulate
|
||||
kotlinx.coroutines.delay(collectionDuration)
|
||||
delay(collectionDuration)
|
||||
//Propagate updates only if something is changed
|
||||
if (!collector.isEmpty()) {
|
||||
//emit changes
|
||||
emit(collector.isolate(manager))
|
||||
//Reset the collector
|
||||
collector = VisionChangeBuilder()
|
||||
mutex.withLock {
|
||||
emit(collector.isolate(manager))
|
||||
//Reset the collector
|
||||
collector = VisionChangeBuilder()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.Null
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.asValue
|
||||
import hep.dataforge.values.string
|
||||
import javafx.scene.control.ColorPicker
|
||||
import javafx.scene.paint.Color
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -22,7 +23,7 @@ public class ColorValueChooser : ValueChooserBase<ColorPicker>() {
|
||||
this.value = Color.valueOf(value.string)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
LoggerFactory.getLogger(javaClass).warn("Invalid color field value: " + value.string)
|
||||
LoggerFactory.getLogger(javaClass).warn("Invalid color field value: $value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.parseValue
|
||||
import hep.dataforge.values.string
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.scene.control.ComboBox
|
||||
import javafx.util.StringConverter
|
||||
|
@ -17,6 +17,7 @@
|
||||
package hep.dataforge.vision.editor
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.values.string
|
||||
import hep.dataforge.vision.dfIconView
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.scene.control.TreeItem
|
||||
|
@ -5,38 +5,40 @@ import hep.dataforge.meta.double
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.int
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.values.int
|
||||
import hep.dataforge.values.string
|
||||
import hep.dataforge.vision.Colors
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.paint.Material
|
||||
import javafx.scene.paint.PhongMaterial
|
||||
|
||||
object FXMaterials {
|
||||
val RED = PhongMaterial().apply {
|
||||
public object FXMaterials {
|
||||
public val RED: PhongMaterial = PhongMaterial().apply {
|
||||
diffuseColor = Color.DARKRED
|
||||
specularColor = Color.WHITE
|
||||
}
|
||||
|
||||
val WHITE = PhongMaterial().apply {
|
||||
public val WHITE: PhongMaterial = PhongMaterial().apply {
|
||||
diffuseColor = Color.WHITE
|
||||
specularColor = Color.LIGHTBLUE
|
||||
}
|
||||
|
||||
val GREY = PhongMaterial().apply {
|
||||
public val GREY: PhongMaterial = PhongMaterial().apply {
|
||||
diffuseColor = Color.DARKGREY
|
||||
specularColor = Color.WHITE
|
||||
}
|
||||
|
||||
val BLUE = PhongMaterial(Color.BLUE)
|
||||
public val BLUE: PhongMaterial = PhongMaterial(Color.BLUE)
|
||||
}
|
||||
|
||||
/**
|
||||
* Infer color based on meta item
|
||||
* @param opacity default opacity
|
||||
*/
|
||||
fun MetaItem<*>.color(opacity: Double = 1.0): Color {
|
||||
public fun MetaItem<*>.color(opacity: Double = 1.0): Color {
|
||||
return when (this) {
|
||||
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) {
|
||||
val int = value.number.toInt()
|
||||
val int = value.int
|
||||
val red = int and 0x00ff0000 shr 16
|
||||
val green = int and 0x0000ff00 shr 8
|
||||
val blue = int and 0x000000ff
|
||||
|
@ -37,7 +37,9 @@ import io.ktor.util.error
|
||||
import io.ktor.websocket.WebSockets
|
||||
import io.ktor.websocket.webSocket
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.html.*
|
||||
import kotlinx.html.stream.createHTML
|
||||
import java.awt.Desktop
|
||||
@ -115,15 +117,12 @@ public class VisionServer internal constructor(
|
||||
|
||||
application.log.debug("Opened server socket for $name")
|
||||
val vision: Vision = visions[name.toName()] ?: error("Plot with id='$name' not registered")
|
||||
try {
|
||||
vision.flowChanges(visionManager, updateInterval.milliseconds).collect { update ->
|
||||
val json = VisionManager.defaultJson.encodeToString(VisionChange.serializer(), update)
|
||||
outgoing.send(Frame.Text(json))
|
||||
}
|
||||
} catch (ex: Throwable) {
|
||||
application.log.error("Closed server socket for $name with exception $ex")
|
||||
vision.flowChanges(visionManager, updateInterval.milliseconds).onEach { update ->
|
||||
val json = VisionManager.defaultJson.encodeToString(VisionChange.serializer(), update)
|
||||
outgoing.send(Frame.Text(json))
|
||||
}.catch { ex ->
|
||||
application.log.error(ex)
|
||||
}
|
||||
}.launchIn(visionManager.context).join()
|
||||
}
|
||||
//Plots in their json representation
|
||||
get("vision") {
|
||||
@ -208,7 +207,7 @@ public fun Application.visionModule(context: Context, route: String = DEFAULT_PA
|
||||
public fun VisionManager.serve(
|
||||
host: String = "localhost",
|
||||
port: Int = 7777,
|
||||
block: VisionServer.()->Unit
|
||||
block: VisionServer.() -> Unit,
|
||||
): ApplicationEngine = context.embeddedServer(CIO, port, host) {
|
||||
visionModule(context).apply(block)
|
||||
}.start()
|
||||
|
@ -2,6 +2,8 @@ package hep.dataforge.vision.solid.three
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.values.int
|
||||
import hep.dataforge.values.string
|
||||
import hep.dataforge.vision.Colors
|
||||
import hep.dataforge.vision.Vision
|
||||
import hep.dataforge.vision.solid.SolidMaterial
|
||||
@ -90,7 +92,7 @@ public object ThreeMaterials {
|
||||
public fun MetaItem<*>.getColor(): Color {
|
||||
return when (this) {
|
||||
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) {
|
||||
val int = value.number.toInt()
|
||||
val int = value.int
|
||||
Color(int)
|
||||
} else {
|
||||
Color(this.value.string)
|
||||
|
Loading…
Reference in New Issue
Block a user