From ecf4a6a198133c620f9654b3703754a25fc70b82 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 13 Aug 2022 12:45:10 +0300 Subject: [PATCH] Add property flows --- .../kotlin/ru/mipt/npm/root/dRootToSolid.kt | 4 +- .../visionforge/gdml/GDMLVisionTest.kt | 4 +- demo/muon-monitor/build.gradle.kts | 1 + .../visionforge/solid/demo/VisionLayout.kt | 3 + .../kscience/visionforge/solid/demo/demo.kt | 2 + .../visionforge/solid/demo/ThreeDemoGrid.kt | 3 + .../visionforge/solid/demo/VariableBox.kt | 6 +- .../visionforge/solid/demo/FXDemoGrid.kt | 5 ++ visionforge-core/build.gradle.kts | 5 ++ .../space/kscience/visionforge/Vision.kt | 19 +--- .../kscience/visionforge/VisionChange.kt | 4 +- .../kscience/visionforge/VisionContainer.kt | 31 +++++-- .../space/kscience/visionforge/VisionGroup.kt | 29 ++++-- .../kscience/visionforge/VisionManager.kt | 6 +- .../kscience/visionforge/VisionProperties.kt | 15 +++- .../kscience/visionforge/flowProperty.kt | 55 ++++++++++++ .../space/kscience/visionforge/useProperty.kt | 54 +++++++++++ .../kscience/visionforge/html/HtmlTagTest.kt | 2 +- .../visionforge/meta/VisionPropertyTest.kt | 89 +++++++++++++++++-- .../visionforge/solid/FXReferenceFactory.kt | 2 +- .../kscience/visionforge/gdml/gdmlLoader.kt | 8 +- .../src/commonTest/kotlin/TestCubes.kt | 4 +- visionforge-solid/build.gradle.kts | 4 +- .../kscience/visionforge/solid/Composite.kt | 4 +- .../kscience/visionforge/solid/ConeSegment.kt | 6 +- .../kscience/visionforge/solid/ConeSurface.kt | 6 +- .../kscience/visionforge/solid/Convex.kt | 4 +- .../kscience/visionforge/solid/Extruded.kt | 2 +- .../kscience/visionforge/solid/Hexagon.kt | 6 +- .../kscience/visionforge/solid/LightSource.kt | 4 +- .../kscience/visionforge/solid/PolyLine.kt | 2 +- .../kscience/visionforge/solid/SolidGroup.kt | 10 +-- .../kscience/visionforge/solid/SolidLabel.kt | 4 +- .../visionforge/solid/SolidReference.kt | 8 +- .../kscience/visionforge/solid/Sphere.kt | 4 +- .../kscience/visionforge/solid/SphereLayer.kt | 4 +- .../solid/transform/RemoveSingleChild.kt | 2 +- .../visionforge/solid/transform/UnRef.kt | 8 +- .../kscience/visionforge/solid/GroupTest.kt | 6 +- .../visionforge/solid/SerializationTest.kt | 6 +- .../visionforge/solid/SolidPluginTest.kt | 6 +- .../visionforge/solid/SolidReferenceTest.kt | 6 +- .../visionforge/solid/VisionUpdateTest.kt | 8 +- visionforge-threejs/build.gradle.kts | 2 +- .../solid/three/ThreeBoxFactory.kt | 2 +- .../solid/three/ThreeCompositeFactory.kt | 2 +- .../solid/three/ThreeConeFactory.kt | 2 +- .../solid/three/ThreeConvexFactory.kt | 2 +- .../visionforge/solid/three/ThreeFactory.kt | 2 +- ...eshThreeFactory.kt => ThreeMeshFactory.kt} | 6 +- .../visionforge/solid/three/ThreePlugin.kt | 2 +- .../solid/three/ThreeReferenceFactory.kt | 2 +- .../solid/three/ThreeSphereFactory.kt | 2 +- 53 files changed, 356 insertions(+), 129 deletions(-) create mode 100644 visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/flowProperty.kt create mode 100644 visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/useProperty.kt rename visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/{MeshThreeFactory.kt => ThreeMeshFactory.kt} (96%) diff --git a/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt b/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt index a867f054..b7b79b51 100644 --- a/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt +++ b/cern-root-loader/src/commonMain/kotlin/ru/mipt/npm/root/dRootToSolid.kt @@ -352,14 +352,14 @@ private fun SolidGroup.addRootVolume( } block() } - set(combinedName?.let { Name.parse(it) }, group) + setChild(combinedName?.let { Name.parse(it) }, group) } else { val templateName = volumesName + volume.name val existing = getPrototype(templateName) if (existing == null) { context.prototypeHolder.prototypes { val group = buildVolume(volume, context) - set(templateName, group) + setChild(templateName, group) } } diff --git a/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisionTest.kt b/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisionTest.kt index 723edb3b..294af3ee 100644 --- a/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisionTest.kt +++ b/demo/gdml/src/commonTest/kotlin/space/kscience/visionforge/gdml/GDMLVisionTest.kt @@ -5,7 +5,7 @@ import space.kscience.dataforge.meta.string 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.getChild import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.SolidMaterial import space.kscience.visionforge.solid.material @@ -18,7 +18,7 @@ class GDMLVisionTest { @Test fun testCubesStyles(){ - val segment = cubes.children["composite-000.segment-0"] as Solid + val segment = cubes.children.getChild("composite-000.segment-0") as Solid println(segment.properties.getValue(Vision.STYLE_KEY)) // println(segment.computePropertyNode(SolidMaterial.MATERIAL_KEY)) // println(segment.computeProperty(SolidMaterial.MATERIAL_COLOR_KEY)) diff --git a/demo/muon-monitor/build.gradle.kts b/demo/muon-monitor/build.gradle.kts index ad37a7c2..b2c69a7d 100644 --- a/demo/muon-monitor/build.gradle.kts +++ b/demo/muon-monitor/build.gradle.kts @@ -48,6 +48,7 @@ kotlin { implementation("io.ktor:ktor-server-cio:${ktorVersion}") implementation("io.ktor:ktor-server-content-negotiation:${ktorVersion}") implementation("io.ktor:ktor-serialization-kotlinx-json:${ktorVersion}") + implementation("ch.qos.logback:logback-classic:1.2.11") } } jsMain { diff --git a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/VisionLayout.kt b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/VisionLayout.kt index 016f2ecf..9b8c6b98 100644 --- a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/VisionLayout.kt +++ b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/VisionLayout.kt @@ -3,7 +3,10 @@ package space.kscience.visionforge.solid.demo import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.Name import space.kscience.visionforge.Vision +import space.kscience.visionforge.solid.Solids public interface VisionLayout { + val solids: Solids + public fun render(name: Name, vision: V, meta: Meta = Meta.EMPTY) } \ No newline at end of file diff --git a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt index 228f63f7..88c6d154 100644 --- a/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt +++ b/demo/solid-showcase/src/commonMain/kotlin/space/kscience/visionforge/solid/demo/demo.kt @@ -5,6 +5,7 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.invoke import space.kscience.dataforge.names.Name import space.kscience.visionforge.Colors +import space.kscience.visionforge.setAsRoot import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.specifications.Canvas3DOptions import space.kscience.visionforge.visible @@ -22,6 +23,7 @@ fun VisionLayout.demo(name: String, title: String = name, block: SolidGro ambientLight{ color.set(Colors.white) } + setAsRoot(solids.visionManager) } render(Name.parse(name), vision, meta) } diff --git a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/ThreeDemoGrid.kt b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/ThreeDemoGrid.kt index 6dcfa36f..d448349c 100644 --- a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/ThreeDemoGrid.kt +++ b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/ThreeDemoGrid.kt @@ -16,6 +16,7 @@ import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.string import space.kscience.dataforge.names.Name import space.kscience.visionforge.solid.Solid +import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.three.ThreeCanvas import space.kscience.visionforge.solid.three.ThreePlugin @@ -27,6 +28,8 @@ class ThreeDemoGrid(element: Element) : VisionLayout { private val three = Global.fetch(ThreePlugin) + override val solids: Solids get() = three.solids + init { element.clear() element.append { diff --git a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt index 56221efb..e55b1c8d 100644 --- a/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt +++ b/demo/solid-showcase/src/jsMain/kotlin/space/kscience/visionforge/solid/demo/VariableBox.kt @@ -9,7 +9,7 @@ import space.kscience.dataforge.meta.number import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.startsWith import space.kscience.visionforge.onPropertyChange -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild import space.kscience.visionforge.solid.SolidGroup import space.kscience.visionforge.solid.layer import space.kscience.visionforge.solid.three.* @@ -20,7 +20,7 @@ internal fun SolidGroup.varBox( ySize: Number, name: String = "", action: VariableBox.() -> Unit = {}, -): VariableBox = VariableBox(xSize, ySize).apply(action).also { set(name, it) } +): VariableBox = VariableBox(xSize, ySize).apply(action).also { setChild(name, it) } internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision() { @@ -59,7 +59,7 @@ internal class VariableBox(val xSize: Number, val ySize: Number) : ThreeJsVision material.color.setRGB(r.toFloat() / 256, g.toFloat() / 256, b.toFloat() / 256) mesh.updateMatrix() } - name.startsWith(MeshThreeFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox) + name.startsWith(ThreeMeshFactory.EDGES_KEY) -> mesh.applyEdges(this@VariableBox) else -> mesh.updateProperty(this@VariableBox, name) } } diff --git a/demo/solid-showcase/src/jvmMain/kotlin/space/kscience/visionforge/solid/demo/FXDemoGrid.kt b/demo/solid-showcase/src/jvmMain/kotlin/space/kscience/visionforge/solid/demo/FXDemoGrid.kt index ef03092a..81501016 100644 --- a/demo/solid-showcase/src/jvmMain/kotlin/space/kscience/visionforge/solid/demo/FXDemoGrid.kt +++ b/demo/solid-showcase/src/jvmMain/kotlin/space/kscience/visionforge/solid/demo/FXDemoGrid.kt @@ -10,9 +10,11 @@ import space.kscience.dataforge.names.Name import space.kscience.visionforge.solid.FX3DPlugin import space.kscience.visionforge.solid.FXCanvas3D import space.kscience.visionforge.solid.Solid +import space.kscience.visionforge.solid.Solids import tornadofx.* class FXDemoGrid : View(title = "DataForge-vis FX demo"), VisionLayout { + private val outputs = FXCollections.observableHashMap() override val root: Parent = borderpane { @@ -24,6 +26,9 @@ class FXDemoGrid : View(title = "DataForge-vis FX demo"), VisionLayout { } private val fx3d = Global.fetch(FX3DPlugin) + override val solids: Solids get() = fx3d.solids + + override fun render(name: Name, vision: Solid, meta: Meta) { outputs.getOrPut(name) { FXCanvas3D(fx3d, canvasOptions) }.render(vision) diff --git a/visionforge-core/build.gradle.kts b/visionforge-core/build.gradle.kts index d9bf251c..a8886521 100644 --- a/visionforge-core/build.gradle.kts +++ b/visionforge-core/build.gradle.kts @@ -13,6 +13,11 @@ kotlin { api("org.jetbrains.kotlin-wrappers:kotlin-css") } } + commonTest{ + dependencies{ + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${space.kscience.gradle.KScienceVersions.coroutinesVersion}") + } + } jsMain { dependencies { api("org.jetbrains.kotlin-wrappers:kotlin-extensions") diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt index a8b590e7..aa698409 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/Vision.kt @@ -11,10 +11,8 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName -import space.kscience.dataforge.names.startsWith import space.kscience.visionforge.AbstractVisionGroup.Companion.updateProperties import space.kscience.visionforge.Vision.Companion.TYPE -import kotlin.reflect.KProperty1 /** * A root type for display hierarchy @@ -72,19 +70,4 @@ public fun Vision.onPropertyChange( callback: (Name) -> Unit ): Job = properties.changes.onEach { callback(it) -}.launchIn(scope ?: error("Orphan Vision can't observe properties")) - - -public fun V.useProperty( - property: KProperty1, - scope: CoroutineScope? = manager?.context, - callBack: V.(T) -> Unit, -): Job { - //Pass initial value. - callBack(property.get(this)) - return properties.changes.onEach { name -> - if (name.startsWith(property.name.asName())) { - callBack(property.get(this@useProperty)) - } - }.launchIn(scope ?: error("Orphan Vision can't observe properties")) -} \ No newline at end of file +}.launchIn(scope ?: error("Orphan Vision can't observe properties")) \ No newline at end of file diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt index 0e3a8dc1..29c38ebd 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionChange.kt @@ -47,7 +47,7 @@ public class VisionChangeBuilder(private val manager: VisionManager) : MutableVi } } - override fun set(name: Name?, child: Vision?) { + override fun setChild(name: Name?, child: Vision?) { if (name == null) error("Static children are not allowed in VisionChange") getOrPutChild(name).apply { vision = child @@ -109,7 +109,7 @@ private fun CoroutineScope.collectChange( if (after != null) { collectChange(fullName, after, collector) } - collector()[fullName] = after + collector().setChild(fullName, after) }?.launchIn(this) } diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionContainer.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionContainer.kt index 481a53ce..bda9ab42 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionContainer.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionContainer.kt @@ -11,12 +11,12 @@ import kotlin.jvm.Synchronized public annotation class VisionBuilder public interface VisionContainer { - public operator fun get(name: Name): V? + public fun getChild(name: Name): V? } public interface MutableVisionContainer { //TODO add documentation - public operator fun set(name: Name?, child: V?) + public fun setChild(name: Name?, child: V?) } /** @@ -33,10 +33,10 @@ public interface VisionChildren : VisionContainer { public operator fun get(token: NameToken): Vision? - override fun get(name: Name): Vision? = when (name.length) { + override fun getChild(name: Name): Vision? = when (name.length) { 0 -> group 1 -> get(name.first()) - else -> get(name.first())?.children?.get(name.cutFirst()) + else -> get(name.first())?.children?.getChild(name.cutFirst()) } public companion object { @@ -49,6 +49,10 @@ public interface VisionChildren : VisionContainer { } } +public operator fun VisionChildren.get(name: Name): Vision? = getChild(name) +public operator fun VisionChildren.get(name: String): Vision? = getChild(name) + + public fun VisionChildren.isEmpty(): Boolean = keys.isEmpty() public inline fun VisionChildren.forEach(block: (NameToken, Vision) -> Unit) { @@ -61,7 +65,7 @@ public interface MutableVisionChildren : VisionChildren, MutableVisionContainer< public operator fun set(token: NameToken, value: Vision?) - override fun set(name: Name?, child: Vision?) { + override fun setChild(name: Name?, child: Vision?) { when { name == null -> { if (child != null) { @@ -81,7 +85,7 @@ public interface MutableVisionChildren : VisionChildren, MutableVisionContainer< val parent: MutableVisionGroup = currentParent as? MutableVisionGroup ?: group.createGroup().also { set(name.first(), it) } - parent.children[name.cutFirst()] = child + parent.children.setChild(name.cutFirst(), child) } } } @@ -89,6 +93,15 @@ public interface MutableVisionChildren : VisionChildren, MutableVisionContainer< public fun clear() } +public operator fun MutableVisionChildren.set(name: Name?, vision: Vision?) { + setChild(name, vision) +} + +public operator fun MutableVisionChildren.set(name: String?, vision: Vision?) { + setChild(name, vision) +} + + /** * Add a static child. Statics could not be found by name, removed or replaced. Changing statics also do not trigger events. */ @@ -102,11 +115,11 @@ public fun VisionChildren.asSequence(): Sequence> = sequ public operator fun VisionChildren.iterator(): Iterator> = asSequence().iterator() -public operator fun VisionContainer.get(str: String): V? = get(Name.parse(str)) +public fun VisionContainer.getChild(str: String): V? = getChild(Name.parse(str)) -public operator fun MutableVisionContainer.set( +public fun MutableVisionContainer.setChild( str: String?, vision: V?, -): Unit = set(str?.parseAsName(), vision) +): Unit = setChild(str?.parseAsName(), vision) internal abstract class VisionChildrenImpl( override val group: MutableVisionGroup, diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt index 8faa21b4..613a5dfe 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionGroup.kt @@ -10,7 +10,6 @@ import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.plus import space.kscience.visionforge.Vision.Companion.STYLE_KEY -import kotlin.js.JsName public interface VisionGroup : Vision { @@ -35,9 +34,9 @@ public abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup override fun update(change: VisionChange) { change.children?.forEach { (name, change) -> when { - change.delete -> children[name] = null - change.vision != null -> children[name] = change.vision - else -> children[name]?.update(change) + change.delete -> children.setChild(name, null) + change.vision != null -> children.setChild(name, change.vision) + else -> children.getChild(name)?.update(change) } } change.properties?.let { @@ -87,12 +86,28 @@ public abstract class AbstractVisionGroup : AbstractVision(), MutableVisionGroup */ @Serializable @SerialName("vision.group") -public class SimpleVisionGroup : AbstractVisionGroup() { +public class SimpleVisionGroup : AbstractVisionGroup(), MutableVisionContainer { override fun createGroup(): SimpleVisionGroup = SimpleVisionGroup() + + override fun setChild(name: Name?, child: Vision?) { + children.setChild(name, child) + } } -@JsName("createVisionGroup") -public fun VisionGroup(): VisionGroup = SimpleVisionGroup() +@VisionBuilder +public fun MutableVisionContainer.group( + name: Name? = null, + builder: SimpleVisionGroup.() -> Unit = {}, +): SimpleVisionGroup = SimpleVisionGroup().apply(builder).also { setChild(name, it) } + +/** + * Define a group with given [name], attach it to this parent and return it. + */ +@VisionBuilder +public fun MutableVisionContainer.group( + name: String, + builder: SimpleVisionGroup.() -> Unit = {}, +): SimpleVisionGroup = SimpleVisionGroup().apply(builder).also { setChild(name, it) } //fun VisualObject.findStyle(styleName: Name): Meta? { // if (this is VisualGroup) { diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt index a6f1a7c6..314b15d5 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionManager.kt @@ -19,7 +19,7 @@ import space.kscience.visionforge.html.VisionOfNumberField import space.kscience.visionforge.html.VisionOfTextField import kotlin.reflect.KClass -public class VisionManager(meta: Meta) : AbstractPlugin(meta) { +public class VisionManager(meta: Meta) : AbstractPlugin(meta), MutableVisionContainer { override val tag: PluginTag get() = Companion.tag /** @@ -58,6 +58,10 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) { public fun encodeToMeta(vision: Vision, descriptor: MetaDescriptor? = null): Meta = encodeToJsonElement(vision).toMeta(descriptor) + override fun setChild(name: Name?, child: Vision?) { + child?.setAsRoot(this) + } + public companion object : PluginFactory { override val tag: PluginTag = PluginTag(name = "vision", group = PluginTag.DATAFORGE_GROUP) override val type: KClass = VisionManager::class diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionProperties.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionProperties.kt index 693e85bf..1f751d55 100644 --- a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionProperties.kt +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/VisionProperties.kt @@ -73,6 +73,19 @@ public interface MutableVisionProperties : VisionProperties { ) } +public fun MutableVisionProperties.remove(name: Name){ + setProperty(name, null) +} + +public fun MutableVisionProperties.remove(name: String){ + remove(name.parseAsName()) +} + +@VisionBuilder +public operator fun MutableVisionProperties.invoke(block: MutableMeta.() -> Unit) { + root(inherit = false, includeStyles = false).apply(block) +} + private class VisionPropertiesItem( val properties: MutableVisionProperties, val nodeName: Name, @@ -190,7 +203,7 @@ public abstract class AbstractVisionProperties( } @Transient - private val _changes = MutableSharedFlow(10) + private val _changes = MutableSharedFlow() override val changes: SharedFlow get() = _changes @OptIn(DelicateCoroutinesApi::class) diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/flowProperty.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/flowProperty.kt new file mode 100644 index 00000000..c8f14ae3 --- /dev/null +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/flowProperty.kt @@ -0,0 +1,55 @@ +package space.kscience.visionforge + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.Value +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.parseAsName +import space.kscience.dataforge.names.startsWith + +/** + * Create a flow of a specific property + */ +public fun Vision.flowProperty( + propertyName: Name, + inherit: Boolean? = null, + includeStyles: Boolean? = null, +): Flow = flow { + //Pass initial value. + emit(properties.getProperty(propertyName, inherit, includeStyles)) + properties.changes.collect { name -> + if (name.startsWith(propertyName)) { + emit(properties.getProperty(propertyName, inherit, includeStyles)) + } + } +} + +public fun Vision.flowProperty( + propertyName: String, + inherit: Boolean? = null, + includeStyles: Boolean? = null, +): Flow = flowProperty(propertyName.parseAsName(), inherit, includeStyles) + +/** + * Flow the value of specific property + */ +public fun Vision.flowPropertyValue( + propertyName: Name, + inherit: Boolean? = null, + includeStyles: Boolean? = null, +): Flow = flow { + //Pass initial value. + emit(properties.getValue(propertyName, inherit, includeStyles)) + properties.changes.collect { name -> + if (name.startsWith(propertyName)) { + emit(properties.getValue(propertyName, inherit, includeStyles)) + } + } +} + +public fun Vision.flowPropertyValue( + propertyName: String, + inherit: Boolean? = null, + includeStyles: Boolean? = null, +): Flow = flowPropertyValue(propertyName.parseAsName(), inherit, includeStyles) diff --git a/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/useProperty.kt b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/useProperty.kt new file mode 100644 index 00000000..b7cec960 --- /dev/null +++ b/visionforge-core/src/commonMain/kotlin/space/kscience/visionforge/useProperty.kt @@ -0,0 +1,54 @@ +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.meta.Meta +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import space.kscience.dataforge.names.parseAsName +import space.kscience.dataforge.names.startsWith +import kotlin.reflect.KProperty1 + + +/** + * Call [callBack] on initial value of the property and then on all subsequent values after change + */ +public fun Vision.useProperty( + propertyName: Name, + inherit: Boolean? = null, + includeStyles: Boolean? = null, + scope: CoroutineScope? = manager?.context, + callBack: (Meta) -> Unit, +): Job { + //Pass initial value. + callBack(properties.getProperty(propertyName, inherit, includeStyles)) + return properties.changes.onEach { name -> + if (name.startsWith(propertyName)) { + callBack(properties.getProperty(propertyName, inherit, includeStyles)) + } + }.launchIn(scope ?: error("Orphan Vision can't observe properties")) +} + +public fun Vision.useProperty( + propertyName: String, + inherit: Boolean? = null, + includeStyles: Boolean? = null, + scope: CoroutineScope? = manager?.context, + callBack: (Meta) -> Unit, +): Job = useProperty(propertyName.parseAsName(),inherit, includeStyles, scope, callBack) + +public fun V.useProperty( + property: KProperty1, + scope: CoroutineScope? = manager?.context, + callBack: V.(T) -> Unit, +): Job { + //Pass initial value. + callBack(property.get(this)) + return properties.changes.onEach { name -> + if (name.startsWith(property.name.asName())) { + callBack(property.get(this@useProperty)) + } + }.launchIn(scope ?: error("Orphan Vision can't observe properties")) +} \ No newline at end of file diff --git a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt index f72fe2bf..670f2018 100644 --- a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt +++ b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/html/HtmlTagTest.kt @@ -30,7 +30,7 @@ fun FlowContent.renderVisionFragment( @DFExperimental -private fun VisionOutput.base(block: VisionGroup.() -> Unit) = VisionGroup().apply(block) +private fun VisionOutput.base(block: VisionGroup.() -> Unit) = context.visionManager.group().apply(block) @DFExperimental class HtmlTagTest { diff --git a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/meta/VisionPropertyTest.kt b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/meta/VisionPropertyTest.kt index e7a35faa..64f0d0b2 100644 --- a/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/meta/VisionPropertyTest.kt +++ b/visionforge-core/src/commonTest/kotlin/space/kscience/visionforge/meta/VisionPropertyTest.kt @@ -1,10 +1,14 @@ package space.kscience.visionforge.meta +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectIndexed +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import space.kscience.dataforge.context.Global +import space.kscience.dataforge.context.fetch import space.kscience.dataforge.meta.* -import space.kscience.visionforge.VisionGroup -import space.kscience.visionforge.getProperty -import space.kscience.visionforge.getValue -import space.kscience.visionforge.set +import space.kscience.visionforge.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotEquals @@ -17,9 +21,12 @@ private class TestScheme : Scheme() { } internal class VisionPropertyTest { + + private val manager = Global.fetch(VisionManager) + @Test fun testPropertyWrite() { - val vision = VisionGroup() + val vision = manager.group() vision.properties["fff"] = 2 vision.properties["fff.ddd"] = false @@ -29,7 +36,7 @@ internal class VisionPropertyTest { @Test fun testPropertyEdit() { - val vision = VisionGroup() + val vision = manager.group() vision.properties.getProperty("fff.ddd").apply { value = 2.asValue() } @@ -39,10 +46,78 @@ internal class VisionPropertyTest { @Test fun testPropertyUpdate() { - val vision = VisionGroup() + val vision = manager.group() vision.properties.getProperty("fff").updateWith(TestScheme) { ddd = 2 } assertEquals(2, vision.properties.getValue("fff.ddd")?.int) } + + @Test + fun testChildrenPropertyPropagation() = runTest(dispatchTimeoutMs = 200) { + val group = Global.fetch(VisionManager).group { + properties { + "test" put 11 + } + group("child") { + properties { + "test" put 22 + } + } + } + + val child = group.children["child"]!! + + var value: Value? = null + + var callCounter = 0 + + child.useProperty("test", inherit = true) { + callCounter++ + value = it.value + } + + assertEquals(22, value?.int) + assertEquals(1, callCounter) + + child.properties.remove("test") + + //Need this to avoid the race + delay(20) + + assertEquals(11, child.properties.getProperty("test", inherit = true).int) + assertEquals(11, value?.int) + assertEquals(2, callCounter) + } + + @Test + fun testChildrenPropertyFlow() = runTest(dispatchTimeoutMs = 200) { + val group = Global.fetch(VisionManager).group { + properties { + "test" put 11 + } + group("child") { + properties { + "test" put 22 + } + } + } + + val child = group.children["child"]!! + + launch { + child.flowPropertyValue("test", inherit = true).collectIndexed { index, value -> + if (index == 0) { + assertEquals(22, value?.int) + } else if (index == 1) { + assertEquals(11, value?.int) + cancel() + } + } + } + //wait for subscription to be created + delay(10) + + child.properties.remove("test") + } } \ No newline at end of file diff --git a/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXReferenceFactory.kt b/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXReferenceFactory.kt index 60b95f9f..1c3ecb60 100644 --- a/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXReferenceFactory.kt +++ b/visionforge-fx/src/main/kotlin/space/kscience/visionforge/solid/FXReferenceFactory.kt @@ -22,7 +22,7 @@ public class FXReferenceFactory(public val plugin: FX3DPlugin) : FX3DFactory { val group: SolidGroup = volume(root, volume) - this[physVolume.name] = group.withPosition(root, physVolume) + this.setChild(physVolume.name, group.withPosition(root, physVolume)) } GdmlLoaderOptions.Action.PROTOTYPE -> { proxyVolume(root, this, physVolume, volume) @@ -357,7 +357,7 @@ private class GdmlLoader(val settings: GdmlLoaderOptions) { final.prototypes { proto.items.forEach { (token, item) -> item.parent = null - set(token.asName(), item as? Solid) + setChild(token.asName(), item as? Solid) } } settings.styleCache.forEach { @@ -385,7 +385,7 @@ public fun Gdml.toVision(block: GdmlLoaderOptions.() -> Unit = {}): SolidGroup { public fun SolidGroup.gdml(gdml: Gdml, key: String? = null, transformer: GdmlLoaderOptions.() -> Unit = {}) { val vision = gdml.toVision(transformer) //println(Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual)) - children[key] = vision + children.setChild(key, vision) } @VisionBuilder diff --git a/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt b/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt index a30cf863..aa262c45 100644 --- a/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt +++ b/visionforge-gdml/src/commonTest/kotlin/TestCubes.kt @@ -4,7 +4,7 @@ import space.kscience.dataforge.context.Context import space.kscience.dataforge.names.Name import space.kscience.gdml.* import space.kscience.visionforge.Vision -import space.kscience.visionforge.get +import space.kscience.visionforge.getChild import space.kscience.visionforge.solid.* import space.kscience.visionforge.visionManager import kotlin.test.Test @@ -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"]?.prototype as? Box + val smallBoxVision = vision.children.getChild("composite-111.smallBox")?.prototype as? Box assertNotNull(smallBoxVision) assertEquals(30.0, smallBoxVision.xSize.toDouble()) } diff --git a/visionforge-solid/build.gradle.kts b/visionforge-solid/build.gradle.kts index f794afe4..7a0f145c 100644 --- a/visionforge-solid/build.gradle.kts +++ b/visionforge-solid/build.gradle.kts @@ -1,3 +1,5 @@ +import space.kscience.gradle.KScienceVersions + plugins { id("space.kscience.gradle.mpp") } @@ -17,7 +19,7 @@ kotlin { } commonTest{ dependencies{ - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${KScienceVersions.coroutinesVersion}") } } jvmTest{ diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt index fb1b4774..1c28025c 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Composite.kt @@ -35,7 +35,7 @@ public inline fun MutableVisionContainer.composite( res.properties.setProperty(Name.EMPTY, group.properties.own) - set(name, res) + setChild(name, res) return res } @@ -57,7 +57,7 @@ public fun SolidGroup.smartComposite( } this } else { - children[name] = group + children.setChild(name, group) group } } else { diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt index 1a8e4a9d..873ae44e 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSegment.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild import kotlin.math.cos import kotlin.math.sin @@ -76,7 +76,7 @@ public inline fun MutableVisionContainer.cylinder( r.toFloat(), height.toFloat(), r.toFloat() -).apply(block).also { set(name, it) } +).apply(block).also { setChild(name, it) } @VisionBuilder public inline fun MutableVisionContainer.cone( @@ -93,4 +93,4 @@ public inline fun MutableVisionContainer.cone( topRadius = upperRadius.toFloat(), startAngle = startAngle.toFloat(), angle = angle.toFloat() -).apply(block).also { set(name, it) } \ No newline at end of file +).apply(block).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt index b5a4d5cf..0bc023e6 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/ConeSurface.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin @@ -139,7 +139,7 @@ public inline fun MutableVisionContainer.tube( topInnerRadius = innerRadius.toFloat(), startAngle = startAngle.toFloat(), angle = angle.toFloat() -).apply(block).also { set(name, it) } +).apply(block).also { setChild(name, it) } @VisionBuilder public inline fun MutableVisionContainer.coneSurface( @@ -160,4 +160,4 @@ public inline fun MutableVisionContainer.coneSurface( topInnerRadius = topInnerRadius.toFloat(), startAngle = startAngle.toFloat(), angle = angle.toFloat() -).apply(block).also { set(name, it) } \ No newline at end of file +).apply(block).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt index ad0a456e..4d50c2c4 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Convex.kt @@ -3,7 +3,7 @@ package space.kscience.visionforge.solid import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild @Serializable @SerialName("solid.convex") @@ -12,7 +12,7 @@ public class Convex(public val points: List) : SolidBase() public inline fun MutableVisionContainer.convex( name: String? = null, action: ConvexBuilder.() -> Unit = {}, -): Convex = ConvexBuilder().apply(action).build().also { set(name, it) } +): Convex = ConvexBuilder().apply(action).build().also { setChild(name, it) } public class ConvexBuilder { private val points = ArrayList() diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt index 68eded95..faec109b 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Extruded.kt @@ -115,4 +115,4 @@ public class ExtrudeBuilder( public fun MutableVisionContainer.extruded( name: String? = null, action: ExtrudeBuilder.() -> Unit = {}, -): Extruded = ExtrudeBuilder().apply(action).build().also { set(name, it) } \ No newline at end of file +): Extruded = ExtrudeBuilder().apply(action).build().also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt index b327f9bf..92f11e1b 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Hexagon.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild public interface Hexagon : GeometrySolid { public val node1: Point3D @@ -58,7 +58,7 @@ public inline fun MutableVisionContainer.box( zSize: Number, name: String? = null, block: Box.() -> Unit = {}, -): Box = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(block).also { set(name, it) } +): Box = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(block).also { setChild(name, it) } @Serializable @SerialName("solid.hexagon") @@ -85,4 +85,4 @@ public inline fun MutableVisionContainer.hexagon( node8: Point3D, name: String? = null, action: Hexagon.() -> Unit = {}, -): Hexagon = GenericHexagon(node1, node2, node3, node4, node5, node6, node7, node8).apply(action).also { set(name, it) } \ No newline at end of file +): Hexagon = GenericHexagon(node1, node2, node3, node4, node5, node6, node7, node8).apply(action).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt index 13736fcd..3db461ef 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/LightSource.kt @@ -55,7 +55,7 @@ public class AmbientLightSource : LightSource() public fun MutableVisionContainer.ambientLight( name: String? = "@ambientLight", block: AmbientLightSource.() -> Unit = {}, -): AmbientLightSource = AmbientLightSource().apply(block).also { set(name, it) } +): AmbientLightSource = AmbientLightSource().apply(block).also { setChild(name, it) } @Serializable @SerialName("solid.light.point") @@ -71,5 +71,5 @@ public fun MutableVisionContainer.pointLight( block: PointLightSource.() -> Unit = {}, ): PointLightSource = PointLightSource().apply(block).also { it.position = Point3D(x, y, z) - set(name, it) + setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt index 587e803c..4d5373b8 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/PolyLine.kt @@ -18,4 +18,4 @@ public fun MutableVisionContainer.polyline( vararg points: Point3D, name: String? = null, action: PolyLine.() -> Unit = {}, -): PolyLine = PolyLine(points.toList()).apply(action).also { set(name, it) } \ No newline at end of file +): PolyLine = PolyLine(points.toList()).apply(action).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt index 80a1129d..f3ca4cf8 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidGroup.kt @@ -38,7 +38,7 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable it to value }.toMap() - public operator fun get(name: Name): Solid? = children[name] as? Solid + public operator fun get(name: Name): Solid? = children.getChild(name) as? Solid private var prototypes: SolidGroup? get() = items[PROTOTYPES_TOKEN] as? SolidGroup @@ -70,8 +70,8 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder, Mutable // super.update(change) // } - override fun set(name: Name?, child: Solid?) { - children[name] = child + override fun setChild(name: Name?, child: Solid?) { + children.setChild(name, child) } public companion object { @@ -85,7 +85,7 @@ public inline fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup = SolidGr public fun MutableVisionContainer.group( name: Name? = null, builder: SolidGroup.() -> Unit = {}, -): SolidGroup = SolidGroup(builder).also { set(name, it) } +): SolidGroup = SolidGroup(builder).also { setChild(name, it) } /** * Define a group with given [name], attach it to this parent and return it. @@ -94,4 +94,4 @@ public fun MutableVisionContainer.group( public fun MutableVisionContainer.group( name: String, action: SolidGroup.() -> Unit = {}, -): SolidGroup = SolidGroup(action).also { set(name, it) } +): SolidGroup = SolidGroup(action).also { setChild(name, it) } diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt index 649e7f7c..2e59c1f8 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidLabel.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild @Serializable @SerialName("solid.label") @@ -21,4 +21,4 @@ public fun MutableVisionContainer.label( fontFamily: String = "Arial", name: String? = null, action: SolidLabel.() -> Unit = {}, -): SolidLabel = SolidLabel(text, fontSize.toDouble(), fontFamily).apply(action).also { set(name, it) } \ No newline at end of file +): SolidLabel = SolidLabel(text, fontSize.toDouble(), fontFamily).apply(action).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt index 51e0bc6b..76eb56aa 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SolidReference.kt @@ -97,7 +97,7 @@ internal class SolidReferenceChild( ) : Solid, VisionGroup { val prototype: Solid - get() = owner.prototype.children?.get(childName) as? Solid + get() = owner.prototype.children?.getChild(childName) as? Solid ?: error("Prototype with name $childName not found") override val descriptor: MetaDescriptor get() = prototype.descriptor @@ -137,7 +137,7 @@ internal class SolidReferenceChild( when { change.delete -> error("Deleting children inside ref is not allowed.") change.vision != null -> error("Updating content of the ref is not allowed") - else -> children[name]?.update(change) + else -> children.getChild(name)?.update(change) } } change.properties?.let { @@ -176,7 +176,7 @@ internal class SolidReferenceChild( public fun MutableVisionContainer.ref( templateName: Name, name: String? = null, -): SolidReference = SolidReference(templateName).also { set(name, it) } +): SolidReference = SolidReference(templateName).also { setChild(name, it) } public fun MutableVisionContainer.ref( templateName: String, @@ -195,7 +195,7 @@ public fun SolidGroup.newRef( val existing = prototypeHolder.getPrototype(prototypeName) if (existing == null) { prototypeHolder.prototypes { - set(prototypeName, obj) + setChild(prototypeName, obj) } } else if (existing != obj) { error("Can't add different prototype on top of existing one") diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt index 0ce0d893..ed43f663 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/Sphere.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin @@ -58,4 +58,4 @@ public inline fun MutableVisionContainer.sphere( action: Sphere.() -> Unit = {}, ): Sphere = Sphere( radius.toFloat(), -).apply(action).also { set(name, it) } \ No newline at end of file +).apply(action).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt index 709968af..bb630772 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/SphereLayer.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import space.kscience.visionforge.MutableVisionContainer import space.kscience.visionforge.VisionBuilder -import space.kscience.visionforge.set +import space.kscience.visionforge.setChild import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin @@ -85,4 +85,4 @@ public inline fun MutableVisionContainer.sphereLayer( phi.toFloat(), thetaStart.toFloat(), theta.toFloat() -).apply(action).also { set(name, it) } \ No newline at end of file +).apply(action).also { setChild(name, it) } \ No newline at end of file diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt index dc01e749..d1e6fe5a 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/RemoveSingleChild.kt @@ -39,7 +39,7 @@ internal object RemoveSingleChild : VisualTreeTransform() { val child: Solid = parent.items.values.first() val newParent = child.updateFrom(parent) newParent.parent = null - children[childName.asName()] = newParent + children.setChild(childName.asName(), newParent) } } } diff --git a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt index b78863d2..72fa1a76 100644 --- a/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt +++ b/visionforge-solid/src/commonMain/kotlin/space/kscience/visionforge/solid/transform/UnRef.kt @@ -4,14 +4,8 @@ import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.visionforge.solid.SolidGroup import space.kscience.visionforge.solid.SolidReference -import kotlin.collections.HashMap -import kotlin.collections.Map import kotlin.collections.component1 import kotlin.collections.component2 -import kotlin.collections.filter -import kotlin.collections.filterIsInstance -import kotlin.collections.fold -import kotlin.collections.forEach import kotlin.collections.set @DFExperimental @@ -33,7 +27,7 @@ internal object UnRef : VisualTreeTransform() { private fun SolidGroup.unref(name: Name) { (this as? SolidGroup)?.prototypes{ - set(name, null) + setChild(name, null) } items.filter { (it.value as? SolidReference)?.prototypeName == name }.forEach { (key, value) -> val reference = value as SolidReference diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt index 87de5c77..013a8d4c 100644 --- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/GroupTest.kt @@ -1,7 +1,7 @@ package space.kscience.visionforge.solid import space.kscience.visionforge.Colors -import space.kscience.visionforge.get +import space.kscience.visionforge.getChild import kotlin.math.PI import kotlin.test.Test import kotlin.test.assertEquals @@ -45,7 +45,7 @@ class GroupTest { } assertEquals(3, group.items.count()) - assertEquals(300.0, (group.children["intersect"] as Solid).y.toDouble()) - assertEquals(-300.0, (group.children["subtract"] as Solid).y.toDouble()) + assertEquals(300.0, (group.children.getChild("intersect") as Solid).y.toDouble()) + assertEquals(-300.0, (group.children.getChild("subtract") as Solid).y.toDouble()) } } \ No newline at end of file diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt index c2dee067..49c90dab 100644 --- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SerializationTest.kt @@ -2,7 +2,7 @@ package space.kscience.visionforge.solid import space.kscience.dataforge.names.Name import space.kscience.visionforge.Colors -import space.kscience.visionforge.get +import space.kscience.visionforge.getChild import kotlin.test.Test import kotlin.test.assertEquals @@ -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?.own, reconstructed.children["cube"]?.properties?.own) + assertEquals(group.children.getChild("cube")?.properties?.own, reconstructed.children.getChild("cube")?.properties?.own) } @Test @@ -66,7 +66,7 @@ class SerializationTest { val serialized = Solids.encodeToString(group) val reconstructed = Solids.decodeFromString(serialized) as SolidGroup - assertEquals(100.0, (reconstructed.children["@ambientLight"] as AmbientLightSource).intensity.toDouble()) + assertEquals(100.0, (reconstructed.children.getChild("@ambientLight") as AmbientLightSource).intensity.toDouble()) } } \ No newline at end of file diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPluginTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPluginTest.kt index 4ac22e1f..d60b9042 100644 --- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPluginTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidPluginTest.kt @@ -3,7 +3,7 @@ package space.kscience.visionforge.solid import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.fetch import space.kscience.dataforge.misc.DFExperimental -import space.kscience.visionforge.get +import space.kscience.visionforge.getChild import kotlin.test.Test import kotlin.test.assertEquals @@ -25,8 +25,8 @@ class SolidPluginTest { val reconstructed = visionManager.decodeFromMeta(meta) as SolidGroup assertEquals( - visionManager.encodeToJsonElement(vision.children["aBox"]!!), - visionManager.encodeToJsonElement(reconstructed.children["aBox"]!!) + visionManager.encodeToJsonElement(vision.children.getChild("aBox")!!), + visionManager.encodeToJsonElement(reconstructed.children.getChild("aBox")!!) ) } } \ No newline at end of file diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt index f74426ba..027f8b03 100644 --- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/SolidReferenceTest.kt @@ -3,7 +3,7 @@ package space.kscience.visionforge.solid import kotlinx.serialization.json.encodeToJsonElement import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.get -import space.kscience.visionforge.get +import space.kscience.visionforge.getChild import space.kscience.visionforge.style import space.kscience.visionforge.useStyle import kotlin.test.Test @@ -24,7 +24,7 @@ class SolidReferenceTest { @Test fun testReferenceProperty(){ - assertEquals("blue", (groupWithReference.children["test"] as Solid).color.string) + assertEquals("blue", (groupWithReference.children.getChild("test") as Solid).color.string) } @Test @@ -32,6 +32,6 @@ class SolidReferenceTest { val serialized = Solids.jsonForSolids.encodeToJsonElement(groupWithReference) val deserialized = Solids.jsonForSolids.decodeFromJsonElement(SolidGroup.serializer(), serialized) assertEquals(groupWithReference.items["test"]?.color.string, deserialized.items["test"]?.color.string) - assertEquals("blue", (deserialized.children["test"] as Solid).color.string) + assertEquals("blue", (deserialized.children.getChild("test") as Solid).color.string) } } \ No newline at end of file diff --git a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt index e5a13594..2cf5c861 100644 --- a/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt +++ b/visionforge-solid/src/commonTest/kotlin/space/kscience/visionforge/solid/VisionUpdateTest.kt @@ -6,7 +6,7 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.asValue import space.kscience.dataforge.names.asName import space.kscience.visionforge.VisionChange -import space.kscience.visionforge.get +import space.kscience.visionforge.getChild import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -29,9 +29,9 @@ internal class VisionUpdateTest { propertyChanged("origin".asName(), SolidMaterial.MATERIAL_COLOR_KEY, Meta("red".asValue())) } targetVision.update(dif) - assertTrue { targetVision.children["top"] is SolidGroup } - assertEquals("red", (targetVision.children["origin"] as Solid).color.string) // Should work - assertEquals("#00007b", (targetVision.children["top"] as Solid).color.string) // new item always takes precedence + assertTrue { targetVision.children.getChild("top") is SolidGroup } + assertEquals("red", (targetVision.children.getChild("origin") as Solid).color.string) // Should work + assertEquals("#00007b", (targetVision.children.getChild("top") as Solid).color.string) // new item always takes precedence } @Test diff --git a/visionforge-threejs/build.gradle.kts b/visionforge-threejs/build.gradle.kts index d9d0f96d..86b8702c 100644 --- a/visionforge-threejs/build.gradle.kts +++ b/visionforge-threejs/build.gradle.kts @@ -10,6 +10,6 @@ kotlin{ dependencies { api(project(":visionforge-solid")) - implementation(npm("three", "0.137.4")) + implementation(npm("three", "0.137.5")) implementation(npm("three-csg-ts", "3.1.10")) } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt index a5b50688..f66492ed 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeBoxFactory.kt @@ -4,7 +4,7 @@ import info.laht.threekt.geometries.BoxGeometry import space.kscience.visionforge.solid.Box import space.kscience.visionforge.solid.detail -public object ThreeBoxFactory : MeshThreeFactory(Box::class) { +public object ThreeBoxFactory : ThreeMeshFactory(Box::class) { override fun buildGeometry(obj: Box): BoxGeometry = obj.detail?.let { detail -> BoxGeometry(obj.xSize, obj.ySize, obj.zSize, detail, detail, detail) diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt index 4bd9826c..de318f95 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeCompositeFactory.kt @@ -50,7 +50,7 @@ public class ThreeCompositeFactory(public val three: ThreePlugin) : ThreeFactory obj.onPropertyChange { name -> when { //name.startsWith(WIREFRAME_KEY) -> mesh.applyWireFrame(obj) - name.startsWith(MeshThreeFactory.EDGES_KEY) -> applyEdges(obj) + name.startsWith(ThreeMeshFactory.EDGES_KEY) -> applyEdges(obj) else -> updateProperty(obj, name) } } diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt index 5789c30e..8eed04ae 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConeFactory.kt @@ -7,7 +7,7 @@ import space.kscience.visionforge.solid.detail import kotlin.math.PI import kotlin.math.pow -public object ThreeConeFactory : MeshThreeFactory(ConeSegment::class) { +public object ThreeConeFactory : ThreeMeshFactory(ConeSegment::class) { override fun buildGeometry(obj: ConeSegment): BufferGeometry { val cylinder = obj.detail?.let { val segments = it.toDouble().pow(0.5).toInt() diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt index fe08b1cf..2ab67219 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeConvexFactory.kt @@ -3,7 +3,7 @@ package space.kscience.visionforge.solid.three import info.laht.threekt.external.geometries.ConvexBufferGeometry import space.kscience.visionforge.solid.Convex -public object ThreeConvexFactory : MeshThreeFactory(Convex::class) { +public object ThreeConvexFactory : ThreeMeshFactory(Convex::class) { override fun buildGeometry(obj: Convex): ConvexBufferGeometry { val vectors = obj.points.map { it.toVector() }.toTypedArray() return ConvexBufferGeometry(vectors) diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt index 3397ea96..8c39aeb3 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeFactory.kt @@ -75,7 +75,7 @@ public fun Object3D.updateProperty(source: Vision, propertyName: Name) { /** * Generic factory for elements which provide inside geometry builder */ -public object ThreeShapeFactory : MeshThreeFactory(GeometrySolid::class) { +public object ThreeShapeFactory : ThreeMeshFactory(GeometrySolid::class) { override fun buildGeometry(obj: GeometrySolid): BufferGeometry = ThreeGeometryBuilder().apply { obj.toGeometry(this) }.build() diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/MeshThreeFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt similarity index 96% rename from visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/MeshThreeFactory.kt rename to visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt index 9309848f..ea39bbea 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/MeshThreeFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeMeshFactory.kt @@ -15,14 +15,14 @@ import space.kscience.visionforge.set import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.SolidMaterial import space.kscience.visionforge.solid.layer -import space.kscience.visionforge.solid.three.MeshThreeFactory.Companion.EDGES_ENABLED_KEY -import space.kscience.visionforge.solid.three.MeshThreeFactory.Companion.EDGES_MATERIAL_KEY +import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_ENABLED_KEY +import space.kscience.visionforge.solid.three.ThreeMeshFactory.Companion.EDGES_MATERIAL_KEY import kotlin.reflect.KClass /** * Basic geometry-based factory */ -public abstract class MeshThreeFactory( +public abstract class ThreeMeshFactory( override val type: KClass, ) : ThreeFactory { /** diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt index 2fe9585c..7c1358d7 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreePlugin.kt @@ -82,7 +82,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer { }.launchIn(context) obj.children.changes.onEach { childName -> - val child = obj.children[childName] + val child = obj.children.getChild(childName) //removing old object findChild(childName)?.let { oldChild -> diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt index 27657931..ade11074 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeReferenceFactory.kt @@ -53,7 +53,7 @@ public object ThreeReferenceFactory : ThreeFactory { ?: 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") + obj.children.getChild(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 { diff --git a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt index 8932a6c8..9d4926c5 100644 --- a/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt +++ b/visionforge-threejs/src/main/kotlin/space/kscience/visionforge/solid/three/ThreeSphereFactory.kt @@ -5,7 +5,7 @@ import info.laht.threekt.geometries.SphereGeometry import space.kscience.visionforge.solid.Sphere import space.kscience.visionforge.solid.detail -public object ThreeSphereFactory : MeshThreeFactory(Sphere::class) { +public object ThreeSphereFactory : ThreeMeshFactory(Sphere::class) { override fun buildGeometry(obj: Sphere): BufferGeometry { return obj.detail?.let {detail -> SphereGeometry(