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