All tests pass
This commit is contained in:
parent
9221df785d
commit
0ea1ee056a
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project")
|
id("space.kscience.gradle.project")
|
||||||
// id("org.jetbrains.kotlinx.kover") version "0.5.0"
|
// id("org.jetbrains.kotlinx.kover") version "0.5.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
kscience{
|
kscience{
|
||||||
|
@ -321,7 +321,7 @@ private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid?
|
|||||||
}
|
}
|
||||||
return if (group.children.isEmpty()) {
|
return if (group.children.isEmpty()) {
|
||||||
null
|
null
|
||||||
} else if (group.items.size == 1 && group.properties.raw == null) {
|
} else if (group.items.size == 1 && group.properties.own == null) {
|
||||||
group.items.values.first().apply { parent = null }
|
group.items.values.first().apply { parent = null }
|
||||||
} else {
|
} else {
|
||||||
group
|
group
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import ru.mipt.npm.gradle.DependencyConfiguration
|
import space.kscience.gradle.DependencyConfiguration
|
||||||
import ru.mipt.npm.gradle.FXModule
|
import space.kscience.gradle.FXModule
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ kotlin {
|
|||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":visionforge-fx"))
|
implementation(project(":visionforge-fx"))
|
||||||
implementation("ch.qos.logback:logback-classic:1.2.5")
|
implementation("ch.qos.logback:logback-classic:1.2.11")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jsMain {
|
jsMain {
|
||||||
|
@ -6,7 +6,6 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.gdml.GdmlShowCase
|
import space.kscience.gdml.GdmlShowCase
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.get
|
import space.kscience.visionforge.get
|
||||||
import space.kscience.visionforge.getPropertyValue
|
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
import space.kscience.visionforge.solid.material
|
import space.kscience.visionforge.solid.material
|
||||||
@ -20,7 +19,7 @@ class GDMLVisionTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testCubesStyles(){
|
fun testCubesStyles(){
|
||||||
val segment = cubes.children["composite-000.segment-0"] as Solid
|
val segment = cubes.children["composite-000.segment-0"] as Solid
|
||||||
println(segment.getPropertyValue(Vision.STYLE_KEY))
|
println(segment.properties.getValue(Vision.STYLE_KEY))
|
||||||
// println(segment.computePropertyNode(SolidMaterial.MATERIAL_KEY))
|
// println(segment.computePropertyNode(SolidMaterial.MATERIAL_KEY))
|
||||||
// println(segment.computeProperty(SolidMaterial.MATERIAL_COLOR_KEY))
|
// println(segment.computeProperty(SolidMaterial.MATERIAL_COLOR_KEY))
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ class GDMLVisionTest {
|
|||||||
fun testPrototypeProperty() {
|
fun testPrototypeProperty() {
|
||||||
val child = cubes[Name.of("composite-000","segment-0")]
|
val child = cubes[Name.of("composite-000","segment-0")]
|
||||||
assertNotNull(child)
|
assertNotNull(child)
|
||||||
child.setPropertyValue(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
|
child.properties.setValue(SolidMaterial.MATERIAL_COLOR_KEY, "red".asValue())
|
||||||
assertEquals("red", child.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string)
|
assertEquals("red", child.properties.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).string)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,6 +26,7 @@ import space.kscience.visionforge.setAsRoot
|
|||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.Solids
|
import space.kscience.visionforge.solid.Solids
|
||||||
import space.kscience.visionforge.solid.ambientLight
|
import space.kscience.visionforge.solid.ambientLight
|
||||||
|
import space.kscience.visionforge.solid.set
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ val GDMLApp = fc<GDMLAppProps>("GDMLApp") { props ->
|
|||||||
console.info("Marking layers for file $name")
|
console.info("Marking layers for file $name")
|
||||||
markLayers()
|
markLayers()
|
||||||
ambientLight {
|
ambientLight {
|
||||||
color(Colors.white)
|
color.set(Colors.white)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import space.kscience.visionforge.Colors
|
|||||||
import space.kscience.visionforge.gdml.toVision
|
import space.kscience.visionforge.gdml.toVision
|
||||||
import space.kscience.visionforge.react.render
|
import space.kscience.visionforge.react.render
|
||||||
import space.kscience.visionforge.solid.ambientLight
|
import space.kscience.visionforge.solid.ambientLight
|
||||||
|
import space.kscience.visionforge.solid.set
|
||||||
import space.kscience.visionforge.solid.three.ThreePlugin
|
import space.kscience.visionforge.solid.three.ThreePlugin
|
||||||
import space.kscience.visionforge.startApplication
|
import space.kscience.visionforge.startApplication
|
||||||
import styled.injectGlobal
|
import styled.injectGlobal
|
||||||
@ -46,7 +47,7 @@ private class GDMLDemoApp : Application {
|
|||||||
child(GDMLApp) {
|
child(GDMLApp) {
|
||||||
val vision = GdmlShowCase.cubes().toVision().apply {
|
val vision = GdmlShowCase.cubes().toVision().apply {
|
||||||
ambientLight {
|
ambientLight {
|
||||||
color(Colors.white)
|
color.set(Colors.white)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
|
//println(context.plugins.fetch(VisionManager).encodeToString(vision))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.js")
|
id("space.kscience.gradle.js")
|
||||||
}
|
}
|
||||||
|
|
||||||
kscience{
|
kscience{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class Model(val manager: VisionManager) {
|
|||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
map.values.forEach {
|
map.values.forEach {
|
||||||
it.properties[SolidMaterial.MATERIAL_COLOR_KEY] = null
|
it.properties.setProperty(SolidMaterial.MATERIAL_COLOR_KEY, null)
|
||||||
}
|
}
|
||||||
tracks.children.clear()
|
tracks.children.clear()
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import space.kscience.visionforge.react.flexRow
|
|||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
import space.kscience.visionforge.ring.tab
|
import space.kscience.visionforge.ring.tab
|
||||||
import space.kscience.visionforge.solid.ambientLight
|
import space.kscience.visionforge.solid.ambientLight
|
||||||
|
import space.kscience.visionforge.solid.set
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.edges
|
import space.kscience.visionforge.solid.three.edges
|
||||||
import styled.css
|
import styled.css
|
||||||
@ -57,7 +58,7 @@ val MMApp = fc<MMAppProps>("Muon monitor") { props ->
|
|||||||
props.model.root.apply {
|
props.model.root.apply {
|
||||||
edges()
|
edges()
|
||||||
ambientLight{
|
ambientLight{
|
||||||
color(Colors.white)
|
color.set(Colors.white)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ private class MMDemoApp : Application {
|
|||||||
val context = Context("MM-demo") {
|
val context = Context("MM-demo") {
|
||||||
plugin(ThreePlugin)
|
plugin(ThreePlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
val visionManager = context.fetch(VisionManager)
|
val visionManager = context.fetch(VisionManager)
|
||||||
|
|
||||||
val model = Model(visionManager)
|
val model = Model(visionManager)
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
|
<!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">-->
|
||||||
<title>Three js demo for particle physics</title>
|
<title>Three js demo for particle physics</title>
|
||||||
<script type="text/javascript" src="muon-monitor.js"></script>
|
<script type="text/javascript" src="muon-monitor.js"></script>
|
||||||
<link rel="stylesheet" href="css/custom-bootstrap.css">
|
|
||||||
</head>
|
</head>
|
||||||
<body class="application">
|
<body class="application">
|
||||||
<div class="container-fluid max-vh-100" id = "app"> </div>
|
<div class="container-fluid max-vh-100" id = "app"> </div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.jvm")
|
id("space.kscience.gradle.jvm")
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import ru.mipt.npm.gradle.DependencyConfiguration
|
import space.kscience.gradle.DependencyConfiguration
|
||||||
import ru.mipt.npm.gradle.FXModule
|
import space.kscience.gradle.FXModule
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import info.laht.threekt.core.Object3D
|
|||||||
import info.laht.threekt.geometries.BoxGeometry
|
import info.laht.threekt.geometries.BoxGeometry
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
import space.kscience.dataforge.meta.asValue
|
import space.kscience.dataforge.meta.asValue
|
||||||
import space.kscience.dataforge.meta.get
|
|
||||||
import space.kscience.dataforge.meta.int
|
import space.kscience.dataforge.meta.int
|
||||||
import space.kscience.dataforge.meta.number
|
import space.kscience.dataforge.meta.number
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
@ -43,13 +42,13 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
|
|||||||
it.layers.enable(this@VariableBox.layer)
|
it.layers.enable(this@VariableBox.layer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mesh.scale.z = meta[VALUE].number?.toDouble() ?: 1.0
|
mesh.scale.z = properties.getValue(VALUE)?.number?.toDouble() ?: 1.0
|
||||||
|
|
||||||
//add listener to object properties
|
//add listener to object properties
|
||||||
onPropertyChange { name ->
|
onPropertyChange { name ->
|
||||||
when {
|
when {
|
||||||
name == VALUE -> {
|
name == VALUE -> {
|
||||||
val value = meta[VALUE].int ?: 0
|
val value = properties.getValue(VALUE)?.int ?: 0
|
||||||
val size = value.toFloat() / 255f * 20f
|
val size = value.toFloat() / 255f * 20f
|
||||||
mesh.scale.z = size.toDouble()
|
mesh.scale.z = size.toDouble()
|
||||||
mesh.position.z = size.toDouble() / 2
|
mesh.position.z = size.toDouble() / 2
|
||||||
@ -69,9 +68,9 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision
|
|||||||
}
|
}
|
||||||
|
|
||||||
var value: Int
|
var value: Int
|
||||||
get() = meta[VALUE].int ?: 0
|
get() = properties.getValue(VALUE)?.int ?: 0
|
||||||
set(value) {
|
set(value) {
|
||||||
setPropertyValue(VALUE, value.asValue())
|
properties.setValue(VALUE, value.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -6,4 +6,4 @@ kotlin.jupyter.add.scanner=false
|
|||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
org.gradle.jvmargs=-Xmx4G
|
org.gradle.jvmargs=-Xmx4G
|
||||||
|
|
||||||
toolsVersion=0.11.8-kotlin-1.7.10
|
toolsVersion=0.12.0-kotlin-1.7.20-Beta
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
id("org.jetbrains.kotlin.jupyter.api")
|
id("org.jetbrains.kotlin.jupyter.api")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,5 +21,5 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
description = "Jupyter api artifact for GDML rendering"
|
description = "Jupyter api artifact for GDML rendering"
|
||||||
@ -56,5 +56,5 @@ kscience {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
||||||
}
|
}
|
@ -15,10 +15,10 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project") version toolsVersion
|
id("space.kscience.gradle.project") version toolsVersion
|
||||||
id("ru.mipt.npm.gradle.mpp") version toolsVersion
|
id("space.kscience.gradle.mpp") version toolsVersion
|
||||||
id("ru.mipt.npm.gradle.jvm") version toolsVersion
|
id("space.kscience.gradle.jvm") version toolsVersion
|
||||||
id("ru.mipt.npm.gradle.js") version toolsVersion
|
id("space.kscience.gradle.js") version toolsVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ dependencyResolutionManagement {
|
|||||||
|
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
create("npmlibs") {
|
create("npmlibs") {
|
||||||
from("ru.mipt.npm:version-catalog:$toolsVersion")
|
from("space.kscience:version-catalog:$toolsVersion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
kotlin("js")
|
kotlin("js")
|
||||||
id("ru.mipt.npm.gradle.js")
|
id("space.kscience.gradle.js")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion: String by rootProject.extra
|
val dataforgeVersion: String by rootProject.extra
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package space.kscience.visionforge.bootstrap
|
package space.kscience.visionforge.bootstrap
|
||||||
|
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.css.BorderStyle
|
import kotlinx.css.BorderStyle
|
||||||
import kotlinx.css.Color
|
import kotlinx.css.Color
|
||||||
import kotlinx.css.padding
|
import kotlinx.css.padding
|
||||||
@ -15,7 +16,6 @@ import react.RBuilder
|
|||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.button
|
import react.dom.button
|
||||||
import react.fc
|
import react.fc
|
||||||
import space.kscience.dataforge.meta.withDefault
|
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.encodeToString
|
import space.kscience.visionforge.encodeToString
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.react.flexColumn
|
||||||
@ -69,8 +69,8 @@ public val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { prop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = props.canvasOptions.meta,
|
scope = props.vision?.manager?.context ?: GlobalScope,
|
||||||
allProperties = props.canvasOptions.meta.withDefault(Canvas3DOptions.descriptor.defaultNode),
|
properties = props.canvasOptions.meta,
|
||||||
descriptor = Canvas3DOptions.descriptor,
|
descriptor = Canvas3DOptions.descriptor,
|
||||||
expanded = false
|
expanded = false
|
||||||
)
|
)
|
||||||
|
@ -3,13 +3,16 @@ package space.kscience.visionforge.bootstrap
|
|||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.dom.client.createRoot
|
import react.dom.client.createRoot
|
||||||
|
import react.key
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.computeProperties
|
|
||||||
import space.kscience.visionforge.getStyle
|
import space.kscience.visionforge.getStyle
|
||||||
|
import space.kscience.visionforge.react.EditorPropertyState
|
||||||
|
import space.kscience.visionforge.react.PropertyEditor
|
||||||
import space.kscience.visionforge.react.metaViewer
|
import space.kscience.visionforge.react.metaViewer
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
|
||||||
import space.kscience.visionforge.react.render
|
import space.kscience.visionforge.react.render
|
||||||
|
import space.kscience.visionforge.root
|
||||||
import space.kscience.visionforge.solid.SolidReference
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
import space.kscience.visionforge.styles
|
import space.kscience.visionforge.styles
|
||||||
|
|
||||||
@ -20,12 +23,25 @@ public fun RBuilder.visionPropertyEditor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
card("Properties") {
|
card("Properties") {
|
||||||
propertyEditor(
|
child(PropertyEditor){
|
||||||
ownProperties = vision.meta,
|
attrs{
|
||||||
allProperties = vision.computeProperties(),
|
this.key = key?.toString()
|
||||||
descriptor = descriptor,
|
this.meta = vision.properties.root()
|
||||||
key = key
|
this.updates = vision.properties.changes
|
||||||
)
|
this.descriptor = descriptor
|
||||||
|
this.scope = vision.manager?.context ?: error("Orphan vision could not be observed")
|
||||||
|
this.getPropertyState = {name->
|
||||||
|
if(vision.properties.own?.get(name)!= null){
|
||||||
|
EditorPropertyState.Defined
|
||||||
|
} else if(vision.properties.root()[name] != null){
|
||||||
|
// TODO differentiate
|
||||||
|
EditorPropertyState.Default()
|
||||||
|
} else {
|
||||||
|
EditorPropertyState.Undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val styles = if (vision is SolidReference) {
|
val styles = if (vision is SolidReference) {
|
||||||
(vision.styles + vision.prototype.styles).distinct()
|
(vision.styles + vision.prototype.styles).distinct()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.js")
|
id("space.kscience.gradle.js")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
|
@ -25,7 +25,7 @@ public val MultiSelectChooser: FC<ValueChooserProps> = fc("MultiSelectChooser")
|
|||||||
select {
|
select {
|
||||||
attrs {
|
attrs {
|
||||||
multiple = true
|
multiple = true
|
||||||
values = (props.actual.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
|
values = (props.meta.value?.list ?: emptyList()).mapTo(HashSet()) { it.string }
|
||||||
onChangeFunction = onChange
|
onChangeFunction = onChange
|
||||||
}
|
}
|
||||||
props.descriptor?.allowedValues?.forEach { optionValue ->
|
props.descriptor?.allowedValues?.forEach { optionValue ->
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
package space.kscience.visionforge.react
|
package space.kscience.visionforge.react
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import kotlinx.css.properties.TextDecoration
|
import kotlinx.css.properties.TextDecoration
|
||||||
import kotlinx.html.js.onClickFunction
|
import kotlinx.html.js.onClickFunction
|
||||||
import org.w3c.dom.Element
|
|
||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import react.*
|
import react.*
|
||||||
import react.dom.attrs
|
import react.dom.attrs
|
||||||
import react.dom.client.createRoot
|
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.descriptors.ValueRequirement
|
import space.kscience.dataforge.meta.descriptors.ValueRequirement
|
||||||
@ -19,17 +24,30 @@ import styled.styledButton
|
|||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
import styled.styledSpan
|
import styled.styledSpan
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display state of a property
|
||||||
|
*/
|
||||||
|
public sealed class EditorPropertyState {
|
||||||
|
public object Defined : EditorPropertyState()
|
||||||
|
public class Default(public val source: String = "unknown") : EditorPropertyState()
|
||||||
|
|
||||||
|
public object Undefined : EditorPropertyState()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public external interface PropertyEditorProps : Props {
|
public external interface PropertyEditorProps : Props {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root config object - always non-null
|
* Root config object - always non-null
|
||||||
*/
|
*/
|
||||||
public var meta: ObservableMutableMeta
|
public var meta: MutableMeta
|
||||||
|
|
||||||
/**
|
public var getPropertyState: (Name) -> EditorPropertyState
|
||||||
* Provide default item (greyed out if used)
|
|
||||||
*/
|
public var scope: CoroutineScope
|
||||||
public var withDefault: MetaProvider
|
|
||||||
|
public var updates: Flow<Name>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full path to the displayed node in [meta]. Could be empty
|
* Full path to the displayed node in [meta]. Could be empty
|
||||||
@ -54,7 +72,7 @@ private val PropertyEditorItem: FC<PropertyEditorProps> = fc("PropertyEditorItem
|
|||||||
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
||||||
var expanded: Boolean by useState { props.expanded ?: true }
|
var expanded: Boolean by useState { props.expanded ?: true }
|
||||||
val descriptor: MetaDescriptor? = useMemo(props.descriptor, props.name) { props.descriptor?.get(props.name) }
|
val descriptor: MetaDescriptor? = useMemo(props.descriptor, props.name) { props.descriptor?.get(props.name) }
|
||||||
var ownProperty: ObservableMutableMeta by useState { props.meta.getOrCreate(props.name) }
|
var property: MutableMeta by useState { props.meta.getOrCreate(props.name) }
|
||||||
|
|
||||||
val keys = useMemo(descriptor) {
|
val keys = useMemo(descriptor) {
|
||||||
buildSet {
|
buildSet {
|
||||||
@ -70,17 +88,18 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
val token = props.name.lastOrNull()?.toString() ?: "Properties"
|
val token = props.name.lastOrNull()?.toString() ?: "Properties"
|
||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
ownProperty = props.meta.getOrCreate(props.name)
|
property = props.meta.getOrCreate(props.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(props.meta) {
|
useEffect(props.meta) {
|
||||||
props.meta.onChange(props) { updatedName ->
|
val job = props.updates.onEach { updatedName ->
|
||||||
if (updatedName == props.name) {
|
if (updatedName == props.name) {
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
}
|
}.launchIn(props.scope)
|
||||||
|
|
||||||
cleanup {
|
cleanup {
|
||||||
props.meta.removeListener(props)
|
job.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +134,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
styledSpan {
|
styledSpan {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeLabel
|
+TreeStyles.treeLabel
|
||||||
if (ownProperty.isEmpty()) {
|
if (property.isEmpty()) {
|
||||||
+TreeStyles.treeLabelInactive
|
+TreeStyles.treeLabelInactive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,8 +150,8 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
ValueChooser {
|
ValueChooser {
|
||||||
attrs {
|
attrs {
|
||||||
this.descriptor = descriptor
|
this.descriptor = descriptor
|
||||||
this.meta = ownProperty
|
this.meta = property
|
||||||
this.actual = props.withDefault.getMeta(props.name) ?: ownProperty
|
this.state = props.getPropertyState(props.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,7 +175,7 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
}
|
}
|
||||||
+"\u00D7"
|
+"\u00D7"
|
||||||
attrs {
|
attrs {
|
||||||
if (ownProperty.isEmpty()) {
|
if (property.isEmpty()) {
|
||||||
disabled = true
|
disabled = true
|
||||||
} else {
|
} else {
|
||||||
onClickFunction = removeClick
|
onClickFunction = removeClick
|
||||||
@ -179,9 +198,11 @@ private fun RBuilder.propertyEditorItem(props: PropertyEditorProps) {
|
|||||||
attrs {
|
attrs {
|
||||||
this.key = props.name.toString()
|
this.key = props.name.toString()
|
||||||
this.meta = props.meta
|
this.meta = props.meta
|
||||||
this.withDefault = props.withDefault
|
|
||||||
this.name = props.name + token
|
this.name = props.name + token
|
||||||
this.descriptor = props.descriptor
|
this.descriptor = props.descriptor
|
||||||
|
this.scope = props.scope
|
||||||
|
this.getPropertyState = { props.getPropertyState(props.name + token) }
|
||||||
|
this.updates = props.updates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//configEditor(props.root, props.name + token, props.descriptor, props.default)
|
//configEditor(props.root, props.name + token, props.descriptor, props.default)
|
||||||
@ -197,44 +218,51 @@ public val PropertyEditor: FC<PropertyEditorProps> = fc("PropertyEditor") { prop
|
|||||||
attrs {
|
attrs {
|
||||||
this.key = ""
|
this.key = ""
|
||||||
this.meta = props.meta
|
this.meta = props.meta
|
||||||
this.withDefault = props.withDefault
|
|
||||||
this.name = Name.EMPTY
|
this.name = Name.EMPTY
|
||||||
this.descriptor = props.descriptor
|
this.descriptor = props.descriptor
|
||||||
this.expanded = props.expanded
|
this.expanded = props.expanded
|
||||||
|
this.scope = props.scope
|
||||||
|
this.getPropertyState = props.getPropertyState
|
||||||
|
this.updates = props.updates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
public fun RBuilder.propertyEditor(
|
public fun RBuilder.propertyEditor(
|
||||||
ownProperties: ObservableMutableMeta,
|
scope: CoroutineScope,
|
||||||
allProperties: MetaProvider = ownProperties,
|
properties: ObservableMutableMeta,
|
||||||
descriptor: MetaDescriptor? = null,
|
descriptor: MetaDescriptor? = null,
|
||||||
key: Any? = null,
|
key: Any? = null,
|
||||||
expanded: Boolean? = null,
|
expanded: Boolean? = null,
|
||||||
) {
|
) {
|
||||||
child(PropertyEditor) {
|
child(PropertyEditor) {
|
||||||
attrs {
|
attrs {
|
||||||
this.meta = ownProperties
|
this.meta = properties
|
||||||
this.withDefault = allProperties
|
|
||||||
this.descriptor = descriptor
|
this.descriptor = descriptor
|
||||||
this.key = key?.toString() ?: ""
|
this.key = key?.toString() ?: ""
|
||||||
this.expanded = expanded
|
this.expanded = expanded
|
||||||
|
this.scope = scope
|
||||||
|
this.getPropertyState = { name ->
|
||||||
|
if (properties[name] != null) {
|
||||||
|
EditorPropertyState.Defined
|
||||||
|
} else if (descriptor?.get(name)?.defaultValue != null) {
|
||||||
|
EditorPropertyState.Default("descriptor")
|
||||||
|
} else {
|
||||||
|
EditorPropertyState.Undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.updates = callbackFlow {
|
||||||
|
properties.onChange(scope) { name ->
|
||||||
|
scope.launch {
|
||||||
|
send(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeOnClose {
|
||||||
|
properties.removeListener(scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public fun RBuilder.configEditor(
|
|
||||||
config: ObservableMutableMeta,
|
|
||||||
default: MetaProvider = config,
|
|
||||||
descriptor: MetaDescriptor? = null,
|
|
||||||
key: Any? = null,
|
|
||||||
): Unit = propertyEditor(config, default, descriptor, key = key)
|
|
||||||
|
|
||||||
public fun Element.configEditor(
|
|
||||||
config: ObservableMutableMeta,
|
|
||||||
default: Meta = config,
|
|
||||||
descriptor: MetaDescriptor? = null,
|
|
||||||
key: Any? = null,
|
|
||||||
): Unit = createRoot(this).render {
|
|
||||||
configEditor(config, default, descriptor, key = key)
|
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ import styled.styledInput
|
|||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val RangeValueChooser: FC<ValueChooserProps> = fc("RangeValueChooser") { props ->
|
public val RangeValueChooser: FC<ValueChooserProps> = fc("RangeValueChooser") { props ->
|
||||||
var innerValue by useState(props.actual.double)
|
var innerValue by useState(props.meta.double)
|
||||||
var rangeDisabled: Boolean by useState(props.meta.value == null)
|
var rangeDisabled: Boolean by useState(props.meta.value == null)
|
||||||
|
|
||||||
val handleDisable: (Event) -> Unit = {
|
val handleDisable: (Event) -> Unit = {
|
||||||
|
@ -16,6 +16,7 @@ import space.kscience.dataforge.names.plus
|
|||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
|
import space.kscience.visionforge.asSequence
|
||||||
import space.kscience.visionforge.isEmpty
|
import space.kscience.visionforge.isEmpty
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
@ -59,9 +60,9 @@ private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
|
|||||||
val obj = props.obj
|
val obj = props.obj
|
||||||
|
|
||||||
//display as node if any child is visible
|
//display as node if any child is visible
|
||||||
if (obj is VisionGroup<*>) {
|
if (obj is VisionGroup) {
|
||||||
flexRow {
|
flexRow {
|
||||||
if (obj.items.any { !it.key.body.startsWith("@") }) {
|
if (obj.children.keys.any { !it.body.startsWith("@") }) {
|
||||||
styledSpan {
|
styledSpan {
|
||||||
css {
|
css {
|
||||||
+TreeStyles.treeCaret
|
+TreeStyles.treeCaret
|
||||||
@ -81,9 +82,9 @@ private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
|
|||||||
css {
|
css {
|
||||||
+TreeStyles.tree
|
+TreeStyles.tree
|
||||||
}
|
}
|
||||||
obj.items.entries
|
obj.children.asSequence()
|
||||||
.filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children
|
.filter { !it.first.toString().startsWith("@") } // ignore statics and other hidden children
|
||||||
.sortedBy { (it.value as? VisionGroup<*>)?.isEmpty() ?: true } // ignore empty groups
|
.sortedBy { (it.second as? VisionGroup)?.children?.isEmpty() ?: true } // ignore empty groups
|
||||||
.forEach { (childToken, child) ->
|
.forEach { (childToken, child) ->
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
@ -92,7 +93,7 @@ private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
|
|||||||
child(ObjectTree) {
|
child(ObjectTree) {
|
||||||
attrs {
|
attrs {
|
||||||
this.name = props.name + childToken
|
this.name = props.name + childToken
|
||||||
this.obj = child.vision
|
this.obj = child
|
||||||
this.selected = props.selected
|
this.selected = props.selected
|
||||||
this.clickCallback = props.clickCallback
|
this.clickCallback = props.clickCallback
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,13 @@ import styled.styledSelect
|
|||||||
|
|
||||||
public external interface ValueChooserProps : Props {
|
public external interface ValueChooserProps : Props {
|
||||||
public var descriptor: MetaDescriptor?
|
public var descriptor: MetaDescriptor?
|
||||||
public var meta: ObservableMutableMeta
|
public var meta: MutableMeta
|
||||||
public var actual: Meta
|
public var state: EditorPropertyState
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val StringValueChooser: FC<ValueChooserProps> = fc("StringValueChooser") { props ->
|
public val StringValueChooser: FC<ValueChooserProps> = fc("StringValueChooser") { props ->
|
||||||
var value by useState(props.actual.string ?: "")
|
var value by useState(props.meta.string ?: "")
|
||||||
val keyDown: (Event) -> Unit = { event ->
|
val keyDown: (Event) -> Unit = { event ->
|
||||||
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
||||||
value = (event.target as HTMLInputElement).value
|
value = (event.target as HTMLInputElement).value
|
||||||
@ -67,7 +67,7 @@ public val BooleanValueChooser: FC<ValueChooserProps> = fc("BooleanValueChooser"
|
|||||||
}
|
}
|
||||||
attrs {
|
attrs {
|
||||||
//this.attributes["indeterminate"] = (props.item == null).toString()
|
//this.attributes["indeterminate"] = (props.item == null).toString()
|
||||||
checked = props.actual.boolean ?: false
|
checked = props.meta.boolean ?: false
|
||||||
onChangeFunction = handleChange
|
onChangeFunction = handleChange
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ public val BooleanValueChooser: FC<ValueChooserProps> = fc("BooleanValueChooser"
|
|||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val NumberValueChooser: FC<ValueChooserProps> = fc("NumberValueChooser") { props ->
|
public val NumberValueChooser: FC<ValueChooserProps> = fc("NumberValueChooser") { props ->
|
||||||
var innerValue by useState(props.actual.string ?: "")
|
var innerValue by useState(props.meta.string ?: "")
|
||||||
val keyDown: (Event) -> Unit = { event ->
|
val keyDown: (Event) -> Unit = { event ->
|
||||||
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
if (event.type == "keydown" && event.asDynamic().key == "Enter") {
|
||||||
innerValue = (event.target as HTMLInputElement).value
|
innerValue = (event.target as HTMLInputElement).value
|
||||||
@ -113,7 +113,7 @@ public val NumberValueChooser: FC<ValueChooserProps> = fc("NumberValueChooser")
|
|||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ComboValueChooser: FC<ValueChooserProps> = fc("ComboValueChooser") { props ->
|
public val ComboValueChooser: FC<ValueChooserProps> = fc("ComboValueChooser") { props ->
|
||||||
var selected by useState(props.actual.string ?: "")
|
var selected by useState(props.meta.string ?: "")
|
||||||
val handleChange: (Event) -> Unit = {
|
val handleChange: (Event) -> Unit = {
|
||||||
selected = (it.target as HTMLSelectElement).value
|
selected = (it.target as HTMLSelectElement).value
|
||||||
props.meta.value = selected.asValue()
|
props.meta.value = selected.asValue()
|
||||||
@ -128,7 +128,7 @@ public val ComboValueChooser: FC<ValueChooserProps> = fc("ComboValueChooser") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
attrs {
|
attrs {
|
||||||
this.value = props.actual.string ?: ""
|
this.value = props.meta.string ?: ""
|
||||||
multiple = false
|
multiple = false
|
||||||
onChangeFunction = handleChange
|
onChangeFunction = handleChange
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ public val ColorValueChooser: FC<ValueChooserProps> = fc("ColorValueChooser") {
|
|||||||
margin(0.px)
|
margin(0.px)
|
||||||
}
|
}
|
||||||
attrs {
|
attrs {
|
||||||
this.value = props.actual.value?.let { value ->
|
this.value = props.meta.value?.let { value ->
|
||||||
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
|
if (value.type == ValueType.NUMBER) Colors.rgbToString(value.int)
|
||||||
else value.string
|
else value.string
|
||||||
} ?: "#000000"
|
} ?: "#000000"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.js")
|
id("space.kscience.gradle.js")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion: String by rootProject.extra
|
val dataforgeVersion: String by rootProject.extra
|
||||||
|
@ -9,18 +9,19 @@ import react.dom.div
|
|||||||
import react.dom.span
|
import react.dom.span
|
||||||
import ringui.*
|
import ringui.*
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.NameToken
|
import space.kscience.dataforge.names.NameToken
|
||||||
import space.kscience.dataforge.names.isEmpty
|
import space.kscience.dataforge.names.isEmpty
|
||||||
import space.kscience.dataforge.names.length
|
import space.kscience.dataforge.names.length
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.react.ThreeCanvasComponent
|
import space.kscience.visionforge.react.*
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.root
|
||||||
import space.kscience.visionforge.react.flexRow
|
import space.kscience.visionforge.setAsRoot
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.SolidGroup
|
import space.kscience.visionforge.solid.SolidGroup
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
|
import space.kscience.visionforge.visionManager
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ public fun ThreeCanvasWithControlsProps.solid(block: SolidGroup.() -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ThreeCanvasWithControlsProps.options(block: Canvas3DOptions.() -> Unit){
|
public fun ThreeCanvasWithControlsProps.options(block: Canvas3DOptions.() -> Unit) {
|
||||||
options = Canvas3DOptions(block)
|
options = Canvas3DOptions(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,14 +82,14 @@ public fun RBuilder.nameCrumbs(name: Name?, link: (Name) -> Unit): Unit = styled
|
|||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
public val ThreeCanvasWithControls: FC<ThreeCanvasWithControlsProps> = fc("ThreeViewWithControls") { props ->
|
public val ThreeCanvasWithControls: FC<ThreeCanvasWithControlsProps> = fc("ThreeViewWithControls") { props ->
|
||||||
var selected by useState { props.selected }
|
var selected: Name? by useState { props.selected }
|
||||||
var solid: Solid? by useState(null)
|
var solid: Solid? by useState(null)
|
||||||
|
|
||||||
useEffect {
|
useEffect {
|
||||||
props.context.launch {
|
props.context.launch {
|
||||||
solid = props.builderOfSolid.await()
|
solid = props.builderOfSolid.await()
|
||||||
//ensure that the solid is properly rooted
|
//ensure that the solid is properly rooted
|
||||||
if(solid?.parent == null){
|
if (solid?.parent == null) {
|
||||||
solid?.setAsRoot(props.context.visionManager)
|
solid?.setAsRoot(props.context.visionManager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,12 +165,25 @@ public val ThreeCanvasWithControls: FC<ThreeCanvasWithControlsProps> = fc("Three
|
|||||||
nameCrumbs(selected) { selected = it }
|
nameCrumbs(selected) { selected = it }
|
||||||
}
|
}
|
||||||
IslandContent {
|
IslandContent {
|
||||||
propertyEditor(
|
child(PropertyEditor) {
|
||||||
ownProperties = vision.properties(),
|
attrs {
|
||||||
allProperties = vision.computeProperties(),
|
this.key = selected.toString()
|
||||||
descriptor = vision.descriptor,
|
this.meta = vision.properties.root()
|
||||||
key = selected
|
this.updates = vision.properties.changes
|
||||||
)
|
this.descriptor = vision.descriptor
|
||||||
|
this.scope = props.context
|
||||||
|
this.getPropertyState = { name ->
|
||||||
|
if (vision.properties.own?.get(name) != null) {
|
||||||
|
EditorPropertyState.Defined
|
||||||
|
} else if (vision.properties.root()[name] != null) {
|
||||||
|
// TODO differentiate
|
||||||
|
EditorPropertyState.Default()
|
||||||
|
} else {
|
||||||
|
EditorPropertyState.Undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,16 @@ import org.w3c.dom.Element
|
|||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.dom.client.createRoot
|
import react.dom.client.createRoot
|
||||||
import react.dom.p
|
import react.dom.p
|
||||||
|
import react.key
|
||||||
import ringui.Island
|
import ringui.Island
|
||||||
import ringui.SmartTabs
|
import ringui.SmartTabs
|
||||||
import ringui.Tab
|
import ringui.Tab
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.computeProperties
|
|
||||||
import space.kscience.visionforge.getStyle
|
import space.kscience.visionforge.getStyle
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.react.*
|
||||||
import space.kscience.visionforge.react.metaViewer
|
import space.kscience.visionforge.root
|
||||||
import space.kscience.visionforge.react.propertyEditor
|
|
||||||
import space.kscience.visionforge.react.render
|
|
||||||
import space.kscience.visionforge.solid.SolidReference
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
import space.kscience.visionforge.styles
|
import space.kscience.visionforge.styles
|
||||||
|
|
||||||
@ -31,12 +30,25 @@ public fun RBuilder.ringPropertyEditor(
|
|||||||
|
|
||||||
flexColumn {
|
flexColumn {
|
||||||
Island("Properties") {
|
Island("Properties") {
|
||||||
propertyEditor(
|
child(PropertyEditor) {
|
||||||
ownProperties = vision.meta,
|
attrs {
|
||||||
allProperties = vision.computeProperties(),
|
this.key = key?.toString()
|
||||||
descriptor = descriptor,
|
this.meta = vision.properties.root()
|
||||||
key = key
|
this.updates = vision.properties.changes
|
||||||
)
|
this.descriptor = descriptor
|
||||||
|
this.scope = vision.manager?.context ?: error("Orphan vision could not be observed")
|
||||||
|
this.getPropertyState = {name->
|
||||||
|
if(vision.properties.own?.get(name)!= null){
|
||||||
|
EditorPropertyState.Defined
|
||||||
|
} else if(vision.properties.root()[name] != null){
|
||||||
|
// TODO differentiate
|
||||||
|
EditorPropertyState.Default()
|
||||||
|
} else {
|
||||||
|
EditorPropertyState.Undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (styles.isNotEmpty()) {
|
if (styles.isNotEmpty()) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package space.kscience.visionforge.ring
|
package space.kscience.visionforge.ring
|
||||||
|
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.css.BorderStyle
|
import kotlinx.css.BorderStyle
|
||||||
import kotlinx.css.Color
|
import kotlinx.css.Color
|
||||||
import kotlinx.css.padding
|
import kotlinx.css.padding
|
||||||
@ -18,7 +19,6 @@ import react.fc
|
|||||||
import ringui.Island
|
import ringui.Island
|
||||||
import ringui.SmartTabs
|
import ringui.SmartTabs
|
||||||
import ringui.Tab
|
import ringui.Tab
|
||||||
import space.kscience.dataforge.meta.withDefault
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.encodeToString
|
import space.kscience.visionforge.encodeToString
|
||||||
@ -75,8 +75,8 @@ internal val CanvasControls: FC<CanvasControlsProps> = fc("CanvasControls") { pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyEditor(
|
propertyEditor(
|
||||||
ownProperties = props.options.meta,
|
scope = props.vision?.manager?.context ?: GlobalScope,
|
||||||
allProperties = props.options.meta.withDefault(Canvas3DOptions.descriptor.defaultNode),
|
properties = props.options.meta,
|
||||||
descriptor = Canvas3DOptions.descriptor,
|
descriptor = Canvas3DOptions.descriptor,
|
||||||
expanded = false
|
expanded = false
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion: String by rootProject.extra
|
val dataforgeVersion: String by rootProject.extra
|
||||||
@ -28,5 +28,5 @@ kscience{
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme{
|
readme{
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
maturity = space.kscience.gradle.Maturity.DEVELOPMENT
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ import kotlin.jvm.JvmInline
|
|||||||
@JvmInline
|
@JvmInline
|
||||||
public value class StyleSheet(private val owner: Vision) {
|
public value class StyleSheet(private val owner: Vision) {
|
||||||
|
|
||||||
private val styleNode: Meta get() = owner.properties[STYLESHEET_KEY]
|
private val styleNode: Meta get() = owner.properties.getProperty(STYLESHEET_KEY)
|
||||||
|
|
||||||
public val items: Map<NameToken, Meta> get() = styleNode.items
|
public val items: Map<NameToken, Meta> get() = styleNode.items
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ public value class StyleSheet(private val owner: Vision) {
|
|||||||
* Define a style without notifying owner
|
* Define a style without notifying owner
|
||||||
*/
|
*/
|
||||||
public fun define(key: String, style: Meta?) {
|
public fun define(key: String, style: Meta?) {
|
||||||
owner.properties[STYLESHEET_KEY + key] = style
|
owner.properties.setProperty(STYLESHEET_KEY + key, style)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,7 +86,7 @@ public val Vision.styleSheet: StyleSheet get() = StyleSheet(this)
|
|||||||
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
|
* Add style name to the list of styles to be resolved later. The style with given name does not necessary exist at the moment.
|
||||||
*/
|
*/
|
||||||
public fun Vision.useStyle(name: String) {
|
public fun Vision.useStyle(name: String) {
|
||||||
styles = (properties.getValue(Vision.STYLE_KEY)?.stringList ?: emptyList()) + name
|
styles = (properties.own?.get(Vision.STYLE_KEY)?.stringList ?: emptyList()) + name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ public fun Vision.useStyle(name: String) {
|
|||||||
* Resolve a style with given name for given [Vision]. The style is not necessarily applied to this [Vision].
|
* Resolve a style with given name for given [Vision]. The style is not necessarily applied to this [Vision].
|
||||||
*/
|
*/
|
||||||
public fun Vision.getStyle(name: String): Meta? =
|
public fun Vision.getStyle(name: String): Meta? =
|
||||||
properties.raw?.getMeta(StyleSheet.STYLESHEET_KEY + name) ?: parent?.getStyle(name)
|
properties.own?.getMeta(StyleSheet.STYLESHEET_KEY + name) ?: parent?.getStyle(name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a property from all styles
|
* Resolve a property from all styles
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package space.kscience.visionforge
|
package space.kscience.visionforge
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import space.kscience.dataforge.context.Global
|
|
||||||
import space.kscience.dataforge.meta.asValue
|
import space.kscience.dataforge.meta.asValue
|
||||||
import space.kscience.dataforge.meta.boolean
|
import space.kscience.dataforge.meta.boolean
|
||||||
import space.kscience.dataforge.meta.descriptors.Described
|
import space.kscience.dataforge.meta.descriptors.Described
|
||||||
@ -30,7 +30,7 @@ public interface Vision : Described {
|
|||||||
/**
|
/**
|
||||||
* Owner [VisionManager]. Used to define coroutine scope a serialization
|
* Owner [VisionManager]. Used to define coroutine scope a serialization
|
||||||
*/
|
*/
|
||||||
public val manager: VisionManager get() = parent?.manager ?: Global.visionManager
|
public val manager: VisionManager? get() = parent?.manager
|
||||||
|
|
||||||
|
|
||||||
public val properties: MutableVisionProperties
|
public val properties: MutableVisionProperties
|
||||||
@ -67,13 +67,17 @@ public var Vision.visible: Boolean?
|
|||||||
/**
|
/**
|
||||||
* Subscribe on property updates. The subscription is bound to the given scope and canceled when the scope is canceled
|
* Subscribe on property updates. The subscription is bound to the given scope and canceled when the scope is canceled
|
||||||
*/
|
*/
|
||||||
public fun Vision.onPropertyChange(callback: (Name) -> Unit): Job = properties.changes.onEach {
|
public fun Vision.onPropertyChange(
|
||||||
|
scope: CoroutineScope? = manager?.context,
|
||||||
|
callback: (Name) -> Unit
|
||||||
|
): Job = properties.changes.onEach {
|
||||||
callback(it)
|
callback(it)
|
||||||
}.launchIn(manager.context)
|
}.launchIn(scope ?: error("Orphan Vision can't observe properties"))
|
||||||
|
|
||||||
|
|
||||||
public fun <V : Vision, T> V.useProperty(
|
public fun <V : Vision, T> V.useProperty(
|
||||||
property: KProperty1<V, T>,
|
property: KProperty1<V, T>,
|
||||||
|
scope: CoroutineScope? = manager?.context,
|
||||||
callBack: V.(T) -> Unit,
|
callBack: V.(T) -> Unit,
|
||||||
): Job {
|
): Job {
|
||||||
//Pass initial value.
|
//Pass initial value.
|
||||||
@ -82,5 +86,5 @@ public fun <V : Vision, T> V.useProperty(
|
|||||||
if (name.startsWith(property.name.asName())) {
|
if (name.startsWith(property.name.asName())) {
|
||||||
callBack(property.get(this@useProperty))
|
callBack(property.get(this@useProperty))
|
||||||
}
|
}
|
||||||
}.launchIn(manager.context)
|
}.launchIn(scope ?: error("Orphan Vision can't observe properties"))
|
||||||
}
|
}
|
@ -91,8 +91,8 @@ private fun CoroutineScope.collectChange(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
//Collect properties change
|
//Collect properties change
|
||||||
source.onPropertyChange { propertyName ->
|
source.onPropertyChange(this) { propertyName ->
|
||||||
val newItem = source.properties.raw?.get(propertyName)
|
val newItem = source.properties.own?.get(propertyName)
|
||||||
collector().propertyChanged(name, propertyName, newItem)
|
collector().propertyChanged(name, propertyName, newItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,8 +118,8 @@ private fun CoroutineScope.collectChange(
|
|||||||
*/
|
*/
|
||||||
public fun Vision.flowChanges(
|
public fun Vision.flowChanges(
|
||||||
collectionDuration: Duration,
|
collectionDuration: Duration,
|
||||||
manager: VisionManager = this.manager,
|
|
||||||
): Flow<VisionChange> = flow {
|
): Flow<VisionChange> = flow {
|
||||||
|
val manager = manager?: error("Orphan vision could not collect changes")
|
||||||
|
|
||||||
var collector = VisionChangeBuilder(manager)
|
var collector = VisionChangeBuilder(manager)
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
|
@ -124,7 +124,7 @@ internal abstract class VisionChildrenImpl(
|
|||||||
return items!!
|
return items!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scope: CoroutineScope get() = group.manager.context
|
private val scope: CoroutineScope? get() = group.manager?.context
|
||||||
|
|
||||||
override val keys: Set<NameToken> get() = items?.keys ?: emptySet()
|
override val keys: Set<NameToken> get() = items?.keys ?: emptySet()
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ internal abstract class VisionChildrenImpl(
|
|||||||
override val changes: SharedFlow<Name> get() = _changes
|
override val changes: SharedFlow<Name> get() = _changes
|
||||||
|
|
||||||
private fun onChange(name: Name) {
|
private fun onChange(name: Name) {
|
||||||
scope.launch {
|
scope?.launch {
|
||||||
_changes.emit(name)
|
_changes.emit(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ internal abstract class VisionChildrenImpl(
|
|||||||
//set parent
|
//set parent
|
||||||
value.parent = group
|
value.parent = group
|
||||||
//start update jobs (only if the vision is rooted)
|
//start update jobs (only if the vision is rooted)
|
||||||
scope.let { scope ->
|
scope?.let { scope ->
|
||||||
val job = value.children?.changes?.onEach {
|
val job = value.children?.changes?.onEach {
|
||||||
onChange(token + it)
|
onChange(token + it)
|
||||||
}?.launchIn(scope)
|
}?.launchIn(scope)
|
||||||
|
@ -107,7 +107,8 @@ public abstract class VisionPlugin(meta: Meta = Meta.EMPTY) : AbstractPlugin(met
|
|||||||
*/
|
*/
|
||||||
public val Context.visionManager: VisionManager get() = fetch(VisionManager)
|
public val Context.visionManager: VisionManager get() = fetch(VisionManager)
|
||||||
|
|
||||||
public fun Vision.encodeToString(): String = manager.encodeToString(this)
|
public fun Vision.encodeToString(): String =
|
||||||
|
manager?.encodeToString(this) ?: error("Orphan vision could not be encoded")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A root vision attached to [VisionManager]
|
* A root vision attached to [VisionManager]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package space.kscience.visionforge
|
package space.kscience.visionforge
|
||||||
|
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
@ -16,14 +18,14 @@ public interface VisionProperties {
|
|||||||
/**
|
/**
|
||||||
* Raw Visions own properties without styles, defaults, etc.
|
* Raw Visions own properties without styles, defaults, etc.
|
||||||
*/
|
*/
|
||||||
public val raw: Meta?
|
public val own: Meta?
|
||||||
|
|
||||||
public val descriptor: MetaDescriptor?
|
public val descriptor: MetaDescriptor?
|
||||||
|
|
||||||
public fun getValue(
|
public fun getValue(
|
||||||
name: Name,
|
name: Name,
|
||||||
inherit: Boolean,
|
inherit: Boolean? = null,
|
||||||
includeStyles: Boolean,
|
includeStyles: Boolean? = null,
|
||||||
): Value?
|
): Value?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,10 +33,10 @@ public interface VisionProperties {
|
|||||||
* @param inherit toggles parent node property lookup. Null means inference from descriptor.
|
* @param inherit toggles parent node property lookup. Null means inference from descriptor.
|
||||||
* @param includeStyles toggles inclusion of properties from styles.
|
* @param includeStyles toggles inclusion of properties from styles.
|
||||||
*/
|
*/
|
||||||
public operator fun get(
|
public fun getProperty(
|
||||||
name: Name,
|
name: Name,
|
||||||
inherit: Boolean,
|
inherit: Boolean? = null,
|
||||||
includeStyles: Boolean,
|
includeStyles: Boolean? = null,
|
||||||
): Meta
|
): Meta
|
||||||
|
|
||||||
public val changes: Flow<Name>
|
public val changes: Flow<Name>
|
||||||
@ -48,10 +50,10 @@ public interface VisionProperties {
|
|||||||
|
|
||||||
public interface MutableVisionProperties : VisionProperties {
|
public interface MutableVisionProperties : VisionProperties {
|
||||||
|
|
||||||
override operator fun get(
|
override fun getProperty(
|
||||||
name: Name,
|
name: Name,
|
||||||
inherit: Boolean,
|
inherit: Boolean?,
|
||||||
includeStyles: Boolean,
|
includeStyles: Boolean?,
|
||||||
): MutableMeta = VisionPropertiesItem(
|
): MutableMeta = VisionPropertiesItem(
|
||||||
this,
|
this,
|
||||||
name,
|
name,
|
||||||
@ -60,7 +62,7 @@ public interface MutableVisionProperties : VisionProperties {
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
public operator fun set(
|
public fun setProperty(
|
||||||
name: Name,
|
name: Name,
|
||||||
node: Meta?,
|
node: Meta?,
|
||||||
)
|
)
|
||||||
@ -84,7 +86,7 @@ private class VisionPropertiesItem(
|
|||||||
|
|
||||||
override val items: Map<NameToken, MutableMeta>
|
override val items: Map<NameToken, MutableMeta>
|
||||||
get() {
|
get() {
|
||||||
val metaKeys = properties.raw?.getMeta(nodeName)?.items?.keys ?: emptySet()
|
val metaKeys = properties.own?.getMeta(nodeName)?.items?.keys ?: emptySet()
|
||||||
val descriptorKeys = descriptor?.children?.map { NameToken(it.key) } ?: emptySet()
|
val descriptorKeys = descriptor?.children?.map { NameToken(it.key) } ?: emptySet()
|
||||||
val defaultKeys = default?.get(nodeName)?.items?.keys ?: emptySet()
|
val defaultKeys = default?.get(nodeName)?.items?.keys ?: emptySet()
|
||||||
val inheritFlag = descriptor?.inherited ?: inherit
|
val inheritFlag = descriptor?.inherited ?: inherit
|
||||||
@ -119,7 +121,7 @@ private class VisionPropertiesItem(
|
|||||||
)
|
)
|
||||||
|
|
||||||
override fun setMeta(name: Name, node: Meta?) {
|
override fun setMeta(name: Name, node: Meta?) {
|
||||||
properties[nodeName + name] = node
|
properties.setProperty(nodeName + name, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = Meta.toString(this)
|
override fun toString(): String = Meta.toString(this)
|
||||||
@ -131,11 +133,10 @@ public abstract class AbstractVisionProperties(
|
|||||||
private val vision: Vision,
|
private val vision: Vision,
|
||||||
) : MutableVisionProperties {
|
) : MutableVisionProperties {
|
||||||
override val descriptor: MetaDescriptor? get() = vision.descriptor
|
override val descriptor: MetaDescriptor? get() = vision.descriptor
|
||||||
protected val default: Meta? get() = descriptor?.defaultNode
|
|
||||||
|
|
||||||
protected abstract var properties: MutableMeta?
|
protected abstract var properties: MutableMeta?
|
||||||
|
|
||||||
override val raw: Meta? get() = properties
|
override val own: Meta? get() = properties
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
protected fun getOrCreateProperties(): MutableMeta {
|
protected fun getOrCreateProperties(): MutableMeta {
|
||||||
@ -149,20 +150,24 @@ public abstract class AbstractVisionProperties(
|
|||||||
|
|
||||||
override fun getValue(
|
override fun getValue(
|
||||||
name: Name,
|
name: Name,
|
||||||
inherit: Boolean,
|
inherit: Boolean?,
|
||||||
includeStyles: Boolean,
|
includeStyles: Boolean?,
|
||||||
): Value? {
|
): Value? {
|
||||||
raw?.get(name)?.value?.let { return it }
|
val descriptor = descriptor?.get(name)
|
||||||
if (includeStyles) {
|
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
||||||
|
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
||||||
|
|
||||||
|
own?.get(name)?.value?.let { return it }
|
||||||
|
if (stylesFlag) {
|
||||||
vision.getStyleProperty(name)?.value?.let { return it }
|
vision.getStyleProperty(name)?.value?.let { return it }
|
||||||
}
|
}
|
||||||
if (inherit) {
|
if (inheritFlag) {
|
||||||
vision.parent?.properties?.getValue(name, inherit, includeStyles)?.let { return it }
|
vision.parent?.properties?.getValue(name, inherit, includeStyles)?.let { return it }
|
||||||
}
|
}
|
||||||
return default?.get(name)?.value
|
return descriptor?.defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun set(name: Name, node: Meta?) {
|
override fun setProperty(name: Name, node: Meta?) {
|
||||||
//TODO check old value?
|
//TODO check old value?
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
properties = node?.asMutableMeta()
|
properties = node?.asMutableMeta()
|
||||||
@ -188,6 +193,7 @@ public abstract class AbstractVisionProperties(
|
|||||||
private val _changes = MutableSharedFlow<Name>(10)
|
private val _changes = MutableSharedFlow<Name>(10)
|
||||||
override val changes: SharedFlow<Name> get() = _changes
|
override val changes: SharedFlow<Name> get() = _changes
|
||||||
|
|
||||||
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
override fun invalidate(propertyName: Name) {
|
override fun invalidate(propertyName: Name) {
|
||||||
if (propertyName == Vision.STYLE_KEY) {
|
if (propertyName == Vision.STYLE_KEY) {
|
||||||
vision.styles.asSequence()
|
vision.styles.asSequence()
|
||||||
@ -198,85 +204,46 @@ public abstract class AbstractVisionProperties(
|
|||||||
invalidate(it.key.asName())
|
invalidate(it.key.asName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vision.manager.context.launch {
|
(vision.manager?.context ?: GlobalScope).launch {
|
||||||
_changes.emit(propertyName)
|
_changes.emit(propertyName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun VisionProperties.getValue(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
): Value? {
|
|
||||||
val descriptor = descriptor?.get(name)
|
|
||||||
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
|
||||||
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
|
||||||
return getValue(name, inheritFlag, stylesFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun VisionProperties.getValue(
|
public fun VisionProperties.getValue(
|
||||||
name: String,
|
name: String,
|
||||||
inherit: Boolean? = null,
|
inherit: Boolean? = null,
|
||||||
includeStyles: Boolean? = null,
|
includeStyles: Boolean? = null,
|
||||||
): Value? = getValue(name.parseAsName(), inherit, includeStyles)
|
): Value? = getValue(name.parseAsName(), inherit, includeStyles)
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the property based on the provided value descriptor. By default, use Vision own descriptor
|
|
||||||
*/
|
|
||||||
public operator fun VisionProperties.get(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
): Meta {
|
|
||||||
val descriptor: MetaDescriptor? = descriptor?.get(name)
|
|
||||||
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
|
||||||
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
|
||||||
return get(name, inheritFlag, stylesFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get [Vision] property using key as a String
|
* Get [Vision] property using key as a String
|
||||||
*/
|
*/
|
||||||
public operator fun VisionProperties.get(
|
public fun VisionProperties.getProperty(
|
||||||
name: String,
|
name: String,
|
||||||
inherit: Boolean? = null,
|
inherit: Boolean? = null,
|
||||||
includeStyles: Boolean? = null,
|
includeStyles: Boolean? = null,
|
||||||
): Meta = get(name.parseAsName(), inherit, includeStyles)
|
): Meta = getProperty(name.parseAsName(), inherit, includeStyles)
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the property based on the provided value descriptor. By default, use Vision own descriptor
|
|
||||||
*/
|
|
||||||
public operator fun MutableVisionProperties.get(
|
|
||||||
name: Name,
|
|
||||||
inherit: Boolean? = null,
|
|
||||||
includeStyles: Boolean? = null,
|
|
||||||
): MutableMeta {
|
|
||||||
val descriptor: MetaDescriptor? = descriptor?.get(name)
|
|
||||||
val inheritFlag = inherit ?: descriptor?.inherited ?: false
|
|
||||||
val stylesFlag = includeStyles ?: descriptor?.usesStyles ?: true
|
|
||||||
return get(name, inheritFlag, stylesFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The root property node with given inheritance and style flags
|
* The root property node with given inheritance and style flags
|
||||||
|
* @param inherit - inherit properties from the [Vision] parent. If null, infer from descriptor
|
||||||
|
* @param includeStyles - include style information. If null, infer from descriptor
|
||||||
*/
|
*/
|
||||||
public fun MutableVisionProperties.root(
|
public fun MutableVisionProperties.root(
|
||||||
inherit: Boolean? = null,
|
inherit: Boolean? = null,
|
||||||
includeStyles: Boolean? = null,
|
includeStyles: Boolean? = null,
|
||||||
): MutableMeta = get(Name.EMPTY, inherit, includeStyles)
|
): MutableMeta = getProperty(Name.EMPTY, inherit, includeStyles)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get [Vision] property using key as a String
|
* Get [Vision] property using key as a String
|
||||||
*/
|
*/
|
||||||
public operator fun MutableVisionProperties.get(
|
public fun MutableVisionProperties.getProperty(
|
||||||
name: String,
|
name: String,
|
||||||
inherit: Boolean? = null,
|
inherit: Boolean? = null,
|
||||||
includeStyles: Boolean? = null,
|
includeStyles: Boolean? = null,
|
||||||
): MutableMeta = get(name.parseAsName(), inherit, includeStyles)
|
): MutableMeta = getProperty(name.parseAsName(), inherit, includeStyles)
|
||||||
|
|
||||||
|
|
||||||
public operator fun MutableVisionProperties.set(name: Name, value: Number): Unit =
|
public operator fun MutableVisionProperties.set(name: Name, value: Number): Unit =
|
||||||
|
@ -9,7 +9,7 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.*
|
||||||
|
|
||||||
//TODO replace by something
|
//TODO replace by something
|
||||||
internal val Vision.mutableProperties get() = properties[Name.EMPTY, false, false]
|
internal val Vision.mutableProperties get() = properties.getProperty(Name.EMPTY, false, false)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
public abstract class VisionOfHtmlInput : AbstractVision() {
|
public abstract class VisionOfHtmlInput : AbstractVision() {
|
||||||
|
@ -54,7 +54,7 @@ class HtmlTagTest {
|
|||||||
div {
|
div {
|
||||||
h2 { +"Properties" }
|
h2 { +"Properties" }
|
||||||
ul {
|
ul {
|
||||||
vision.properties.raw?.items?.forEach {
|
vision.properties.own?.items?.forEach {
|
||||||
li {
|
li {
|
||||||
a { +it.key.toString() }
|
a { +it.key.toString() }
|
||||||
p { +it.value.toString() }
|
p { +it.value.toString() }
|
||||||
|
@ -2,7 +2,7 @@ package space.kscience.visionforge.meta
|
|||||||
|
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.visionforge.VisionGroup
|
import space.kscience.visionforge.VisionGroup
|
||||||
import space.kscience.visionforge.get
|
import space.kscience.visionforge.getProperty
|
||||||
import space.kscience.visionforge.getValue
|
import space.kscience.visionforge.getValue
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -30,7 +30,7 @@ internal class VisionPropertyTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testPropertyEdit() {
|
fun testPropertyEdit() {
|
||||||
val vision = VisionGroup()
|
val vision = VisionGroup()
|
||||||
vision.properties["fff.ddd"].apply {
|
vision.properties.getProperty("fff.ddd").apply {
|
||||||
value = 2.asValue()
|
value = 2.asValue()
|
||||||
}
|
}
|
||||||
assertEquals(2, vision.properties.getValue("fff.ddd")?.int)
|
assertEquals(2, vision.properties.getValue("fff.ddd")?.int)
|
||||||
@ -40,7 +40,7 @@ internal class VisionPropertyTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testPropertyUpdate() {
|
fun testPropertyUpdate() {
|
||||||
val vision = VisionGroup()
|
val vision = VisionGroup()
|
||||||
vision.properties["fff"].updateWith(TestScheme) {
|
vision.properties.getProperty("fff").updateWith(TestScheme) {
|
||||||
ddd = 2
|
ddd = 2
|
||||||
}
|
}
|
||||||
assertEquals(2, vision.properties.getValue("fff.ddd")?.int)
|
assertEquals(2, vision.properties.getValue("fff.ddd")?.int)
|
||||||
|
@ -115,7 +115,7 @@ public class VisionClient : AbstractPlugin() {
|
|||||||
|
|
||||||
onopen = {
|
onopen = {
|
||||||
feedbackJob = vision.flowChanges(
|
feedbackJob = vision.flowChanges(
|
||||||
feedbackAggregationTime.milliseconds
|
feedbackAggregationTime.milliseconds,
|
||||||
).onEach { change ->
|
).onEach { change ->
|
||||||
send(visionManager.encodeToString(change))
|
send(visionManager.encodeToString(change))
|
||||||
}.launchIn(visionManager.context)
|
}.launchIn(visionManager.context)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.jvm")
|
id("space.kscience.gradle.jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion: String by rootProject.extra
|
val dataforgeVersion: String by rootProject.extra
|
||||||
val fxVersion: String by rootProject.extra
|
val fxVersion: String by rootProject.extra
|
||||||
|
|
||||||
kscience{
|
kscience{
|
||||||
useFx(ru.mipt.npm.gradle.FXModule.CONTROLS, version = fxVersion)
|
useFx(space.kscience.gradle.FXModule.CONTROLS, version = fxVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -15,12 +15,12 @@ dependencies {
|
|||||||
api("org.fxyz3d:fxyz3d:0.5.4") {
|
api("org.fxyz3d:fxyz3d:0.5.4") {
|
||||||
exclude(module = "slf4j-simple")
|
exclude(module = "slf4j-simple")
|
||||||
}
|
}
|
||||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion}")
|
api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${space.kscience.gradle.KScienceVersions.coroutinesVersion}")
|
||||||
implementation("eu.mihosoft.vrl.jcsg:jcsg:0.5.7") {
|
implementation("eu.mihosoft.vrl.jcsg:jcsg:0.5.7") {
|
||||||
exclude(module = "slf4j-simple")
|
exclude(module = "slf4j-simple")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readme{
|
readme{
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
maturity = space.kscience.gradle.Maturity.PROTOTYPE
|
||||||
}
|
}
|
@ -16,7 +16,6 @@ import space.kscience.dataforge.context.*
|
|||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.boolean
|
import space.kscience.dataforge.meta.boolean
|
||||||
import space.kscience.dataforge.misc.Type
|
import space.kscience.dataforge.misc.Type
|
||||||
import space.kscience.visionforge.get
|
|
||||||
import space.kscience.visionforge.solid.FX3DFactory.Companion.TYPE
|
import space.kscience.visionforge.solid.FX3DFactory.Companion.TYPE
|
||||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
||||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_WIREFRAME_KEY
|
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_WIREFRAME_KEY
|
||||||
@ -77,7 +76,7 @@ public class FX3DPlugin : AbstractPlugin() {
|
|||||||
is PolyLine -> PolyLine3D(
|
is PolyLine -> PolyLine3D(
|
||||||
obj.points.map { Point3D(it.x, it.y, it.z) },
|
obj.points.map { Point3D(it.x, it.y, it.z) },
|
||||||
obj.thickness.toFloat(),
|
obj.thickness.toFloat(),
|
||||||
obj.properties.get(SolidMaterial.MATERIAL_COLOR_KEY).color()
|
obj.properties.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).color()
|
||||||
).apply {
|
).apply {
|
||||||
this.meshView.cullFace = CullFace.FRONT
|
this.meshView.cullFace = CullFace.FRONT
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import space.kscience.dataforge.meta.*
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.get
|
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ public class VisualObjectFXBinding(public val fx: FX3DPlugin, public val obj: Vi
|
|||||||
public operator fun get(key: Name): ObjectBinding<Meta?> {
|
public operator fun get(key: Name): ObjectBinding<Meta?> {
|
||||||
return bindings.getOrPut(key) {
|
return bindings.getOrPut(key) {
|
||||||
object : ObjectBinding<Meta?>() {
|
object : ObjectBinding<Meta?>() {
|
||||||
override fun computeValue(): Meta = obj.properties[key]
|
override fun computeValue(): Meta = obj.properties.getProperty(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
@ -13,5 +13,10 @@ kotlin {
|
|||||||
api("space.kscience:gdml:0.4.0")
|
api("space.kscience:gdml:0.4.0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
jvmTest{
|
||||||
|
dependencies{
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.2.11")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package space.kscience.visionforge.gdml
|
package space.kscience.visionforge.gdml
|
||||||
|
|
||||||
|
import space.kscience.dataforge.context.Global
|
||||||
import space.kscience.dataforge.context.info
|
import space.kscience.dataforge.context.info
|
||||||
import space.kscience.dataforge.context.logger
|
import space.kscience.dataforge.context.logger
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
@ -50,7 +51,7 @@ private fun VisionCounterTree.topToBottom(): Sequence<VisionCounterTree> = seque
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun SolidGroup.markLayers(thresholds: List<Int> = listOf(500, 1000, 20000, 50000)) {
|
public fun SolidGroup.markLayers(thresholds: List<Int> = listOf(500, 1000, 20000, 50000)) {
|
||||||
val logger = manager.context.logger
|
val logger = manager?.context?.logger ?: Global.logger
|
||||||
val counterTree = VisionCounterTree(Name.EMPTY, this, hashMapOf())
|
val counterTree = VisionCounterTree(Name.EMPTY, this, hashMapOf())
|
||||||
val totalCount = counterTree.childrenCount
|
val totalCount = counterTree.childrenCount
|
||||||
if (totalCount > (thresholds.firstOrNull() ?: 0)) {
|
if (totalCount > (thresholds.firstOrNull() ?: 0)) {
|
||||||
|
@ -26,7 +26,7 @@ class TestCubes {
|
|||||||
val smallBoxPrototype = vision.getPrototype(Name.parse("solids.smallBox")) as? Box
|
val smallBoxPrototype = vision.getPrototype(Name.parse("solids.smallBox")) as? Box
|
||||||
assertNotNull(smallBoxPrototype)
|
assertNotNull(smallBoxPrototype)
|
||||||
assertEquals(30.0, smallBoxPrototype.xSize.toDouble())
|
assertEquals(30.0, smallBoxPrototype.xSize.toDouble())
|
||||||
val smallBoxVision = vision.children["composite-111.smallBox"]?.unref as? Box
|
val smallBoxVision = vision.children["composite-111.smallBox"]?.prototype as? Box
|
||||||
assertNotNull(smallBoxVision)
|
assertNotNull(smallBoxVision)
|
||||||
assertEquals(30.0, smallBoxVision.xSize.toDouble())
|
assertEquals(30.0, smallBoxVision.xSize.toDouble())
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
val markdownVersion = "0.2.4"
|
val markdownVersion = "0.2.4"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
val plotlyVersion = "0.5.3-dev-1"
|
val plotlyVersion = "0.5.3-dev-1"
|
||||||
|
@ -16,7 +16,7 @@ import space.kscience.visionforge.root
|
|||||||
public class VisionOfPlotly private constructor() : AbstractVision() {
|
public class VisionOfPlotly private constructor() : AbstractVision() {
|
||||||
|
|
||||||
public constructor(plot: Plot) : this() {
|
public constructor(plot: Plot) : this() {
|
||||||
properties[Name.EMPTY] = plot.meta
|
properties.setProperty(Name.EMPTY, plot.meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
public val plot: Plot get() = Plot(properties.root().asObservable())
|
public val plot: Plot get() = Plot(properties.root().asObservable())
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.jvm")
|
id("space.kscience.gradle.jvm")
|
||||||
}
|
}
|
||||||
|
|
||||||
val ktorVersion = npmlibs.versions.ktor.get()
|
val ktorVersion = npmlibs.versions.ktor.get()
|
||||||
|
@ -92,6 +92,7 @@ public class VisionServer internal constructor(
|
|||||||
header()
|
header()
|
||||||
}
|
}
|
||||||
title(title)
|
title(title)
|
||||||
|
consumer.header()
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
//Load the fragment and remember all loaded visions
|
//Load the fragment and remember all loaded visions
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
kscience{
|
kscience{
|
||||||
@ -20,9 +20,14 @@ kotlin {
|
|||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
jvmTest{
|
||||||
|
dependencies{
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.2.11")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readme{
|
readme{
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
maturity = space.kscience.gradle.Maturity.DEVELOPMENT
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ public class ColorAccessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun Vision.color(): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property ->
|
public fun Vision.color(): ReadOnlyProperty<Vision, ColorAccessor> = ReadOnlyProperty { _, property ->
|
||||||
ColorAccessor(properties.root(), property.name.asName())
|
ColorAccessor(properties.root(true), property.name.asName())
|
||||||
}
|
}
|
||||||
|
|
||||||
public var ColorAccessor?.string: String?
|
public var ColorAccessor?.string: String?
|
||||||
|
@ -33,7 +33,7 @@ public inline fun MutableVisionContainer<Solid>.composite(
|
|||||||
}
|
}
|
||||||
val res = Composite(type, children[0], children[1])
|
val res = Composite(type, children[0], children[1])
|
||||||
|
|
||||||
res.properties[Name.EMPTY] = group.properties.raw
|
res.properties.setProperty(Name.EMPTY, group.properties.own)
|
||||||
|
|
||||||
set(name, res)
|
set(name, res)
|
||||||
return res
|
return res
|
||||||
@ -49,7 +49,7 @@ public fun SolidGroup.smartComposite(
|
|||||||
@VisionBuilder builder: SolidGroup.() -> Unit,
|
@VisionBuilder builder: SolidGroup.() -> Unit,
|
||||||
): Solid = if (type == CompositeType.GROUP) {
|
): Solid = if (type == CompositeType.GROUP) {
|
||||||
val group = SolidGroup(builder)
|
val group = SolidGroup(builder)
|
||||||
if (name == null && group.properties.raw == null) {
|
if (name == null && group.properties.own == null) {
|
||||||
//append directly to group if no properties are defined
|
//append directly to group if no properties are defined
|
||||||
group.items.forEach { (_, value) ->
|
group.items.forEach { (_, value) ->
|
||||||
value.parent = null
|
value.parent = null
|
||||||
|
@ -107,7 +107,7 @@ public class ExtrudeBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun build(): Extruded = Extruded(shape, layers).apply {
|
internal fun build(): Extruded = Extruded(shape, layers).apply {
|
||||||
this.properties[Name.EMPTY] = this@ExtrudeBuilder.properties
|
this.properties.setProperty(Name.EMPTY, this@ExtrudeBuilder.properties)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import space.kscience.visionforge.*
|
|||||||
public class PolyLine(public val points: List<Point3D>) : SolidBase<PolyLine>() {
|
public class PolyLine(public val points: List<Point3D>) : SolidBase<PolyLine>() {
|
||||||
|
|
||||||
//var lineType by string()
|
//var lineType by string()
|
||||||
public var thickness: Number by properties[SolidMaterial.MATERIAL_KEY].number { 1.0 }
|
public var thickness: Number by properties.getProperty(SolidMaterial.MATERIAL_KEY).number { 1.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
|
@ -170,7 +170,7 @@ internal fun float(name: Name, default: Number): ReadWriteProperty<Solid, Number
|
|||||||
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D?> =
|
internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D?> =
|
||||||
object : ReadWriteProperty<Solid, Point3D?> {
|
object : ReadWriteProperty<Solid, Point3D?> {
|
||||||
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? {
|
override fun getValue(thisRef: Solid, property: KProperty<*>): Point3D? {
|
||||||
val item = thisRef.properties.raw?.get(name) ?: return null
|
val item = thisRef.properties.own?.get(name) ?: return null
|
||||||
return object : Point3D {
|
return object : Point3D {
|
||||||
override val x: Float get() = item[X_KEY]?.float ?: default
|
override val x: Float get() = item[X_KEY]?.float ?: default
|
||||||
override val y: Float get() = item[Y_KEY]?.float ?: default
|
override val y: Float get() = item[Y_KEY]?.float ?: default
|
||||||
@ -180,7 +180,7 @@ internal fun point(name: Name, default: Float): ReadWriteProperty<Solid, Point3D
|
|||||||
|
|
||||||
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D?) {
|
override fun setValue(thisRef: Solid, property: KProperty<*>, value: Point3D?) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
thisRef.properties[name] = null
|
thisRef.properties.setProperty(name, null)
|
||||||
} else {
|
} else {
|
||||||
thisRef.properties[name + X_KEY] = value.x
|
thisRef.properties[name + X_KEY] = value.x
|
||||||
thisRef.properties[name + Y_KEY] = value.y
|
thisRef.properties[name + Y_KEY] = value.y
|
||||||
|
@ -54,7 +54,7 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable
|
|||||||
* If prototype is a ref, then it is unfolded automatically.
|
* If prototype is a ref, then it is unfolded automatically.
|
||||||
*/
|
*/
|
||||||
override fun getPrototype(name: Name): Solid? =
|
override fun getPrototype(name: Name): Solid? =
|
||||||
prototypes?.get(name)?.unref ?: (parent as? PrototypeHolder)?.getPrototype(name)
|
prototypes?.get(name)?.prototype ?: (parent as? PrototypeHolder)?.getPrototype(name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create or edit prototype node as a group
|
* Create or edit prototype node as a group
|
||||||
|
@ -99,15 +99,15 @@ public class SolidMaterial : Scheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public val Solid.color: ColorAccessor
|
public val Solid.color: ColorAccessor
|
||||||
get() = ColorAccessor(properties.root(), MATERIAL_COLOR_KEY)
|
get() = ColorAccessor(properties.root(true), MATERIAL_COLOR_KEY)
|
||||||
|
|
||||||
public var Solid.material: SolidMaterial?
|
public var Solid.material: SolidMaterial?
|
||||||
get() = SolidMaterial.read(properties[MATERIAL_KEY])
|
get() = SolidMaterial.read(properties.getProperty(MATERIAL_KEY))
|
||||||
set(value) = properties.set(MATERIAL_KEY, value?.meta)
|
set(value) = properties.setProperty(MATERIAL_KEY, value?.meta)
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
|
public fun Solid.material(builder: SolidMaterial.() -> Unit) {
|
||||||
properties[MATERIAL_KEY].updateWith(SolidMaterial, builder)
|
properties.getProperty(MATERIAL_KEY).updateWith(SolidMaterial, builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public var Solid.opacity: Number?
|
public var Solid.opacity: Number?
|
||||||
|
@ -16,9 +16,10 @@ import space.kscience.visionforge.solid.SolidReference.Companion.REFERENCE_CHILD
|
|||||||
* Get a vision prototype if it is a [SolidReference] or vision itself if it is not.
|
* Get a vision prototype if it is a [SolidReference] or vision itself if it is not.
|
||||||
* Unref is recursive, so it always returns a non-reference.
|
* Unref is recursive, so it always returns a non-reference.
|
||||||
*/
|
*/
|
||||||
public val Vision.unref: Solid
|
public val Vision.prototype: Solid
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
is SolidReference -> prototype.unref
|
is SolidReference -> prototype.prototype
|
||||||
|
is SolidReferenceChild -> prototype.prototype
|
||||||
is Solid -> this
|
is Solid -> this
|
||||||
else -> error("This Vision is neither Solid nor SolidReference")
|
else -> error("This Vision is neither Solid nor SolidReference")
|
||||||
}
|
}
|
||||||
@ -55,13 +56,13 @@ public class SolidReference(
|
|||||||
propertiesInternal = value
|
propertiesInternal = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override val raw: Meta? get() = properties
|
override val own: Meta? get() = properties
|
||||||
|
|
||||||
override fun get(name: Name, inherit: Boolean, includeStyles: Boolean): MutableMeta {
|
override fun getProperty(name: Name, inherit: Boolean?, includeStyles: Boolean?): MutableMeta {
|
||||||
return properties?.getMeta(name) ?: prototype.properties.get(name, inherit, includeStyles)
|
return properties?.getMeta(name) ?: prototype.properties.getProperty(name, inherit, includeStyles)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValue(name: Name, inherit: Boolean, includeStyles: Boolean): Value? {
|
override fun getValue(name: Name, inherit: Boolean?, includeStyles: Boolean?): Value? {
|
||||||
return properties?.getValue(name) ?: prototype.properties.getValue(name, inherit, includeStyles)
|
return properties?.getValue(name) ?: prototype.properties.getValue(name, inherit, includeStyles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,23 +106,23 @@ internal class SolidReferenceChild(
|
|||||||
override val properties: MutableVisionProperties = object : MutableVisionProperties {
|
override val properties: MutableVisionProperties = object : MutableVisionProperties {
|
||||||
override val descriptor: MetaDescriptor get() = this@SolidReferenceChild.descriptor
|
override val descriptor: MetaDescriptor get() = this@SolidReferenceChild.descriptor
|
||||||
|
|
||||||
override val raw: MutableMeta by lazy { owner.properties[childToken(childName).asName()] }
|
override val own: MutableMeta by lazy { owner.properties.getProperty(childToken(childName).asName()) }
|
||||||
|
|
||||||
override fun get(name: Name, inherit: Boolean, includeStyles: Boolean): MutableMeta =
|
override fun getProperty(name: Name, inherit: Boolean?, includeStyles: Boolean?): MutableMeta =
|
||||||
raw.getMeta(name) ?: prototype.properties.get(name, inherit, includeStyles)
|
own.getMeta(name) ?: prototype.properties.getProperty(name, inherit, includeStyles)
|
||||||
|
|
||||||
override fun getValue(
|
override fun getValue(
|
||||||
name: Name,
|
name: Name,
|
||||||
inherit: Boolean,
|
inherit: Boolean?,
|
||||||
includeStyles: Boolean,
|
includeStyles: Boolean?,
|
||||||
): Value? = raw.getValue(name) ?: prototype.properties.getValue(name, inherit, includeStyles)
|
): Value? = own.getValue(name) ?: prototype.properties.getValue(name, inherit, includeStyles)
|
||||||
|
|
||||||
override fun set(name: Name, node: Meta?) {
|
override fun setProperty(name: Name, node: Meta?) {
|
||||||
raw.setMeta(name, node)
|
own.setMeta(name, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(name: Name, value: Value?) {
|
override fun setValue(name: Name, value: Value?) {
|
||||||
raw.setValue(name, value)
|
own.setValue(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val changes: Flow<Name> get() = owner.properties.changes.filter { it.startsWith(childToken(childName)) }
|
override val changes: Flow<Name> get() = owner.properties.changes.filter { it.startsWith(childToken(childName)) }
|
||||||
|
@ -20,7 +20,7 @@ internal fun Solid.updateFrom(other: Solid): Solid {
|
|||||||
scaleX *= other.scaleX
|
scaleX *= other.scaleX
|
||||||
scaleY *= other.scaleY
|
scaleY *= other.scaleY
|
||||||
scaleZ *= other.scaleZ
|
scaleZ *= other.scaleZ
|
||||||
properties[Name.EMPTY] = other.properties.root()
|
properties.setProperty(Name.EMPTY, other.properties.root())
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package space.kscience.visionforge.solid
|
|||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.withTimeout
|
|
||||||
import space.kscience.dataforge.meta.int
|
import space.kscience.dataforge.meta.int
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
@ -26,13 +25,13 @@ class PropertyTest {
|
|||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
fun testColorUpdate() = runTest {
|
fun testColorUpdate() = runTest(dispatchTimeoutMs = 200) {
|
||||||
val box = Box(10.0f, 10.0f, 10.0f)
|
val box = Box(10.0f, 10.0f, 10.0f)
|
||||||
|
|
||||||
val c = CompletableDeferred<String?>()
|
val c = CompletableDeferred<String?>()
|
||||||
|
|
||||||
|
|
||||||
box.onPropertyChange {
|
val subscription = box.onPropertyChange(this) {
|
||||||
if (it == SolidMaterial.MATERIAL_COLOR_KEY) {
|
if (it == SolidMaterial.MATERIAL_COLOR_KEY) {
|
||||||
c.complete(box.color.string)
|
c.complete(box.color.string)
|
||||||
}
|
}
|
||||||
@ -42,8 +41,8 @@ class PropertyTest {
|
|||||||
color.set("pink")
|
color.set("pink")
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("pink", withTimeout(50) { c.await() })
|
assertEquals("pink", c.await())
|
||||||
|
subscription.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -31,7 +31,7 @@ class SerializationTest {
|
|||||||
val string = Solids.encodeToString(cube)
|
val string = Solids.encodeToString(cube)
|
||||||
println(string)
|
println(string)
|
||||||
val newCube = Solids.decodeFromString(string)
|
val newCube = Solids.decodeFromString(string)
|
||||||
assertEquals(cube.properties.raw, newCube.properties.raw)
|
assertEquals(cube.properties.own, newCube.properties.own)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -52,7 +52,7 @@ class SerializationTest {
|
|||||||
val string = Solids.encodeToString(group)
|
val string = Solids.encodeToString(group)
|
||||||
println(string)
|
println(string)
|
||||||
val reconstructed = Solids.decodeFromString(string) as SolidGroup
|
val reconstructed = Solids.decodeFromString(string) as SolidGroup
|
||||||
assertEquals(group.children["cube"]?.properties?.raw, reconstructed.children["cube"]?.properties?.raw)
|
assertEquals(group.children["cube"]?.properties?.own, reconstructed.children["cube"]?.properties?.own)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
val tablesVersion = "0.2.0-dev-3"
|
val tablesVersion = "0.2.0-dev-3"
|
||||||
@ -36,5 +36,5 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readme{
|
readme{
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
maturity = space.kscience.gradle.Maturity.PROTOTYPE
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ internal class VisionOfTableTest {
|
|||||||
val x by ColumnHeader.typed<Value>()
|
val x by ColumnHeader.typed<Value>()
|
||||||
val y by ColumnHeader.typed<Value>()
|
val y by ColumnHeader.typed<Value>()
|
||||||
|
|
||||||
val table = ColumnTable(100) {
|
val table = ColumnTable<Value>(100) {
|
||||||
x.fill { it.asValue() }
|
x.fill { it.asValue() }
|
||||||
y.values = x.values.map { it?.double?.pow(2)?.asValue() }
|
y.values = x.values.map { it?.double?.pow(2)?.asValue() }
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.js")
|
id("space.kscience.gradle.js")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin{
|
kotlin{
|
||||||
|
@ -10,7 +10,6 @@ import space.kscience.dataforge.names.asName
|
|||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.visionforge.VisionBuilder
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.get
|
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.set
|
import space.kscience.visionforge.set
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
@ -78,7 +77,7 @@ public abstract class MeshThreeFactory<in T : Solid>(
|
|||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) {
|
public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) {
|
||||||
properties.set(EDGES_ENABLED_KEY, enabled)
|
properties.set(EDGES_ENABLED_KEY, enabled)
|
||||||
SolidMaterial.write(properties[EDGES_MATERIAL_KEY]).apply(block)
|
SolidMaterial.write(properties.getProperty(EDGES_MATERIAL_KEY)).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Mesh.applyProperties(obj: Solid): Mesh = apply {
|
internal fun Mesh.applyProperties(obj: Solid): Mesh = apply {
|
||||||
@ -94,9 +93,9 @@ internal fun Mesh.applyProperties(obj: Solid): Mesh = apply {
|
|||||||
public fun Mesh.applyEdges(obj: Solid) {
|
public fun Mesh.applyEdges(obj: Solid) {
|
||||||
val edges = children.find { it.name == "@edges" } as? LineSegments
|
val edges = children.find { it.name == "@edges" } as? LineSegments
|
||||||
//inherited edges definition, enabled by default
|
//inherited edges definition, enabled by default
|
||||||
if (obj.properties.get(EDGES_ENABLED_KEY, inherit = true).boolean != false) {
|
if (obj.properties.getProperty(EDGES_ENABLED_KEY, inherit = true).boolean != false) {
|
||||||
val bufferGeometry = geometry as? BufferGeometry ?: return
|
val bufferGeometry = geometry as? BufferGeometry ?: return
|
||||||
val material = ThreeMaterials.getLineMaterial(obj.properties[EDGES_MATERIAL_KEY], true)
|
val material = ThreeMaterials.getLineMaterial(obj.properties.getProperty(EDGES_MATERIAL_KEY), true)
|
||||||
if (edges == null) {
|
if (edges == null) {
|
||||||
add(
|
add(
|
||||||
LineSegments(
|
LineSegments(
|
||||||
|
@ -11,7 +11,6 @@ import org.w3c.dom.CanvasRenderingContext2D
|
|||||||
import org.w3c.dom.CanvasTextBaseline
|
import org.w3c.dom.CanvasTextBaseline
|
||||||
import org.w3c.dom.HTMLCanvasElement
|
import org.w3c.dom.HTMLCanvasElement
|
||||||
import org.w3c.dom.MIDDLE
|
import org.w3c.dom.MIDDLE
|
||||||
import space.kscience.visionforge.get
|
|
||||||
import space.kscience.visionforge.solid.SolidLabel
|
import space.kscience.visionforge.solid.SolidLabel
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
import space.kscience.visionforge.solid.three.ThreeCanvas.Companion.DO_NOT_HIGHLIGHT_TAG
|
import space.kscience.visionforge.solid.three.ThreeCanvas.Companion.DO_NOT_HIGHLIGHT_TAG
|
||||||
@ -27,7 +26,7 @@ public object ThreeCanvasLabelFactory : ThreeFactory<SolidLabel> {
|
|||||||
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
val canvas = document.createElement("canvas") as HTMLCanvasElement
|
||||||
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
val context = canvas.getContext("2d") as CanvasRenderingContext2D
|
||||||
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
|
||||||
context.fillStyle = obj.properties[SolidMaterial.MATERIAL_COLOR_KEY].value ?: "black"
|
context.fillStyle = obj.properties.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).value ?: "black"
|
||||||
context.textBaseline = CanvasTextBaseline.MIDDLE
|
context.textBaseline = CanvasTextBaseline.MIDDLE
|
||||||
val metrics = context.measureText(obj.text)
|
val metrics = context.measureText(obj.text)
|
||||||
//canvas.width = metrics.width.toInt()
|
//canvas.width = metrics.width.toInt()
|
||||||
|
@ -4,7 +4,6 @@ import info.laht.threekt.core.BufferGeometry
|
|||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.math.Color
|
import info.laht.threekt.math.Color
|
||||||
import info.laht.threekt.objects.LineSegments
|
import info.laht.threekt.objects.LineSegments
|
||||||
import space.kscience.visionforge.get
|
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.solid.PolyLine
|
import space.kscience.visionforge.solid.PolyLine
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
@ -25,7 +24,7 @@ public object ThreeLineFactory : ThreeFactory<PolyLine> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val material = ThreeMaterials.getLineMaterial(
|
val material = ThreeMaterials.getLineMaterial(
|
||||||
obj.properties[SolidMaterial.MATERIAL_KEY],
|
obj.properties.getProperty(SolidMaterial.MATERIAL_KEY),
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,7 +10,9 @@ import space.kscience.dataforge.meta.*
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.Colors
|
||||||
|
import space.kscience.visionforge.Vision
|
||||||
|
import space.kscience.visionforge.getStyleNodes
|
||||||
import space.kscience.visionforge.solid.ColorAccessor
|
import space.kscience.visionforge.solid.ColorAccessor
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
import space.kscience.visionforge.solid.SolidReference
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
@ -129,15 +131,15 @@ private var Material.cached: Boolean
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun Mesh.updateMaterial(vision: Vision) {
|
public fun Mesh.updateMaterial(vision: Vision) {
|
||||||
val ownMaterialMeta = vision.properties.raw?.get(SolidMaterial.MATERIAL_KEY)
|
val ownMaterialMeta = vision.properties.own?.get(SolidMaterial.MATERIAL_KEY)
|
||||||
if (ownMaterialMeta == null) {
|
if (ownMaterialMeta == null) {
|
||||||
if (vision is SolidReference && vision.getStyleNodes(SolidMaterial.MATERIAL_KEY).isEmpty()) {
|
if (vision is SolidReference && vision.getStyleNodes(SolidMaterial.MATERIAL_KEY).isEmpty()) {
|
||||||
updateMaterial(vision.prototype)
|
updateMaterial(vision.prototype)
|
||||||
} else {
|
} else {
|
||||||
material = ThreeMaterials.cacheMaterial(vision.properties[SolidMaterial.MATERIAL_KEY])
|
material = ThreeMaterials.cacheMaterial(vision.properties.getProperty(SolidMaterial.MATERIAL_KEY))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
material = ThreeMaterials.buildMaterial(vision.properties[SolidMaterial.MATERIAL_KEY])
|
material = ThreeMaterials.buildMaterial(vision.properties.getProperty(SolidMaterial.MATERIAL_KEY))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,15 +154,16 @@ public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
|||||||
} else {
|
} else {
|
||||||
when (propertyName) {
|
when (propertyName) {
|
||||||
SolidMaterial.MATERIAL_COLOR_KEY -> {
|
SolidMaterial.MATERIAL_COLOR_KEY -> {
|
||||||
material.asDynamic().color = vision.properties[SolidMaterial.MATERIAL_COLOR_KEY].threeColor()
|
material.asDynamic().color = vision.properties.getProperty(SolidMaterial.MATERIAL_COLOR_KEY).threeColor()
|
||||||
?: ThreeMaterials.DEFAULT_COLOR
|
?: ThreeMaterials.DEFAULT_COLOR
|
||||||
}
|
}
|
||||||
SolidMaterial.SPECULAR_COLOR_KEY -> {
|
SolidMaterial.SPECULAR_COLOR_KEY -> {
|
||||||
material.asDynamic().specular = vision.properties[SolidMaterial.SPECULAR_COLOR_KEY].threeColor()
|
material.asDynamic().specular = vision.properties.getProperty(SolidMaterial.SPECULAR_COLOR_KEY).threeColor()
|
||||||
?: ThreeMaterials.DEFAULT_COLOR
|
?: ThreeMaterials.DEFAULT_COLOR
|
||||||
}
|
}
|
||||||
SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY -> {
|
SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY -> {
|
||||||
material.asDynamic().emissive = vision.properties[SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY].threeColor()
|
material.asDynamic().emissive = vision.properties.getProperty(SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY)
|
||||||
|
.threeColor()
|
||||||
?: ThreeMaterials.BLACK_COLOR
|
?: ThreeMaterials.BLACK_COLOR
|
||||||
}
|
}
|
||||||
SolidMaterial.MATERIAL_OPACITY_KEY -> {
|
SolidMaterial.MATERIAL_OPACITY_KEY -> {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package space.kscience.visionforge.solid.three
|
package space.kscience.visionforge.solid.three
|
||||||
|
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import space.kscience.dataforge.context.*
|
import space.kscience.dataforge.context.*
|
||||||
@ -9,7 +11,6 @@ import space.kscience.dataforge.meta.update
|
|||||||
import space.kscience.dataforge.names.*
|
import space.kscience.dataforge.names.*
|
||||||
import space.kscience.visionforge.ElementVisionRenderer
|
import space.kscience.visionforge.ElementVisionRenderer
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.onPropertyChange
|
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.visible
|
import space.kscience.visionforge.visible
|
||||||
@ -48,11 +49,11 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
|
|
||||||
public fun buildObject3D(obj: Solid): Object3D = when (obj) {
|
public fun buildObject3D(obj: Solid): Object3D = when (obj) {
|
||||||
is ThreeJsVision -> obj.render(this)
|
is ThreeJsVision -> obj.render(this)
|
||||||
is SolidReferenceGroup -> ThreeReferenceFactory.build(this, obj)
|
is SolidReference -> ThreeReferenceFactory.build(this, obj)
|
||||||
is SolidGroup -> {
|
is SolidGroup -> {
|
||||||
val group = ThreeGroup()
|
val group = ThreeGroup()
|
||||||
obj.items.forEach { (token, child) ->
|
obj.items.forEach { (token, child) ->
|
||||||
if (child is Solid && token != SolidGroup.PROTOTYPES_TOKEN && child.ignore != true) {
|
if (token != SolidGroup.PROTOTYPES_TOKEN && child.ignore != true) {
|
||||||
try {
|
try {
|
||||||
val object3D = buildObject3D(child)
|
val object3D = buildObject3D(child)
|
||||||
group[token] = object3D
|
group[token] = object3D
|
||||||
@ -67,7 +68,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
updatePosition(obj)
|
updatePosition(obj)
|
||||||
//obj.onChildrenChange()
|
//obj.onChildrenChange()
|
||||||
|
|
||||||
obj.onPropertyChange { name ->
|
obj.properties.changes.onEach { name ->
|
||||||
if (
|
if (
|
||||||
name.startsWith(Solid.POSITION_KEY) ||
|
name.startsWith(Solid.POSITION_KEY) ||
|
||||||
name.startsWith(Solid.ROTATION_KEY) ||
|
name.startsWith(Solid.ROTATION_KEY) ||
|
||||||
@ -78,10 +79,10 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
} else if (name == Vision.VISIBLE_KEY) {
|
} else if (name == Vision.VISIBLE_KEY) {
|
||||||
visible = obj.visible ?: true
|
visible = obj.visible ?: true
|
||||||
}
|
}
|
||||||
}
|
}.launchIn(context)
|
||||||
|
|
||||||
obj.onStructureChanged(this){ childName ->
|
obj.children.changes.onEach { childName ->
|
||||||
val child = get(childName)
|
val child = obj.children[childName]
|
||||||
|
|
||||||
//removing old object
|
//removing old object
|
||||||
findChild(childName)?.let { oldChild ->
|
findChild(childName)?.let { oldChild ->
|
||||||
@ -97,7 +98,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
logger.error(ex) { "Failed to render $child" }
|
logger.error(ex) { "Failed to render $child" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}.launchIn(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Composite -> compositeFactory.build(this, obj)
|
is Composite -> compositeFactory.build(this, obj)
|
||||||
|
@ -7,20 +7,21 @@ import space.kscience.dataforge.names.cutFirst
|
|||||||
import space.kscience.dataforge.names.firstOrNull
|
import space.kscience.dataforge.names.firstOrNull
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.solid.Solid
|
import space.kscience.visionforge.solid.Solid
|
||||||
import space.kscience.visionforge.solid.SolidReferenceGroup
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
import space.kscience.visionforge.solid.SolidReferenceGroup.Companion.REFERENCE_CHILD_PROPERTY_PREFIX
|
import space.kscience.visionforge.solid.SolidReference.Companion.REFERENCE_CHILD_PROPERTY_PREFIX
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public object ThreeReferenceFactory : ThreeFactory<SolidReferenceGroup> {
|
public object ThreeReferenceFactory : ThreeFactory<SolidReference> {
|
||||||
private val cache = HashMap<Solid, Object3D>()
|
private val cache = HashMap<Solid, Object3D>()
|
||||||
|
|
||||||
override val type: KClass<SolidReferenceGroup> = SolidReferenceGroup::class
|
override val type: KClass<SolidReference> = SolidReference::class
|
||||||
|
|
||||||
private fun Object3D.replicate(): Object3D {
|
private fun Object3D.replicate(): Object3D {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is Mesh -> Mesh(geometry, material).also {
|
is Mesh -> Mesh(geometry, material).also {
|
||||||
it.applyMatrix4(matrix)
|
it.applyMatrix4(matrix)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> clone(false)
|
else -> clone(false)
|
||||||
}.also { obj: Object3D ->
|
}.also { obj: Object3D ->
|
||||||
obj.name = this.name
|
obj.name = this.name
|
||||||
@ -30,7 +31,7 @@ public object ThreeReferenceFactory : ThreeFactory<SolidReferenceGroup> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(three: ThreePlugin, obj: SolidReferenceGroup): Object3D {
|
override fun build(three: ThreePlugin, obj: SolidReference): Object3D {
|
||||||
val template = obj.prototype
|
val template = obj.prototype
|
||||||
val cachedObject = cache.getOrPut(template) {
|
val cachedObject = cache.getOrPut(template) {
|
||||||
three.buildObject3D(template)
|
three.buildObject3D(template)
|
||||||
@ -39,18 +40,20 @@ public object ThreeReferenceFactory : ThreeFactory<SolidReferenceGroup> {
|
|||||||
val object3D: Object3D = cachedObject.replicate()
|
val object3D: Object3D = cachedObject.replicate()
|
||||||
object3D.updatePosition(obj)
|
object3D.updatePosition(obj)
|
||||||
|
|
||||||
if(object3D is Mesh){
|
if (object3D is Mesh) {
|
||||||
//object3D.material = ThreeMaterials.buildMaterial(obj.getProperty(SolidMaterial.MATERIAL_KEY).node!!)
|
//object3D.material = ThreeMaterials.buildMaterial(obj.getProperty(SolidMaterial.MATERIAL_KEY).node!!)
|
||||||
object3D.applyProperties(obj)
|
object3D.applyProperties(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO apply child properties
|
//TODO apply child properties
|
||||||
|
|
||||||
obj.onPropertyChange { name->
|
obj.onPropertyChange { name ->
|
||||||
if (name.firstOrNull()?.body == REFERENCE_CHILD_PROPERTY_PREFIX) {
|
if (name.firstOrNull()?.body == REFERENCE_CHILD_PROPERTY_PREFIX) {
|
||||||
val childName = name.firstOrNull()?.index?.let(Name::parse) ?: error("Wrong syntax for reference child property: '$name'")
|
val childName = name.firstOrNull()?.index?.let(Name::parse)
|
||||||
|
?: error("Wrong syntax for reference child property: '$name'")
|
||||||
val propertyName = name.cutFirst()
|
val propertyName = name.cutFirst()
|
||||||
val referenceChild = obj.children[childName] ?: error("Reference child with name '$childName' not found")
|
val referenceChild =
|
||||||
|
obj.children[childName] ?: error("Reference child with name '$childName' not found")
|
||||||
val child = object3D.findChild(childName) ?: error("Object child with name '$childName' not found")
|
val child = object3D.findChild(childName) ?: error("Object child with name '$childName' not found")
|
||||||
child.updateProperty(referenceChild, propertyName)
|
child.updateProperty(referenceChild, propertyName)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
val ktorVersion: String by rootProject.extra
|
val ktorVersion: String by rootProject.extra
|
||||||
|
Loading…
Reference in New Issue
Block a user